前两章我们简单讲解了SpringBoot的易用性,SpringBoot框架内部提供了很多我们需要用到的组件,需要什么你就可以拿到项目里。
在我们平时的项目中,数据的存储以及访问都是最为核心的关键部分,现在有很多企业采用主流的数据库,如关系型数据库:MySQL,oracle,sqlserver。非关系型数据库:redis,mongodb等。
SpringBoot已经为我们提供了很多种的数据库来做数据存储以及读取,上面只是简单的几种,那么我接下来以MySQL为例来讲述下本章的内容。
本章目标
学习并且使用SpringBoot访问MySQL数据库,并且结合SpringDataJPA完成CRUD(Create,Read,Update,Delete)简单操作。
构建项目
接下来我们先来创建SpringBoot项目,如下图1所示:

点击Next输入一些项目参数,如下图2所示:

点击Next后选择我们需要导入项目的SpringBoot组件,这里要注意一定要选择正确的组件,如下图3所示:

可以看到图3我们选择了,web,MySQL,JPA组件作为我们开发必备组件,我们点击Next输入项目名称后进入项目窗口,如下图4所示:

我们打开pom.xml可以看到springboot自动为我们添加了spring-data-jpa、mysql-connector-java的支持,如下图5所示:

上图的注释是我添加的,项目默认创建完成后是没有注释的。
注意:如果使用内部tomcat运行项目需要将spring-boot-starter-tomcat的scope标签注释掉。
配置数据源以及JPA
今后我们修改application.properties文件配置为application.yml配置。.yml配置文件与.properties配置要更清晰更有层次感,可以很明了的看懂配置信息。
我们在resources目录下创建application.yml文件,并且配置DataSource以及JPA,如下图6所示:

可以看到上述配置文件内,我们使用了本地的一个mysql数据库,mysql数据库是我们事先安装好的,并且创建了一个名叫test的数据库,JPA的配置了show-sql用来在控制台输出JPA自动生成的sql语句。
上述数据配置文件已经完成,接下来我们新建数据库测试表结构我使用的数据库工具是Navicat你们可自行下载或者使用其他工具,结构如下图7所示:

创建表语句我会放到resources目录下,请大家到文档地址下载对应课程源码。
接下来我们开始编写springmvc控制器以及实体类,我们采用@RestController注解来编写一个控制器,如下图8所示:

创建实体
我们根据数据库中的字段对应创建一个UserEntity来作为对应操作,如下图9所示:

可以看到图9中我们使用到了很多注解,关于注解的具体含义我们放到下面章节中具体讲解。
创建JPA
既然实体类我们也已经创建完成了,那么接下来我们需要使用SpringDataJPA来完成数据库操作,我们新建名字叫做jpa的package,然后创建UserJPA接口并且继承SpringDataJPA内的接口作为父类,如下图10所示:

我们UserJPA继承了JpaRepository接口(SpringDataJPA提供的简单数据操作接口)、JpaSpecificationExecutor(SpringDataJPA提供的复杂查询接口)、Serializable(序列化接口)。
我们并不需要做其他的任何操作了,因为SpringBoot以及SpringDataJPA会为我们全部搞定,SpringDataJPA内部使用了类代理的方式让继承了它接口的子接口都以spring管理的Bean的形式存在,也就是说我们可以直接使用@Autowired注解在spring管理bean使用,如下图11所示:

到这一步我们的数据库层几乎已经编写完成了,那么我们需要编写控制器让我们通过页面可以访问到数据。
编写查询方法
我们回到UserController中,然后创建一个查询用户列表的方法,如下图12所示:

其中userJps.findAll()方法就是SpringDataJPA为我们提供的内置方法,它可以查询表内所有的数据,除了findAll还有很多有用的方法,我们后期使用一章的内容来详细介绍这个强大的家伙!
编写添加、更新方法

可以看到上图13中,我们只是简单的实现实体的持久化操作,userJPA.save方法可以执行添加也可以执行更新,如果需要执行持久化的实体存在主键值则更新数据,如果不存在则添加数据。
编写删除方法

我们删除完用户后直接返回了用户列表,可以查看到用户是否已经删除成功。
初尝试运行项目
具体如何运行项目请到LessonTwo去阅读,下面我们可以看到项目是正常运行的如下图15所示:

我红色标记的部分可以看到,springmvc加载了我定义的请求。那么我们尝试访问用户列表路径:127.0.0.1:8080/user/list可以看到如下图16所示,因为我们数据库中并没有数据,所以我们没有查询到结果:

可以看下IntelliJ IDEA工具控制台输出的语句:
Hibernate: select userentity0_.t_id as t_id1_0_, userentity0_.t_address as t_addres2_0_, userentity0_.t_age as t_age3_0_, userentity0_.t_name as t_name4_0_ from t_user userentity0_
因为我们没有设置格式化sql所以生成的sql语句都是一行显示的。
添加更新用户
我们现在添加一条用户信息到数据库,请求地址:http://127.0.0.1:8080/user/save?name=admin&age=22&address=jinan,效果如下图17所示:

可以看到我们成功的添加了一条数据,并且用户数据主键编号也返回了,我们在执行参数中并没有添加id的值,这个id是数据库自动生成的,springDataJPA查询成功后会自动返回主键的值到实体主键映射字段中。
多插入几条数据方便我们下一步操作,插入完成后我们再次访问用户列表请求地址,效果如下图18所示:

上图18我们查询出了数据库中的所有用户数据,那么我们接下来更新下主键编号为1的用户信息,我们把age以及address分别改成,23,beijing,效果如下图19所示:

我们可以看到,在访问地址的时候我并没有传name字段的值,那么springDataJPA会认为你要清空name字段的值所以这样访问是不可以的,我们需要将name也传入,效果如下图20所示:

可以看到上图20,更新用户的name属性是有值得。你们可自行访问用户列表地址查询是否已经更新,我这里就不做演示了。
删除用户
我们可以根据用户的主键来删除一条数据,如下图21所示:

我们可以看到我传入的id=1,删除完成后我们自动读取了用户列表,springDataJPA给我们没有返回id=1的用户,我们查看数据库数据也没有发现id=1用户,证明id=1的用户确实已经被从数据库中删除了。
总结
上述内容就是我们本章的全部内容,主要讲述了springboot整合mysql并且使用SpringDataJPA来完成数据库的CRUD操作。
因为我们是接着上一章的内容讲解的,如果你有不明白的地方可以去查看我的第二章:SpringBoot与JSP间不可描述的秘密。
本章内容已经更新到码云,请大家下载学习:
SpringBoot配套源码地址:https://gitee.com/hengboy/spring-boot-chapter
SpringCloud配套源码地址:https://gitee.com/hengboy/spring-cloud-chapter
SpringBoot相关系列文章请访问:目录:SpringBoot学习目录
QueryDSL相关系列文章请访问:QueryDSL通用查询框架学习目录
SpringDataJPA相关系列文章请访问:目录:SpringDataJPA学习目录
SpringBoot相关文章请访问:目录:SpringBoot学习目录,感谢阅读!
欢迎加入QQ技术交流群,共同进步。

网友评论
public UserEntity save(@RequestParam(value = "name") String name,
@RequestParam(value = "age") int age,
@RequestParam(value = "address") String address) {
UserEntity Entity=new UserEntity();
Entity.setT_name(name);
Entity.setT_age(age);
Entity.setT_address(address);
return userJpa.save(Entity);
}
这是我改的save方法,需要用RequestParam获取参数,请问不用RequestParam是怎么实现参数获取的?
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'test.hibernate_sequence' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
in 'reader', line 2, column 2:
datasource:
^
expected <block end>, but found BlockMappingStart
in 'reader', line 7, column 3:
jpa:
求解~~~~~~~~~~~~~~~~~~~~~~~~
^
datasource:
url: jdbc:mysql://localhost:3306/content?characterEncoding=utf8
driverClassName: com.mysql.jdbc.Driver
username: root
password: 123456
jpa:
database: MySQL
show-sql: true
hibernate:
naming_strategy: org.hibernate.cfg.improvedNamingStrategy
感觉没有重复啊
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userJPA in com.example.demo.controller.UserController required a bean of type 'com.example.demo.jpa.UserJPA' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.jpa.UserJPA' in your configuration.
发现掉进了了spring boot1.5 和2.0的坑。
2018-07-23 10:55:56.449 INFO 1687048 --- [ main] com.snowy.Lesson03Application : No active profile set, falling back to default profiles: default
2018-07-23 10:55:56.534 INFO 1687048 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@3835c46: startup date [Mon Jul 23 10:55:56 CST 2018]; root of context hierarchy
2018-07-23 10:55:58.311 INFO 1687048 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2018-07-23 10:55:58.566 INFO 1687048 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2018-07-23 10:55:58.605 INFO 1687048 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for .
public interface MydbDAO extends CrudRepository<Mydb, Integer>, Serializable {
}
public class MydbService {
@Autowired
private MydbDAO mydbDAO;
}
报错:
org.springframework.web.context.ContextLoader.initWebApplicationContext Context initialization failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mydbService': Unsatisfied dependency expressed through field 'mydbDAO'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.concretepage.dao.MydbDAO' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:587)
java.lang.NullPointerException: null
at com.example.demo.entity.UserEntity.getId(UserEntity.java:36) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
at org.springframework.beans.BeanWrapperImpl$BeanPropertyHandler.getValue(BeanWrapperImpl.java:308) ~[spring-beans-5.0.7.RELEASE.jar:5.0.7.RELEASE]
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
TABLE:使用一个特定的数据库表格来保存主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
IDENTITY:主键由数据库自动生成(主要是自动增长型)
AUTO:主键由程序控制。
Caused by: java.sql.SQLFeatureNotSupportedException: 这个 org.postgresql.jdbc.PgConnection.createClob() 方法尚未被实作。
at org.postgresql.Driver.notImplemented(Driver.java:683) ~[postgresql-42.2.2.jar:42.2.2]
at org.postgresql.jdbc.PgConnection.createClob(PgConnection.java:1252) ~[postgresql-42.2.2.jar:42.2.2]
2018-06-27 11:35:39.414 ERROR 13224 --- [ main] o.apache.catalina.core.StandardService : Failed to start connector [Connector[HTTP/1.1-8080]]
Caused by: org.apache.catalina.LifecycleException: Protocol handler start failed
Caused by: java.net.BindException: Address already in use: bind
望赐教
jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=true 和
jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&useSSL=false已经试过,仍不可连接成功
应该改为 userJPA.deleteById(id);
http://localhost:8080/user/save?name=xiaowu&;age=18&address=北京
出现了sql错误:
java.sql.SQLException: Incorrect string value: '\xE5\x8C\x97\xE4\xBA\xAC...' for column 't_address' at row 1
我记得以前是可以的呀。
我去网上百度了一下,还真是这个原因。
解决办法:http://www.cnblogs.com/wangjikun/p/5687370.html
楼主,你是故意挖的这个坑的吗?欺负我MySQL用的不熟
Hibernate: select next_val as id_val from hibernate_sequence for update
2018-05-31 18:12:44.747 ERROR 9100 --- [nio-8080-exec-2] o.hibernate.id.enhanced.TableStructure : could not read a hi value
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'td_clotherp.hibernate_sequence' doesn't exist
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_121]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_121]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_121]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_121]
不知道,这个问题是什么错误
@ID
@GeneratedValue(strategy = GenerationType.IDENTITY)
@column(name = "t_id")
private Long id;
实体里面得@GeneratedValue注解后面还得加上设置自增主键得备注
C:\Users\Administrator\Downloads\新建文件夹 (11)\imooc-o2o-master\demo11\src\main\java\com\example\demo11\controller\UserController.java
Error:(32, 24) java: 不兼容的类型: java.lang.Long无法转换为com.example.demo11.entity.UserEntity
url: jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf8&useSSL=true
@GeneratedValue(strategy = GenerationType.IDENTITY)//请问楼主你不写括号里这句
//怎么实现添加成功的?
@column(name = "t_id")
private Long id;
不能添加指定新的id
直接不写 id 会报错!
There was an unexpected error (type=Internal Server Error, status=500).
error performing isolated work; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: error performing isolated work
Hibernate升到5.1版本,之前的hibernate.ejb.naming_strategy将不再被支持,而是被替换成了两个属性:
implicit naming strategy:隐式命名策略,使用此属性当我们使用的表或列没有明确指定一个使用的名称 。
physical naming strategy:物理命名策略,用于转换“逻辑名称”(隐式或显式)的表或列成一个物理名称。
对于PhysicalNamingStrategyStandardImpl有DefaultNamingStrategy的效果;对于SpringPhysicalNamingStrategy 有ImprovedNamingStrategy的效果。
`t_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`t_name` VARCHAR(30) NULL DEFAULT NULL COMMENT '名称',
`t_age` INT(10) NULL DEFAULT NULL COMMENT '年龄',
`t_address` VARCHAR(100) NULL DEFAULT NULL COMMENT '家庭住址',
PRIMARY KEY (`t_id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
看到楼主的文章,着实受教了