工具:idea 2019.1 gradle: 5.2.1 SpringBoot 2.1.5
JPA的功能十分强大,并且使用简单,将很多常用的SQL语句都封装了起来,并且,它还可以根据你方法的名称来执行相应的SQL语句。接下来就来看一下,JPA在SpringBoot中怎么使用吧。
新建立一个SpringBoot项目,在build.gradle 里面添加相应的依赖,web包和JPA包
build.gradle
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' //runtimeOnly 'mysql:mysql-connector-java' 因为SpringBoot默认引入的是较高版本8.X 的MySQL,但是我电脑上安装的MySQL只有5.X,可能会不兼容,会报 CLIENT_PLUGIN_AUTH is required // https://mvnrepository.com/artifact/mysql/mysql-connector-java compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.38' testImplementation 'org.springframework.boot:spring-boot-starter-test' }往application.properties中配置数据源,JPA等
application.properties
#配置数据源 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql:///user?characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=root spring.jpa.hibernate.ddl-auto=update # 他的各种属性 # create: 会在程序启动时,新建表,如果有了表会先删除,再新建 # update: 会在程序启动时,如果没有表,会新建表,有表的话,不会删除,只会更新其中的数据 # create-drop:会在程序结束的时候,删除表 # validate:运行程序会校验数据与数据库的字段类型是否相同,不同会报错 # 参考: https://blog.csdn.net/zhangtongpeng/article/details/79609942《spring-boot工程中,jpa下hibernate的ddl-auto的各种属性》 spring.jpa.show-sql=true # 在控制台打印SQL语句,调试的时候好用一点 spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect # 指定使用innnoDB来作为数据库引擎, 在 SrpingBoot 2.0 版本中, # Hibernate 创建数据表的时候,默认的数据库存储引擎选择的是 MyISAM (之前好像是 InnoDB,这点比较诡异)。 # 这个参数是在建表的时候,将默认的存储引擎切换为 InnoDB 用的。 # 参考:https://www.jianshu.com/p/c14640b63653 SpringBoot 中 JPA 的使用在包下面添加control、service,repository,model包
分别放,controller层,service层、dao层,和model层代码
Student.java
package com.example.springbootjpa.model; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity(name = "student") public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private String gender; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User{" + "id=" + id + ", name=" + name + ", age=" + age + '}'; } }@Entity表示这是一个实体类,可在后面指定这个实体类对应的表名,还有一种是使用@Table来指定。其中@Id的作用是,指定这一张表的id字段,下面的@GeneratedValue是放在id字段上的一个注解,如果设置了strategy = GenerationType.IDENTITY,表示这个主键是自动递增的。GenerationType一共有四个值,各有各的意思。 具体可参考:https://www.cnblogs.com/sgh1023/p/10231941.html 这篇写的比较详细。 @Column 如果不加,则表示使用当前的属性名作为标的字段名,长度什么的采用默认的方式。也可以选择添加了之后,使用自己的设置,@Column(length=20)等。 实体类设置好之后,启动项目。等到启动完毕,我们mysql中,查看到多了一个student表,并且id是自增的。但是他建出来的表的字段顺序不是按照你实体类中的顺序来的。 这就是使用JPA的好处之一,但是表里面还是没有数据,需要自己添加。但是也是省了自己建表的时间,如果表比较多的话,也是会花费挺长时间的。 之后我们往里面添加几条记录,使用SQL语句插入
INSERT INTO student(id, name, gender, age) VALUES ('1', '薛之谦', '男', '18'); INSERT INTO student(id, name, gender, age) VALUES ('2', '何炅', '男', '18'); INSERT INTO student(id, name, gender, age) VALUES ('3', '撒微笑', '男', '20'); INSERT INTO student(id, name, gender, age) VALUES ('4', '何美男', '男', '18'); INSERT INTO student(id, name, gender, age) VALUES ('5', '欧校花', '女', '18'); INSERT INTO student(id, name, gender, age) VALUES ('6', '毛不易', '男', '22'); INSERT INTO student(id, name, gender, age) VALUES ('7', '大天师', '男', '22'); INSERT INTO student(id, name, gender, age) VALUES ('8', '白bra', '男', '22');你也可以使用之后建立的StudentRepository.java里面的方法来添加记录
StudentRepository.java
package com.example.springbootjpa.repository; import com.example.springbootjpa.model.Student; import org.springframework.data.jpa.repository.JpaRepository; public interface StudentRepository extends JpaRepository<Student, Integer> { }这里添加dao层就比较简单了,只需要继承JpaRepository<T, ID>就行了,其中的泛型T是指当前的dao对应的实体类是哪个,后面的泛型ID指的是这个实体类的ID的类型 继承之后,我们就可以使用这个类去调用很多的方法。
这些是比较常用的CRUD方法,但是它最厉害的地方在于,他可以通过你方法的名字来组合你所需要的SQL语句,比如findByName(String name),它能生成一条select * from xxxx where name = ?的 SQL语句
还有像其他的like, and, or等都能使用
KeywordSampleJPQL snippetAndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2Is,EqualsfindByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2LessThanfindByAgeLessThan… where x.age < ?1LessThanEqualfindByAgeLessThanEqual… where x.age ⇐ ?1GreaterThanfindByAgeGreaterThan… where x.age > ?1GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1AfterfindByStartDateAfter… where x.startDate > ?1BeforefindByStartDateBefore… where x.startDate < ?1IsNullfindByAgeIsNull… where x.age is nullIsNotNull,NotNullfindByAge(Is)NotNull… where x.age not nullLikefindByFirstnameLike… where x.firstname like ?1NotLikefindByFirstnameNotLike… where x.firstname not like ?1StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname descNotfindByLastnameNot… where x.lastname <> ?1InfindByAgeIn(Collection ages)… where x.age in ?1NotInfindByAgeNotIn(Collection age)… where x.age not in ?1TRUEfindByActiveTrue()… where x.active = trueFALSEfindByActiveFalse()… where x.active = falseIgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1) (表格来自 纯洁的微笑 博客 http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html )
也可以在Repository中自己写接口方法,在接口方法上使用@Query注解来写自己的SQL查询语句,如果涉及到修改或者删除需要添加@Modify注解,并且不支持insert操作,如果想要使用insert操作需要使用原生SQL语句。还可以添加事务的支持@Transactional
原生SQL
@Query(value = "insert into stuent(id, name, gender, age) values(#{id}, #{name}, #{gender}, #{age}})", nativeQuery = true) public void testInsert(Student student);参数的使用可以使用索引的方式,在相应的位置使用?1, ?2, ?3等来表示第几个参数,这种方式可以不用添加@Param注解。也可以使用参数名的方式,在相应的位置使用 :+@Param 注解中的值,比如:name, :age等
添加service层和control层
StudentController.java
package com.example.springbootjpa.control; import com.example.springbootjpa.model.Student; import com.example.springbootjpa.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class StudentController { @Autowired private StudentService studentService; @RequestMapping("/findAll") public List<Student> findAll(){ return studentService.findAll(); } }StudentService.java
package com.example.springbootjpa.service; import com.example.springbootjpa.model.Student; import com.example.springbootjpa.repository.StudentRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class StudentService { @Autowired private StudentRepository studentRepository; public List<Student> findAll(){ return studentRepository.findAll(); } }启动之后,访问localhost:8080/findAll,会得到如下效果
其余方法的测试,可以自己去尝试。