詳解使用Spring?Data?repository進(jìn)行數(shù)據(jù)層的訪問(wèn)問(wèn)題
使用Spring Data repository進(jìn)行數(shù)據(jù)層的訪問(wèn)
抽象出Spring Data repository是因?yàn)樵陂_(kāi)發(fā)過(guò)程中,常常會(huì)為了實(shí)現(xiàn)不同持久化存儲(chǔ)的數(shù)據(jù)訪問(wèn)層而寫(xiě)大量的大同小異的代碼。
Spring Data repository的目的就是要大幅減少這些重復(fù)的代碼。 Spring Data Elasticsearch為文檔的存儲(chǔ),查詢,排序和統(tǒng)計(jì)提供了一個(gè)高度抽象的模板。
核心概念
Spring Data repository抽象中最核心的接口就是Repository。該接口使用了泛型,需要提供兩個(gè)類型參數(shù),
- 第一個(gè)是接口處理的域?qū)ο箢愋?/li>
- 第二個(gè)是域?qū)ο蟮闹麈I類型。
這個(gè)接口常被看做是一個(gè)標(biāo)記型接口,用來(lái)獲取要操作的域?qū)ο箢愋秃蛶椭_(kāi)發(fā)者識(shí)別繼承這個(gè)類的接口。在Repository的基礎(chǔ)上,CrudRepository接口提供了針對(duì)實(shí)體類的復(fù)雜的CRUD(增刪改查)操作。
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> { <S extends T> S save(S entity); T findOne(ID primaryKey); Iterable<T> findAll(); Long count(); void delete(T entity); boolean exists(ID primaryKey); // … more functionality omitted. }
PagingAndSortingRepository接口在CrudRepository的基礎(chǔ)上增加了一些方法,使開(kāi)發(fā)者可以方便的對(duì)實(shí)體類進(jìn)行分頁(yè)和排序。
public interface PagingAndSortingRepository<T, ID extends Serializable> extends CrudRepository<T, ID> { Iterable<T> findAll(Sort sort); Page<T> findAll(Pageable pageable); }
在分頁(yè)長(zhǎng)度為20的基礎(chǔ)上,想要獲取第二頁(yè)的User數(shù)據(jù),代碼如下
PagingAndSortingRepository<User, Long> repository = // … get access to a bean Page<User> users = repository.findAll(new PageRequest(1, 20));
查詢方法
標(biāo)準(zhǔn)的CRUD(增刪改查)功能都要使用查詢語(yǔ)句來(lái)查詢數(shù)據(jù)庫(kù)。但通過(guò)使用Spring Data,只要五個(gè)步驟就可以實(shí)現(xiàn)。
- 創(chuàng)建一個(gè)Domain類
@Entity @Document public class Person { … }
- 聲明一個(gè)繼承Repository接口或其子接口的持久層接口。并標(biāo)明要處理的域?qū)ο箢愋图捌渲麈I的類型(在下面的例子中,要處理的域?qū)ο笫荘erson,其主鍵類型是Long)
interface PersonRepository extends Repository<Person, Long> { … }
- 在接口中聲明查詢方法(spring會(huì)為其生成實(shí)現(xiàn)代碼)
interface PersonRepository extends Repository<Person, Long> { List<Person> findByLastname(String lastname); }
- 讓Spring創(chuàng)建對(duì)這些接口的代理實(shí)例。
使用JavaConfig的方式
import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @EnableJpaRepositories class Config {}
使用xml配置的方式
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <jpa:repositories base-package="com.acme.repositories"/> </beans>
注入repository實(shí)例,并使用
public class SomeClient { @Autowired private PersonRepository repository; public void doSomething() { List<Person> persons = repository.findByLastname("Matthews"); } }
定義查詢方法
CREATE
Spring Data repository自帶了一個(gè)非常有用的查詢構(gòu)造器。它會(huì)從方法名中去掉類似find..By,read...By,query...By,count...By之類的前綴,然后解析剩余的名字。我們也可以在方法名中加入更多的表達(dá)式,比如查詢時(shí)需要distinct約束,那么在方法名中加入Distinct即可。方法名中的第一個(gè)By是一個(gè)分解符,代表著查詢語(yǔ)句的開(kāi)始,我們可以用And或Or來(lái)將多個(gè)查詢條件關(guān)聯(lián)起來(lái)。
public interface PersonRepository extends Repository<User, Long> { List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // Enables the distinct flag for the query List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enabling ignoring case for an individual property List<Person> findByLastnameIgnoreCase(String lastname); // Enabling ignoring case for all suitable properties List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // Enabling static ORDER BY for a query List<Person> findByLastnameOrderByFirstnameAsc(String lastname); List<Person> findByLastnameOrderByFirstnameDesc(String lastname); }
除此之外,我們還可以為方法添加某些特定類型的參數(shù)(如:Pageable和Sort)來(lái)動(dòng)態(tài)的在查詢中添加分頁(yè)和排序。
Page<User> findByLastname(String lastname, Pageable pageable); Slice<User> findByLastname(String lastname, Pageable pageable); List<User> findByLastname(String lastname, Sort sort); List<User> findByLastname(String lastname, Pageable pageable);
USE_DECLARED_QUERY
如果方法通過(guò) @Query 指定了查詢語(yǔ)句,則使用該語(yǔ)句創(chuàng)建Query;如果沒(méi)有,則查找是否定義了符合條件的Named Query,如果找到,則使用該命名查詢;如果兩者都沒(méi)有找到,則拋出異常。使用@Query聲明查詢語(yǔ)句的例子如下:
//使用Query注解 @Query("select a from AccountInfo a where a.accountId = ?1") public AccountInfo findByAccountId(Long accountId);
CREATE_IF_NOT_FOUND
結(jié)合了CREATE和USE_DECLARED_QUERY 兩種策略,會(huì)先嘗試查找聲明好的查詢,如果沒(méi)有找到,就按照解析方法名的方式構(gòu)建查詢。這是默認(rèn)的查詢策略,如果不更改配置,會(huì)一直使用這種策略構(gòu)建查詢。這種策略支持通過(guò)方法名快速定義一個(gè)查詢,也允許引入聲明好的查詢。
WEB支持
DomainClassConverter 允許開(kāi)發(fā)者在SpringMVC控制層的方法中直接使用域?qū)ο箢愋?Domain types),而無(wú)需通過(guò)repository手動(dòng)查找這個(gè)實(shí)例。
@Controller @RequestMapping("/users") public class UserController { @RequestMapping("/{id}") public String showUserForm(@PathVariable("id") User user, Model model) { model.addAttribute("user", user); return "userForm"; } }
上面的方法直接接收了一個(gè)User對(duì)象,開(kāi)發(fā)者不需要做任何的搜索操作,轉(zhuǎn)換器會(huì)自動(dòng)將路徑變量id轉(zhuǎn)為User對(duì)象的id,并且調(diào)用了findOne()方法查詢出User實(shí)體。 注意:當(dāng)前的Repository 必須實(shí)現(xiàn)CrudRepository
HandlerMethodArgumentResolver使開(kāi)發(fā)者可以在controller的方法中使用Pageable和Sort作為參數(shù)。
@Controller @RequestMapping("/users") public class UserController { @Autowired UserRepository repository; @RequestMapping public String showUsers(Model model, Pageable pageable) { model.addAttribute("users", repository.findAll(pageable)); return "users"; } }
通過(guò)上面的方法定義,Spring MVC會(huì)使用下面的默認(rèn)配置嘗試從請(qǐng)求參數(shù)中得到一個(gè)Pageable的實(shí)例。
參數(shù)名 | 作用 |
---|---|
page | 想要獲取的頁(yè)數(shù),默認(rèn)為0 |
size | 獲取頁(yè)的大小,默認(rèn)為20 |
page | 需要排序的屬性,格式為property,property(,ASC/DESC),默認(rèn)升序排序。支持多個(gè)字段排序,比如?sort=firstname&sort=lastname,asc |
開(kāi)發(fā)者也可以針對(duì)多個(gè)表定義多個(gè)Pageable或Sort實(shí)例,需要使用Spring的@Qualifier注解來(lái)區(qū)分它們。并且請(qǐng)求參數(shù)名要帶有${qualifier}_的前綴。例子如下:
public String showUsers(Model model, @Qualifier("foo") Pageable first, @Qualifier("bar") Pageable second) { … }
請(qǐng)求中需要帶有foo_page和bar_page等參數(shù)。
到此這篇關(guān)于使用Spring Data repository進(jìn)行數(shù)據(jù)層的訪問(wèn)的文章就介紹到這了,更多相關(guān)Spring Data repository數(shù)據(jù)層訪問(wèn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Spring MVC攔截器實(shí)現(xiàn)日志記錄的方法
本篇文章主要介紹了使用Spring MVC攔截器實(shí)現(xiàn)日志記錄的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04maven多moudle項(xiàng)目在idea里面顯示多個(gè)root問(wèn)題及解決
這篇文章主要介紹了maven多moudle項(xiàng)目在idea里面顯示多個(gè)root問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Spring數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)原理深入刨析
開(kāi)發(fā)web項(xiàng)目,我們肯定會(huì)和數(shù)據(jù)庫(kù)打交道,因此就會(huì)涉及到數(shù)據(jù)庫(kù)鏈接的問(wèn)題。在以前我們開(kāi)發(fā)傳統(tǒng)的SSM結(jié)構(gòu)的項(xiàng)目時(shí)進(jìn)行數(shù)據(jù)庫(kù)鏈接都是通過(guò)JDBC進(jìn)行數(shù)據(jù)鏈接,我們每和數(shù)據(jù)庫(kù)打一次交道都需要先獲取一次鏈接,操作完后再關(guān)閉鏈接,這樣子效率很低,因此就出現(xiàn)了連接池2022-11-11Java中幾個(gè)Reference常見(jiàn)的作用詳解
這篇文章主要給大家介紹了Java中關(guān)于Reference多個(gè)作用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編一起來(lái)學(xué)習(xí)學(xué)習(xí)吧。2017-06-06Java中@DS+@Transactional注解切換數(shù)據(jù)源失效解決方案
本文主要介紹了@DS+@Transactional注解切換數(shù)據(jù)源失效解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06