Spring Data JPA —— 快速入門

1、概述

  JPA : Java Persistence API, Java持久層API,是JDK 5.0註解或XML描述對象-關係表的映射關係,並將運行期的實體對象持久化到數據庫中。java

  Spring Data JPA 是Spring基於ORM框架、JPA規範封裝的一套JPA應用框架,可以使開發者用極簡的代碼便可實現對數據的訪問和操做。它提供了包括增刪改查等在內的經常使用功能,且易於擴展!學習並使用SpringDataJPA能夠極大提升開發效率! 除了CRUD外,還包括如分頁、排序等一些經常使用的功能。下面的示例代碼便可完成數據保存的操做,而無需具體實現類.mysql

public interface UserDao extends Repository<AccountInfo, Long> { 
  public AccountInfo save(AccountInfo accountInfo);
}

2、Spring Data JPA的核心接口

  • Repository:最頂層的接口,是一個空的接口,目的是爲了統一全部Repository的類型,且能讓組件掃描的時候自動識別。spring

  • CrudRepository :是Repository的子接口,提供CRUD的功能sql

  • PagingAndSortingRepository:是CrudRepository的子接口,添加分頁和排序的功能數據庫

  • JpaRepository:是PagingAndSortingRepository的子接口,增長了一些實用的功能,好比:批量操做等。apache

  • JpaSpecificationExecutor:用來作負責查詢的接口app

  • Specification:是Spring Data JPA提供的一個查詢規範,要作複雜的查詢,只需圍繞這個規範來設置查詢條件便可框架

 

3、快速入門

一、構建demo環境

  • 使用maven創建jar項目,下圖爲項目文件目錄

  • 導入依賴dom

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.cenobitor</groupId>
 5     <artifactId>JPADemo</artifactId>
 6     <version>0.0.1-SNAPSHOT</version>
 7     <packaging>pom</packaging>
 8     <description>統一管理依賴</description>
 9 
10     <properties>
11         <spring.version>4.2.4.RELEASE</spring.version>
12         <hibernate.version>5.0.7.Final</hibernate.version>
13         <slf4j.version>1.6.6</slf4j.version>
14         <springdatajpa.version>1.10.4.RELEASE</springdatajpa.version>
15         <c3p0.version>0.9.1.2</c3p0.version>
16         <junit.version>4.11</junit.version>
17     </properties>
18 
19     <dependencies>
20         <!-- spring 框架 -->
21         <dependency>
22             <groupId>org.springframework</groupId>
23             <artifactId>spring-context</artifactId>
24             <version>${spring.version}</version>
25         </dependency>
26 
27         <dependency>
28             <groupId>org.springframework</groupId>
29             <artifactId>spring-test</artifactId>
30             <version>${spring.version}</version>
31         </dependency>
32 
33 
34         <!-- spring data jpa 數據庫持久層 -->
35         <dependency>
36             <groupId>org.springframework.data</groupId>
37             <artifactId>spring-data-jpa</artifactId>
38             <version>${springdatajpa.version}</version>
39         </dependency>
40 
41         <!-- hibernate 框架 -->
42         <dependency>
43             <groupId>org.hibernate</groupId>
44             <artifactId>hibernate-core</artifactId>
45             <version>${hibernate.version}</version>
46         </dependency>
47         <dependency>
48             <groupId>org.hibernate</groupId>
49             <artifactId>hibernate-entitymanager</artifactId>
50             <version>${hibernate.version}</version>
51         </dependency>
52 
53         <!-- 數據庫鏈接池 -->
54         <dependency>
55             <groupId>c3p0</groupId>
56             <artifactId>c3p0</artifactId>
57             <version>${c3p0.version}</version>
58         </dependency>
59 
60         <!-- 日誌框架 -->
61         <dependency>
62             <groupId>org.slf4j</groupId>
63             <artifactId>slf4j-log4j12</artifactId>
64             <version>${slf4j.version}</version>
65         </dependency>
66         <!-- 數據庫驅動 -->
67         <dependency>
68             <groupId>mysql</groupId>
69             <artifactId>mysql-connector-java</artifactId>
70             <version>5.1.6</version>
71         </dependency>
72 
73         <!-- 單元測試 -->
74         <dependency>
75             <groupId>junit</groupId>
76             <artifactId>junit</artifactId>
77             <version>${junit.version}</version>
78         </dependency>
79     </dependencies>
80 
81 </project>
  • 在applicationContext.xml中增長以下配置ssh

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
 5        xmlns:jpa="http://www.springframework.org/schema/data/jpa"
 6        xsi:schemaLocation="
 7                         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 8                         http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
 9                         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
10                         http://www.springframework.org/schema/data/jpa
11                         http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
12 
13     <!--指定鏈接池配置-->
14     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
15         <property name="driverClass" value="com.mysql.jdbc.Driver" />
16         <property name="jdbcUrl" value="jdbc:mysql:///ssh01?useSSL=false" />
17         <property name="user" value="root" />
18         <property name="password" value="" />
19     </bean>
20     <!-- spring整合JPA -->
21     <bean id="entityManagerFactory"
22         class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
23         <property name="dataSource" ref="dataSource" />
24         <!--指定JPA掃描的實體類所在的包-->
25         <property name="packagesToScan" value="com.cenobitor.domain" />
26         <!-- 指定持久層提供者爲Hibernate -->
27         <property name="persistenceProvider">
28             <bean class="org.hibernate.ejb.HibernatePersistence" />
29         </property>
30         <property name="jpaVendorAdapter">
31             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
32                 <!-- 自動建表 -->
33                 <property name="generateDdl" value="true" />
34                 <property name="database" value="MYSQL" />
35                 <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
36                 <property name="showSql" value="true" />
37             </bean>
38         </property>
39         <property name="jpaDialect">
40             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
41         </property>
42     </bean>
43 
44     <!-- 配置事務管理器 -->
45     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
46         <property name="entityManagerFactory" ref="entityManagerFactory" />
47     </bean>
48 
49     <!-- 開啓事務註解 -->
50     <tx:annotation-driven transaction-manager="transactionManager" />
51     <!--指定Spring Data JPA要進行掃描的包,該包中的類框架會自動爲其建立代理-->
52     <jpa:repositories base-package="com.cenobitor.dao" />
53 
54 </beans>
  • 項目中新建com.cenobitor.domain包,建立實體類
 1 @Entity
 2 @Table
 3 public class User {
 4     @Id
 5     @GeneratedValue
 6     @Column
 7     private Integer id;
 8     @Column
 9     private String name;
10     @Column
11     private String password;
12 
13     public Integer getId() {
14         return id;
15     }
16 
17     public void setId(Integer id) {
18         this.id = id;
19     }
20 
21     public String getName() {
22         return name;
23     }
24 
25     public void setName(String name) {
26         this.name = name;
27     }
28 
29     public String getPassword() {
30         return password;
31     }
32 
33     public void setPassword(String password) {
34         this.password = password;
35     }
36 
37     @Override
38     public String toString() {
39         return "User{" +
40                 "id=" + id +
41                 ", name='" + name + '\'' +
42                 ", password='" + password + '\'' +
43                 '}';
44     }
45 }
  • 項目中新建com.cenobitor.dao包,建立dao
1 // 泛型參數1 : 實體類
2 // 泛型參數2 : 實體類中主鍵的類型
3 @Repository
4 public interface JpaRepository extends org.springframework.data.jpa.repository.JpaRepository<User,Integer>{
5 
6 }
  • 在com.cenobitor.test建立測試類,進行測試用例,若是在控制檯看到Hibernate輸出sql語句,說明操做成功

 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration("classpath:applicationContext.xml")
 3 public class SpringDataJPATest {
 4     @Autowired
 5     private JpaRepository jpaRepository;
 6 
 7     @Test
 8     public void testQuery() {
 9         // 查詢操做
10         List<User> list = jpaRepository.findAll();
11         for (User user : list) {
12             System.out.println(user);
13         }
14     }
15 }

二、增刪改查操做

 1 @Test
 2     public void testSave() {
 3         // 保存數據
 4         User user = new User();
 5         user.setName("趙六");
 6         user.setPassword("1234");
 7 
 8         jpaRepository.save(user);
 9     }
10 
11     @Test
12     public void testUpdate() {
13         // 更新操做,傳入主鍵ID
14         User user = new User();
15         user.setId(3);
16         user.setName("李四");
17         // 調用該方法時,首先進行查詢操做,若是數據不存在,執行插入
18         // 若是數據存在,執行修改
19         jpaRepository.save(user);
20     }
21 
22     @Test
23     public void testDelete() {
24         //刪除操做
25         jpaRepository.delete(3);
26     }
27 
28     @Test
29     public void testFindOne() {
30         //根據主鍵進行查詢
31         User user = jpaRepository.findOne(4);
32         System.out.println(user);
33     }

三、自定義查詢操做

  JpaRepository支持接口規範方法名查詢。意思是若是在接口中定義的查詢方法符合它的命名規則,就能夠不用寫實現。

  例如:findByName這個方法表示從數據庫中查詢Name這個屬性等於XXX的全部記 錄,相似於SQL語句:select*from xTablewherename=x這種形式 這段話有兩個重點:

①方法名須要在接口中設定

②必須符合必定的命名規範 

  • 方法名構造方法

  find+全局修飾+By+實體的屬性名稱+限定詞+鏈接詞+.(其它實體屬性)+OrderBy+ 排序屬性+排序方向
  例如:

findDistinctByFirstNameIgnoreCaseAndLastNameOrderByAgeDesc(String firstName,StringlastName){.} 

  其中:Distinct是全局修飾(非必須),FirstName和LastName是實體的屬性名, And是鏈接詞,IgnoreCase是限定詞,Age是排序屬性,Desc是排序方向,限定詞 和鏈接詞統稱爲「關鍵詞」 

  • 經常使用詞以下:
    • 全局修飾:Distinct,Top,First
    • 關鍵詞:IsNull,IsNotNull,Like,NotLike,Containing,In,NotIn, IgnoreCase,Between,Equals,LesThan,GreaterThan,After,Before
    • 排序方向:Asc,Desc
    • 鏈接詞:And,Or
  • 示例
 1 // 泛型參數1 : 實體類
 2 // 泛型參數2 : 實體類中主鍵的類型
 3 @Repository
 4 public interface JpaRepository extends org.springframework.data.jpa.repository.JpaRepository<User,Integer>{
 5     // =============標準命名方式===============
 6     // 根據名字進行精準查詢,Standard類中有name字段
 7     User findByName(String name);
 8     // 根據名字進行模糊查詢
 9     User findByNameLike(String name);
10     // 查詢名字爲空的數據
11     List<User> findByNameIsNull();
12     // 多條件查詢
13     User findByNameAndPassword(String name,String password);
14     // ==============非標準命名方式=============
15     // 使用JPQL進行非標準命名查詢
16     @Query("from User u where u.name like ?")
17     User findByNamexxxxxLikeJPQL(String name);
18     // 使用JPQL進行非標準多條件查詢
19     // 默認狀況下,問號的順序和傳入的參數順序是一致的
20     // 能夠在問號後面追加數字,改變和參數的匹配順序
21     // 下面的示例中,傳入的第一個參數匹配到第二個問號,傳入的第二個參數匹配到第一個問號
22     @Query("from User u where u.name like ?2 and password = ?1")
23     User findByNameAndOperatorJPQL(String password,String name);
24     // 使用標準SQL進行非標準命名查詢
25     @Query(value = "select * from user u where u.name like ?", nativeQuery = true)
26     User findByNamexxxxxLikeSQL(String name);
27 }
 1   @Test
 2     public void testFindByName(){
 3         User user = jpaRepository.findByName("趙六");
 4         System.out.println(user);
 5     }
 6 
 7     @Test
 8     public void testFindByNameLike(){
 9         User user = jpaRepository.findByNameLike("%六");
10         System.out.println(user);
11     }
12 
13     @Test
14     public void testFindByNameIsNull(){
15         List<User> users = jpaRepository.findByNameIsNull();
16         System.out.println(users);
17     }
18 
19     @Test
20     public void testFindByNameAndPassword(){
21         User user = jpaRepository.findByNameAndPassword("趙六","1234");
22         System.out.println(user);
23     }
24 
25     @Test
26     public void testFindByNamexxxxxLikeJPQL(){
27         User user = jpaRepository.findByNamexxxxxLikeJPQL("趙六");
28         System.out.println(user);
29     }
30 
31     @Test
32     public void testFindByNameAndOperatorJPQL(){
33         User user = jpaRepository.findByNameAndOperatorJPQL("1234","趙六");
34         System.out.println(user);
35     }
36 
37     @Test
38     public void testFindByNamexxxxxLikeSQL(){
39         User user = jpaRepository.findByNamexxxxxLikeSQL("趙六");
40         System.out.println(user);
41     }

四、自定義更新刪除操做

 1 // ================自定義增刪改操做==========
 2     @Transactional // 使用事務
 3     @Modifying // 執行修改操做
 4     @Query("delete from User u where u.name = ?")
 5     void deleteByName(String name);
 6 
 7     @Transactional
 8     @Modifying // 執行修改操做
 9     @Query("update User u set u.password = ?2 where u.name = ?1")
10     void updatePasswordByName(String name, String password);
 1     @Test
 2     public void testDeleteByName() {
 3         // 使用JPQL進行自定義刪除操做
 4         jpaRepository.deleteByName("趙六");
 5     }
 6 
 7     @Test
 8     public void testUpdatePasswordByName() {
 9         // 使用JPQL進行自定義更新操做
10         jpaRepository.updatePasswordByName("趙六","333");
11     }
五、分頁查詢與條件分頁查詢
  • 分頁查詢
 1     //分頁查詢
 2     @Test
 3     public void TestPageQuery() throws IOException {
 4         int page = 1 ;  //當前頁面
 5         int rows = 10 ; //每頁數據條數
 6         //建立分頁條件
 7         Pageable pageable = new PageRequest(page - 1, rows);
 8         Page<User> page1 = jpaRepository.findAll(pageable);
 9         //獲取總數據條數
10         long totalElements = page1.getTotalElements();
11         //獲取結果集
12         List<User> list = page1.getContent();
13         System.out.println(list);
14 
15     }
  • 條件分頁查詢
@Repository
public interface JpaRepository extends JpaRepository<User,Integer>,
        JpaSpecificationExecutor<User> {
}
 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration("classpath:applicationContext.xml")
 3 public class SpringDataJPATest {
 4     @Autowired
 5     private JpaRepository jpaRepository;
 6 
 7     @Test
 8     public void testConditionPageQuery() throws IOException {
 9 
10         User user = new User();
11         user.setName("李%");
12         user.setPassword("1234");
13 
14         int page = 1 ;  //當前頁面
15         int rows = 10 ; //每頁數據條數
16 
17         //構造查詢條件
18         Specification<User> specification = new Specification<User>() {
19             @Override
20             public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
21                 /**
22                  * 建立一個查詢的where語句
23                  * @param root : 根對象.能夠簡單的認爲就是泛型對象
24                  * @param cb : 構建查詢條件
25                  * @return a {@link Predicate}, must not be {@literal null}.
26                  */
27                 String name = user.getName();
28                 String password = user.getPassword();
29                 // 存儲條件的集合
30                 ArrayList<Predicate> list = new ArrayList<>();
31                 if (! name.isEmpty()){
32                     //構建模糊查詢條件,參數2爲具體的比較的值
33                     Predicate p1 = cb.like(root.get("name").as(String.class),name);
34                     list.add(p1);
35                 }
36                 if (! password.isEmpty()){
37                     Predicate p2 = cb.equal(root.get("password").as(String.class), password);
38                     list.add(p2);
39                 }
40                 if (list.size() == 0 ){
41                     return null;
42                 }
43                 Predicate[] arr = new Predicate[list.size()];
44                 list.toArray(arr);
45                 return cb.and(arr);
46             }
47 
48         };
49         Pageable pageable = new PageRequest(page-1,rows);
50         Page<User> page1 = jpaRepository.findAll(specification,pageable);
51         List<User> content = page1.getContent();
52         System.out.println(content);
53     }
54 }
相關文章
相關標籤/搜索