工具:idea 2019.1
gradle: 5.2.1
SpringBoot 2.1.5
JPA的功能十分强大,并且使用简单,将很多常用的SQL语句都封装了起来,并且,它还可以根据你方法的名称来执行相应的SQL语句。接下来就来看一下,JPA在SpringBoot中怎么使用吧。
1. 新建项目
新建立一个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'
}
2. 添加配置
往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 的使用
3. 添加包和类
在包下面添加control
、service
,repository
,model
包
分别放,controller
层,service
层、dao
层,和model
层代码
3.1 添加一个实体类
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
里面的方法来添加记录
3.2 添加dao层,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
等都能使用
Keyword | Sample | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | … where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | … where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals | findByFirstnameIs,findByFirstnameEquals | … where x.firstname = ?1 |
Between | findByStartDateBetween | … where x.startDate between ?1 and ?2 |
LessThan | findByAgeLessThan | … where x.age < ?1 |
LessThanEqual | findByAgeLessThanEqual | … where x.age ⇐ ?1 |
GreaterThan | findByAgeGreaterThan | … where x.age > ?1 |
GreaterThanEqual | findByAgeGreaterThanEqual | … where x.age >= ?1 |
After | findByStartDateAfter | … where x.startDate > ?1 |
Before | findByStartDateBefore | … where x.startDate < ?1 |
IsNull | findByAgeIsNull | … where x.age is null |
IsNotNull,NotNull | findByAge(Is)NotNull | … where x.age not null |
Like | findByFirstnameLike | … where x.firstname like ?1 |
NotLike | findByFirstnameNotLike | … where x.firstname not like ?1 |
StartingWith | findByFirstnameStartingWith | … where x.firstname like ?1 (parameter bound with appended %) |
EndingWith | findByFirstnameEndingWith | … where x.firstname like ?1 (parameter bound with prepended %) |
Containing | findByFirstnameContaining | … where x.firstname like ?1 (parameter bound wrapped in %) |
OrderBy | findByAgeOrderByLastnameDesc | … where x.age = ?1 order by x.lastname desc |
Not | findByLastnameNot | … where x.lastname <> ?1 |
In | findByAgeIn(Collection ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection age) | … where x.age not in ?1 |
TRUE | findByActiveTrue() | … where x.active = true |
FALSE | findByActiveFalse() | … where x.active = false |
IgnoreCase | findByFirstnameIgnoreCase | … 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
等
3.4 简单测试
添加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();
}
}
4. 启动
启动之后,访问localhost:8080/findAll
,会得到如下效果
其余方法的测试,可以自己去尝试。