在spring boot的项目中使用spring data jpa真的很简单,写起来真的是笔下生风,神清气爽。非常适合喜欢偷懒的人,可以让你抛开反复编写的dao层代码以及一些写吐了的简单查询语句。
首先spring data jpa用起来就很简单,再加上集成在spring boot的项目中,还省去了xml配置,就更是开箱即用了。
spring data jpa简介
首先jpa(Java Persistence API)是一种orm框架的规范,让一个实体类自身就可以通过注解描述其与数据库表的对应关系。
jpa只是一个接口规范,用的最多的实现是hibernate。而spring data jpa就是采用hibernate作为实现的基础上,又进行的一层封装,更加屏蔽掉了hibernate的使用细节,降低了学习门槛。
spring data jpa的使用
1.基本配置
要使用spring data jpa需要在pom.xml种添加一个依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
要访问数据库肯定需要配置数据库的url,账号密码等信息。
这些信息可以在application.yml文件中配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/数据库名
username: 账号
password: 密码
这里先打断一下,如果想要修改数据源的实现,可以在java代码的配置类中配置想要的数据源实现的bean。
比如我使用alibaba的druid数据源实现,除了在pom.xml中加入依赖之外,需要在配置类中加入对应bean的配置:
@Autowired
Environment environment;
@Bean
public DataSource dataSource() throws SQLException {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setUrl(environment.getProperty("spring.datasource.url"));
dataSource.setUsername(environment.getProperty("spring.datasource.username"));//用户名
dataSource.setPassword(environment.getProperty("spring.datasource.password"));//密码
dataSource.setInitialSize(2);
dataSource.setMaxActive(500);
dataSource.setMinIdle(0);
dataSource.setMaxWait(60000);
dataSource.setValidationQuery("SELECT 1");
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setTestWhileIdle(true);
dataSource.setPoolPreparedStatements(false);
dataSource.setFilters("mergeStat");
return dataSource;
}
这是spring4推荐的使用java类进行配置的方式。
继续,然后就是spring data jpa的配置了,因为是采用hibernate来实现的,所以配置中与hibernate有一定联系:
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: true
其中ddl-auto有4种策略,与hibernate一样。
create:
每次启动项目,先删除之前创建的表结构,再根据实体类创建表结构。
create-drop :
每次启动项目,根据实体类创建表结构,每次终止项目,删除所有表结构。
update:
每次启动项目,验证实体类对应的数据库表结构,如果不一致就更新结构,如创建新表,新增字段等。
validate :
每次启动项目,验证实体类对应的数据库表结构,如果不一致就抛出异常。
一般使用update。
2.实体类
接下来随便写个实体类:
@Entity(name = "sys_student")
public class Student {
@Id
private String code;
private String name;
private String age;
private String banji;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getBanji() {
return banji;
}
public void setBanji(String banji) {
this.banji = banji;
}
}
@Entity注解表示该类是一个实体类,name属性表示对应的数据库表名。@Id注解顾名思义,就是指该属性作为数据库的主键。
jpa规范中还有很多注解,这里只用到了最主要的两个。
有了实体类,需要对这个实体类编写增删改查的代码。
此时便到了spring data jpa展现威力的时候了。
3.dao层接口
新建一个接口,作为student的dao层接口。
/**
* Created by liuruijie on 2017/2/18.
* student dao
*/
public interface StudentDao extends JpaRepository<Student, String>{
//按照姓名和班级查询
List<Student> findByNameAndBanji(String name, String banji);
//如果配置了@Qurey注解,则会按照里面的sql语句进行查询
@Query(value = "select s from #{#entityName} s where age<?1")
List<Student> customselect(Integer age);
}
这个接口继承于JpaRepository接口,后者提供了几乎所有常用的crud方法。
写完dao层接口后,下一步通常是编写实现类,然而,到这里就行了,根本不用自己实现。
4.使用
我们使用一下这个接口,在controller中注入它。
/**
* Created by liuruijie on 2017/2/18.
* student controller
*/
@RestController
@RequestMapping("student")
public class StudentController {
//注入自己建的dao接口
@Autowired
StudentDao studentDao;
//根据主键获取
@GetMapping("{id}")
public Object selectOne(@PathVariable("id") String code){
System.out.println(code);
return studentDao.findOne(code);
}
//自定义查询1
@GetMapping("nameAndBanji")
public Object findByNameAndBanji(String name, String banji){
return studentDao.findByNameAndBanji(name, banji);
}
//自定义查询2
@GetMapping("age/{age}")
public Object selectByAge(@PathVariable("age") Integer age){
return studentDao.customselect(age);
}
//修改
@PutMapping("{id}")
public Object update(@PathVariable("id") String id, Student student) {
student.setCode(id);
return studentDao.save(student);
}
//新增
@PostMapping
public Object insertOne(Student student){
studentDao.save(student);
return "ok";
}
}
测试一下是否真的能用。
先在数据库中插入几条记录。
发现完全没问题,也就是说只要我们继承了spring data jpa提供的接口,我们就可以获得基本的一些crud方法,并且自定义的方法也不用自己写实现就能使用。
自定义查询方法
spring data jpa自定义查询方法主要有3种方式
1.按一定规则命名的方法
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 | findByFirstname,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<Age> ages) | … where x.age in ?1 |
NotIn | findByAgeNotIn(Collection<Age> 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) |
2.@NamedQurey注解
这个注解是实体类上的注解,用于指定一个方法名对应的查询语句。
@Entity(name = "sys_student")
@NamedQuery(name = "User.namedquery"
, query = "select s from sys_student s where s.age<20")
public class Student {
···
public interface StudentDao extends JpaRepository<Student, String>{
···
//namedQuery
List<Student> namedquery();
···
这个方式就是将某个名称和查询语句绑定在一起,此时调用namedquery()方法就相当于执行@NamedQurey中配置的查询语句。
3.@Qurey注解
这个注解是方法上的注解,作用于dao层接口的方法上,顾名思义,加上这个注解,就可以将一个查询语句与一个方法绑定起来。
public interface StudentDao extends JpaRepository<Student, String>{
···
//如果配置了@Qurey注解,则会按照里面的sql语句进行查询
@Query(value = "select s from #{#entityName} s where age<?1")
List<Student> customselect(Integer age);
···
?是占位符,1是参数序号,从1开始。#{#entityName}是SpEl表达式,这里的值就是Student的实体名,即@Entity注解中设置的name。