在spring boot的項目中使用spring data jpa真的很簡單型宙,寫起來真的是筆下生風(fēng)响牛,神清氣爽瞬捕。非常適合喜歡偷懶的人歉嗓,可以讓你拋開反復(fù)編寫的dao層代碼以及一些寫吐了的簡單查詢語句丰介。
首先spring data jpa用起來就很簡單,再加上集成在spring boot的項目中鉴分,還省去了xml配置哮幢,就更是開箱即用了。
spring data jpa簡介
首先jpa(Java Persistence API)是一種orm框架的規(guī)范志珍,讓一個實體類自身就可以通過注解描述其與數(shù)據(jù)庫表的對應(yīng)關(guān)系橙垢。
jpa只是一個接口規(guī)范,用的最多的實現(xiàn)是hibernate伦糯。而spring data jpa就是采用hibernate作為實現(xiàn)的基礎(chǔ)上柜某,又進行的一層封裝嗽元,更加屏蔽掉了hibernate的使用細節(jié),降低了學(xué)習(xí)門檻喂击。
spring data jpa的使用
1.基本配置
要使用spring data jpa需要在pom.xml種添加一個依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
要訪問數(shù)據(jù)庫肯定需要配置數(shù)據(jù)庫的url剂癌,賬號密碼等信息。
這些信息可以在application.yml文件中配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/數(shù)據(jù)庫名
username: 賬號
password: 密碼
這里先打斷一下翰绊,如果想要修改數(shù)據(jù)源的實現(xiàn)佩谷,可以在java代碼的配置類中配置想要的數(shù)據(jù)源實現(xiàn)的bean。
比如我使用alibaba的druid數(shù)據(jù)源實現(xiàn)监嗜,除了在pom.xml中加入依賴之外谐檀,需要在配置類中加入對應(yīng)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類進行配置的方式。
繼續(xù)秤茅,然后就是spring data jpa的配置了稚补,因為是采用hibernate來實現(xiàn)的,所以配置中與hibernate有一定聯(lián)系:
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: true
其中ddl-auto有4種策略框喳,與hibernate一樣课幕。
create:
每次啟動項目,先刪除之前創(chuàng)建的表結(jié)構(gòu)五垮,再根據(jù)實體類創(chuàng)建表結(jié)構(gòu)乍惊。
create-drop :
每次啟動項目,根據(jù)實體類創(chuàng)建表結(jié)構(gòu)放仗,每次終止項目润绎,刪除所有表結(jié)構(gòu)。
update:
每次啟動項目诞挨,驗證實體類對應(yīng)的數(shù)據(jù)庫表結(jié)構(gòu)莉撇,如果不一致就更新結(jié)構(gòu),如創(chuàng)建新表惶傻,新增字段等棍郎。
validate :
每次啟動項目,驗證實體類對應(yīng)的數(shù)據(jù)庫表結(jié)構(gòu)银室,如果不一致就拋出異常涂佃。
一般使用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屬性表示對應(yīng)的數(shù)據(jù)庫表名辜荠。@Id注解顧名思義,就是指該屬性作為數(shù)據(jù)庫的主鍵抓狭。
jpa規(guī)范中還有很多注解伯病,這里只用到了最主要的兩個。
有了實體類否过,需要對這個實體類編寫增刪改查的代碼狱从。
此時便到了spring data jpa展現(xiàn)威力的時候了膨蛮。
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層接口后,下一步通常是編寫實現(xiàn)類持偏,然而驼卖,到這里就行了,根本不用自己實現(xiàn)鸿秆。
4.使用
我們使用一下這個接口酌畜,在controller中注入它。
/**
* Created by liuruijie on 2017/2/18.
* student controller
*/
@RestController
@RequestMapping("student")
public class StudentController {
//注入自己建的dao接口
@Autowired
StudentDao studentDao;
//根據(jù)主鍵獲取
@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";
}
}
測試一下是否真的能用卿叽。
先在數(shù)據(jù)庫中插入幾條記錄桥胞。
發(fā)現(xiàn)完全沒問題,也就是說只要我們繼承了spring data jpa提供的接口考婴,我們就可以獲得基本的一些crud方法贩虾,并且自定義的方法也不用自己寫實現(xiàn)就能使用。
自定義查詢方法
spring data jpa自定義查詢方法主要有3種方式
1.按一定規(guī)則命名的方法
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注解
這個注解是實體類上的注解沥阱,用于指定一個方法名對應(yīng)的查詢語句缎罢。
@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();
···
這個方式就是將某個名稱和查詢語句綁定在一起,此時調(diào)用namedquery()方法就相當(dāng)于執(zhí)行@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是參數(shù)序號抽莱,從1開始范抓。#{#entityName}是SpEl表達式,這里的值就是Student的實體名食铐,即@Entity注解中設(shè)置的name匕垫。