淺談Spring Data如何簡化數(shù)據(jù)操作的方法
Spring Data 概述
Spring Data
用于簡化數(shù)據(jù)庫訪問,支持NoSQL 和 關(guān)系數(shù)據(jù)存儲,其主要目標(biāo)是使數(shù)據(jù)庫的訪問變得方便快捷。
SpringData 項目所支持 NoSQL 存儲:
MongoDB (文檔數(shù)據(jù)庫)
Neo4j(圖形數(shù)據(jù)庫)
Redis(鍵/值存儲)
Hbase(列族數(shù)據(jù)庫)
SpringData 項目所支持的關(guān)系數(shù)據(jù)存儲技術(shù):
JDBC
JPA
Spring Data JPA
JPA Spring Data : 致力于減少數(shù)據(jù)訪問層 (DAO) 的開發(fā)量. 開發(fā)者唯一要做的,就只是聲明持久層的接口,其他都交給 Spring Data JPA 來幫你完成!
開發(fā)步驟
配置 Spring 整合 JPA
在 Spring 配置文件中配置 Spring Data,讓 Spring 為聲明的接口創(chuàng)建代理對象,配置了 \<jpa:repositories> 后,Spring 初始化容器時將會掃描 base-package 指定的包目錄及其子目錄,為繼承 Repository 或其子接口的接口創(chuàng)建代理對象,并將代理對象注冊為 Spring Bean,業(yè)務(wù)層便可以通過 Spring 自動封裝的特性來直接使用該對象。
聲明持久層的接口,該接口繼承 Repository,Repository 是一個標(biāo)記型接口,它不包含任何方法,如必要,Spring Data 可實現(xiàn) Repository 其他子接口,其中定義了一些常用的增刪改查,以及分頁相關(guān)的方法。
在接口中聲明需要的方法,Spring Data 將根據(jù)給定的策略來為其生成實現(xiàn)代碼。
搭建環(huán)境
導(dǎo)包:
antlr-2.7.7.jar
c3p0-0.9.2.1.jar
com.springsource.net.sf.cglib-2.2.0.jar
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
commons-logging-1.1.3.jar
dom4j-1.6.1.jar
hamcrest-core-1.3.jar
hibernate-c3p0-4.2.4.Final.jar
hibernate-commons-annotations-4.0.2.Final.jar
hibernate-core-4.2.4.Final.jar
hibernate-entitymanager-4.2.4.Final.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
javassist-3.15.0-GA.jar
jboss-logging-3.1.0.GA.jar
jboss-transaction-api_1.1_spec-1.0.1.Final.jar
junit-4.12.jar
mchange-commons-java-0.2.3.4.jar
mysql-connector-java-5.1.7-bin.jar
slf4j-api-1.6.1.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-data-commons-1.6.2.RELEASE.jar
spring-data-jpa-1.4.2.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" 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-1.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <context:component-scan base-package="com.kernel.spring.data"/> <!--配置數(shù)據(jù)源--> <context:property-placeholder location="classpath:db.properties"/> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"/> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/> <property name="user" value="${jdbc.user}"/> <property name="password" value="${jdbc.password}"/> </bean> <!--配置JPA的EntityManagerFactory--> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> </property> <property name="packagesToScan" value="com.kernel.spring.data"/> <property name="jpaProperties"> <props> <!--生成的數(shù)據(jù)表的映射策略--> <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop> <!--生成的數(shù)據(jù)表的列的映射策略--> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> </props> </property> </bean> <!--配置事務(wù)管理器--> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!--配置支持注解的事務(wù)--> <tx:annotation-driven transaction-manager="transactionManager"/> <!--配置Spring Data--> <jpa:repositories base-package="com.kernel.spring.data" entity-manager-factory-ref="entityManagerFactory"/> </beans>
Repository 接口
Repository 接口是 Spring Data 的一個核心接口,不提供任何方法,只要遵循接口方法定義規(guī)范,就無需寫實現(xiàn)類,與繼承 Repository 接口等價的一種方式,就是在持久層接口上使用 @RepositoryDefinition 注解,并為其指定domainClass 和 idClass 屬性。
Repository 的子接口
Repository: 僅僅是一個標(biāo)識,表明任何繼承它的均為倉庫接口類。
CrudRepository: 繼承 Repository,實現(xiàn)了一組 CRUD 相關(guān)的方法 。
PagingAndSortingRepository: 繼承 CrudRepository,實現(xiàn)了一組分頁排序相關(guān)的方法 。
JpaRepository: 繼承 PagingAndSortingRepository,實現(xiàn)一組 JPA 規(guī)范相關(guān)的方法 。
自定義的 XxxxRepository 需要繼承 JpaRepository,這樣的 XxxxRepository 接口就具備了通用的數(shù)據(jù)訪問控制層的能力。
JpaSpecificationExecutor: 不屬于Repository體系,實現(xiàn)一組 JPA Criteria 查詢相關(guān)的方法 。
Spring Data 方法定義規(guī)范
簡單條件查詢,查詢某一個實體或者集合,查詢方法以 get、find、read 開頭,涉及條件查詢時,條件的屬性用關(guān)鍵字連接,條件屬性以首字母大寫。
例如
public interface PersonRepository extends Repository<Person, Integer> { Person getByLastName(String lastName); List<Person> getByLastNameStartingWithAndIdLessThan(String lastName, Integer id); List<Person> getByLastNameEndingWithAndIdLessThan(String lastName, Integer id); List<Person> getByEmailInAndAgeLessThan(List list, Integer id); List<Person> getByAddress_IdGreaterThan(Integer id); }
Spring Data 支持的關(guān)鍵字
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? |
Betwee | 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) |
@Query 注解
這種查詢可以聲明在 Repository 方法中,擺脫像命名查詢那樣的約束,將查詢直接在相應(yīng)的接口方法中聲明,結(jié)構(gòu)更為清晰,這是 Spring Data 的特有實現(xiàn)。
索引參數(shù):
索引值從1開始,查詢中 ?x 的個數(shù)需要與方法形參個數(shù)相等,并且順序也要一致。
@Query("SELECT p FROM Person p WHERE p.lastName = ?1 and p.age = ?2") Person getByLastNameAndAge(String lastName, int age);
命名參數(shù):
可以定義好參數(shù)名,賦值值采用 @Param(參數(shù)名),而不用管順序。
@Query("SELECT p FROM Person p WHERE p.lastName = :lastName and p.id = :id") Person getByLastNameAndId(@Param("id")int id, @Param("lastName")String lastName);
本地查詢:
可以使用 @Query 執(zhí)行本地查詢,只要設(shè)置 nativeQuery 為 true。
@Query(value = "SELECT COUNT (id) FROM jpa_persons", nativeQuery = true) long getTotalCount();
@Modifying 注解和事務(wù)
@Query 與 @Modifying 這兩個注解一起使用,可以執(zhí)行 UPDATE、DELETE 操作。
注意,UPDATE、DELETE 需要使用事務(wù),因此需要定義在 Service 層。
事務(wù):
Spring Data 提供了默認(rèn)的事務(wù)處理方式,即所有的查詢均為只讀事務(wù)。
對于自定義的方法,如需改變 Spring Data 提供的事務(wù)方式,可以在方法上添加 @Transactional 注解。
進行多個 Repository 操作時,也應(yīng)該使它們在同一個事務(wù)中處理,按照分層架構(gòu)的思想,這部分屬于業(yè)務(wù)邏輯層,因此,需要在 Service 層實現(xiàn)對多個 Repository 的調(diào)用,并在相應(yīng)的方法上聲明事務(wù)。
CrudRepository 接口
CrudRepository 接口提供了最基本的對實體類的添刪改查操作
T save(T entity) 保存單個實體
Iterable<T> save(Iterable<? extends T> entities) 保存集合
T findOne(ID id) 根據(jù)id查找實體
boolean exists(ID id) 根據(jù)id判斷實體是否存在
Iterable<T> findAll() 查詢所有實體,不用或慎用
long count() 查詢實體數(shù)量
void delete(ID id) 根據(jù)Id刪除實體
void delete(T entity) 刪除一個實體
void delete(Iterable<? extends T> entities) 刪除一個實體的集合
void deleteAll() 刪除所有實體,不用或慎用
PagingAndSortingRepository 接口
該接口提供了分頁與排序功能
Iterable<T> findAll(Sort sort) 排序
Page<T> findAll(Pageable pageable) 分頁查詢(含排序功能)
@Test public void testPagingAndSortingRespository(){ int pageNo = 3; int pageSize = 5; Sort.Order order = new Sort.Order(Sort.Direction.DESC, "id"); Sort.Order order1 = new Sort.Order(Sort.Direction.ASC, "email"); Sort sort = new Sort(order,order1); PageRequest pageable = new PageRequest(pageNo, pageSize, sort); Page<Person> page = personRepository.findAll(pageable); System.out.println(page.getNumberOfElements()); System.out.println(page.getContent()); }
JpaRepository 接口
該接口提供了JPA的相關(guān)功能
List<T> findAll() 查找所有實體
List<T> findAll(Sort sort) 排序、查找所有實體
List<T> save(Iterable<? extends T> entities) 保存集合
void flush() 執(zhí)行緩存與數(shù)據(jù)庫同步
T saveAndFlush(T entity) 強制執(zhí)行持久化
void deleteInBatch(Iterable<T> entities) 刪除一個實體集合
JpaSpecificationExecutor 接口
不屬于Repository體系,實現(xiàn)一組 JPA Criteria 查詢相關(guān)的方法
Specification:封裝 JPA Criteria 查詢條件。通常使用匿名內(nèi)部類的方式來創(chuàng)建該接口的對象
@Test public void testJpaSpecificationExecutor(){ int pageNo = 3; int pageSize = 5; PageRequest pageable = new PageRequest(pageNo, pageSize); Specification<Person> specification = new Specification<Person>() { /** * @param root 代表查詢的實體類 * @param criteriaQuery 可以從中得到root對象,即告知 JPA Criteria 查詢哪個實體類, * 還可以添加查詢條件,還可以結(jié)合EntityManager對象得到最終查詢的 TypedQuery * @param criteriaBuilder 用于創(chuàng)建criteria工廠 * @return Predicate類型,代表一個查詢條件 */ @Override public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Predicate predicate = criteriaBuilder.ge(root.get("id"),5); return predicate; } }; Page<Person> page = personRepository.findAll(specification, pageable); System.out.println(page.getNumberOfElements()); System.out.println(page.getContent()); }
自定義 Repository 方法
為某一個 Repository 上添加自定義方法
創(chuàng)建一個 XXXDAO 接口,聲明接口方法。
創(chuàng)建一個 XXXRepository 接口,并繼承 XXXDAO 接口。
提供 XXXRepository 的實現(xiàn)類 XXXRepositoryImpl,并實現(xiàn) XXXDAO 定義的接口方法。
實際上在使用 XXXRepository 的自定義方法時會調(diào)用 XXXRepositoryImpl 中的實現(xiàn)。
為所有的 Repository 都添加自實現(xiàn)的方法
創(chuàng)建一個 XXXRepository 接口,需要繼承 創(chuàng)建一個 Repository 接口。
提供 XXXRepository 的實現(xiàn)類 XXXRepositoryImpl,且繼承 SimpleJpaRepository,并提供方法的實現(xiàn)。
定義 JpaRepositoryFactoryBean 的實現(xiàn)類,使其生成 XXXRepository 的接口實現(xiàn)類的對象。
修改 \<jpa:repositories/> 節(jié)點的 factory-class 屬性指向 JpaRepositoryFactoryBean 的實現(xiàn)類的全類名。
注意:
全局的擴展實現(xiàn)類不要用 Imp 作為后綴名,
或者為全局?jǐn)U展接口添加 @NoRepositoryBean注解告知 SpringData 不要把其作為 Repository。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 使用Spring Data Redis實現(xiàn)數(shù)據(jù)緩存的方法
- springboot使用spring-data-jpa操作MySQL數(shù)據(jù)庫
- Spring boot中使用Spring-data-jpa方便快捷的訪問數(shù)據(jù)庫(推薦)
- 詳解基于Spring Boot與Spring Data JPA的多數(shù)據(jù)源配置
- 詳解Spring Data操作Redis數(shù)據(jù)庫
- Spring(AbstractRoutingDataSource)實現(xiàn)動態(tài)數(shù)據(jù)源切換示例
- 使用Spring的AbstractRoutingDataSource實現(xiàn)多數(shù)據(jù)源切換示例
相關(guān)文章
java 之JNA中的Memory和Pointer的使用方法
這篇文章主要介紹了java 之JNA中的Memory和Pointer的使用方法,文章基于Java的相關(guān)自來哦展開對Pointer和Memory的使用介紹,需要的小伙伴可以參考一下2022-04-04spring boot使用properties定義短信模板的方法教程
這篇文章主要給大家介紹了關(guān)于spring boot使用properties定義短信模板的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01Mybatis報錯mapkey is required問題及解決
這篇文章主要介紹了Mybatis報錯mapkey is required問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06SpringBoot+WebMagic+MyBaties實現(xiàn)爬蟲和數(shù)據(jù)入庫的示例
WebMagic是一個開源爬蟲框架,本項目通過在SpringBoot項目中使用WebMagic去抓取數(shù)據(jù),最后使用MyBatis將數(shù)據(jù)入庫。具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-10-10Java創(chuàng)建數(shù)組的幾種方式總結(jié)
下面小編就為大家?guī)硪黄狫ava創(chuàng)建數(shù)組的幾種方式總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-10-10