JPA02 -- Spring Data JPA01

关于JPA总共写了三篇内容,下面附上链接:

JPA01:https://www.cnblogs.com/buwei/p/9979794.html
JPA02:https://www.cnblogs.com/buwei/p/9985287.html
JPA03:https://www.cnblogs.com/buwei/p/9985941.html

一、Spring Data JPA的概述

  1.1 Spring Data JPA概述

  Spring Data JPA是Spring基于ORM框架、JPA规范的基础上封装的一套JPA应用框架。他提供了包括增删改查在内的常用功能,且易于扩展。

  Spring Data JPA让我们解脱了DAO的操作,基本上所有的CRUD都可以依赖于它来实现,在试驾的工程中,推荐使用Spring Data JPA+ORM(如:Hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。

  1.2 Spring Data JPA的特性

  使用Spring Data JPA,我们的DAO层只需要写接口,就自动具有了增删改查、分页查询等方法。

  1.3 Spring Data JPA与JPA和Hibernate之间的关系

  JPA是一套规范,内部是由接口和抽象内组成,Hibernate是一套乘数的ORM框架,而且Hibernate实现了JPA规范,所以也可以称Hibernate是JPA的一种实现方式,我们使用JPA的API编程,是一种面向接口编程的思想。

二、Spring Data JPA的快速入门

  2.1 需求说明

  Spring Data JPA完成客户的基本CRUD操作

  2.2 搭建Spring Data JPA的开发环境

  1. 引入Spring Data JPA的坐标

  使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者Hibernate,所以需要导入Spring相关坐标,Hibernate坐标,数据库驱动坐标等。

  1     <properties>
  2         <spring.version>4.2.4.RELEASE</spring.version>
  3         <hibernate.version>5.0.7.Final</hibernate.version>
  4         <slf4j.version>1.6.6</slf4j.version>
  5         <log4j.version>1.2.12</log4j.version>
  6         <c3p0.version>0.9.1.2</c3p0.version>
  7         <mysql.version>5.1.6</mysql.version>
  8     </properties>
  9     <dependencies>
 10         <!-- junit单元测试 -->
 11         <dependency>
 12             <groupId>junit</groupId>
 13             <artifactId>junit</artifactId>
 14             <version>4.9</version>
 15             <scope>test</scope>
 16         </dependency>
 17 
 18         <!-- spring beg -->
 19         <dependency>
 20             <groupId>org.aspectj</groupId>
 21             <artifactId>aspectjweaver</artifactId>
 22             <version>1.6.8</version>
 23         </dependency>
 24 
 25         <dependency>
 26             <groupId>org.springframework</groupId>
 27             <artifactId>spring-aop</artifactId>
 28             <version>${spring.version}</version>
 29         </dependency>
 30 
 31         <dependency>
 32             <groupId>org.springframework</groupId>
 33             <artifactId>spring-context</artifactId>
 34             <version>${spring.version}</version>
 35         </dependency>
 36 
 37         <dependency>
 38             <groupId>org.springframework</groupId>
 39             <artifactId>spring-context-support</artifactId>
 40             <version>${spring.version}</version>
 41         </dependency>
 42 
 43         <dependency>
 44             <groupId>org.springframework</groupId>
 45             <artifactId>spring-orm</artifactId>
 46             <version>${spring.version}</version>
 47         </dependency>
 48 
 49         <dependency>
 50             <groupId>org.springframework</groupId>
 51             <artifactId>spring-beans</artifactId>
 52             <version>${spring.version}</version>
 53         </dependency>
 54 
 55         <dependency>
 56             <groupId>org.springframework</groupId>
 57             <artifactId>spring-core</artifactId>
 58             <version>${spring.version}</version>
 59         </dependency>
 60         <!-- spring end -->
 61 
 62         <!-- hibernate beg -->
 63         <dependency>
 64             <groupId>org.hibernate</groupId>
 65             <artifactId>hibernate-core</artifactId>
 66             <version>${hibernate.version}</version>
 67         </dependency>
 68         <dependency>
 69             <groupId>org.hibernate</groupId>
 70             <artifactId>hibernate-entitymanager</artifactId>
 71             <version>${hibernate.version}</version>
 72         </dependency>
 73         <dependency>
 74             <groupId>org.hibernate</groupId>
 75             <artifactId>hibernate-validator</artifactId>
 76             <version>5.2.1.Final</version>
 77         </dependency>
 78         <!-- hibernate end -->
 79 
 80         <!-- c3p0 beg -->
 81         <dependency>
 82             <groupId>c3p0</groupId>
 83             <artifactId>c3p0</artifactId>
 84             <version>${c3p0.version}</version>
 85         </dependency>
 86         <!-- c3p0 end -->
 87 
 88         <!-- log end -->
 89         <dependency>
 90             <groupId>log4j</groupId>
 91             <artifactId>log4j</artifactId>
 92             <version>${log4j.version}</version>
 93         </dependency>
 94 
 95         <dependency>
 96             <groupId>org.slf4j</groupId>
 97             <artifactId>slf4j-api</artifactId>
 98             <version>${slf4j.version}</version>
 99         </dependency>
100 
101         <dependency>
102             <groupId>org.slf4j</groupId>
103             <artifactId>slf4j-log4j12</artifactId>
104             <version>${slf4j.version}</version>
105         </dependency>
106         <!-- log end -->
107 
108 
109         <dependency>
110             <groupId>mysql</groupId>
111             <artifactId>mysql-connector-java</artifactId>
112             <version>${mysql.version}</version>
113         </dependency>
114 
115         <dependency>
116             <groupId>org.springframework.data</groupId>
117             <artifactId>spring-data-jpa</artifactId>
118             <version>1.9.0.RELEASE</version>
119         </dependency>
120 
121         <dependency>
122             <groupId>org.springframework</groupId>
123             <artifactId>spring-test</artifactId>
124             <version>4.2.4.RELEASE</version>
125         </dependency>
126 
127         <!-- el beg 使用spring data jpa 必须引入 -->
128         <dependency>
129             <groupId>javax.el</groupId>
130             <artifactId>javax.el-api</artifactId>
131             <version>2.2.4</version>
132         </dependency>
133 
134         <dependency>
135             <groupId>org.glassfish.web</groupId>
136             <artifactId>javax.el</artifactId>
137             <version>2.2.4</version>
138         </dependency>
139         <!-- el end -->
140     </dependencies>

  2. 整合Spring Data JPA与JPA

  创建applicationContext.xml配置文件

  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" xmlns:aop="http://www.springframework.org/schema/aop"
  4        xmlns:context="http://www.springframework.org/schema/context"
  5        xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
  6        xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
  7        xsi:schemaLocation="
  8         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  9         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
 10         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
 11         http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
 12         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
 13         http://www.springframework.org/schema/data/jpa
 14         http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
 15 
 16     <!-- 1.dataSource 配置数据库连接池-->
 17     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
 18         <property name="driverClass" value="com.mysql.jdbc.Driver" />
 19         <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_jpa" />
 20         <property name="user" value="root" />
 21         <property name="password" value="root" />
 22     </bean>
 23 
 24     <!-- spring和spring data jpa的配置 -->
 25     <!-- 2.配置entityManagerFactory对象交个spring容器管理 -->
 26     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 27         <property name="dataSource" ref="dataSource" />
 28         <!-- 配置要扫描的包(实体类所在的包)-->
 29         <property name="packagesToScan" value="com.buwei.domain" />
 30         <!-- jpa的实现厂商 -->
 31         <property name="persistenceProvider">
 32             <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
 33         </property>
 34         <!--JPA的供应商适配器-->
 35         <property name="jpaVendorAdapter">
 36             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
 37                 <!-- 配置是否自动创建数据库表 -->
 38                 <property name="generateDdl" value="false" />
 39                 <!-- 指定数据库类型 -->
 40                 <property name="database" value="MYSQL" />
 41                 <!-- 数据库方言,支持的特有语法 -->
 42                 <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
 43                 <!-- 是否显示sql-->
 44                 <property name="showSql" value="true" />
 45             </bean>
 46         </property>
 47 
 48         <!-- jpa的方言:高级特性 -->
 49         <property name="jpaDialect">
 50             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
 51         </property>
 52 
 53         <!--注入jpa的配置信息
 54             加载jpa的基本配置信息和jpa实现方式(hibernate)的配置信息
 55             hibernate.hbm2ddl.auto : 自动创建数据库表
 56                 create : 每次都会重新创建数据库表
 57                 update:有表不会重新创建,没有表会重新创建表
 58                 none:不创建表
 59         -->
 60         <property name="jpaProperties" >
 61             <props>
 62                 <prop key="hibernate.hbm2ddl.auto">update</prop>
 63             </props>
 64         </property>
 65 
 66     </bean>
 67     <!-- 3.事务管理器-->
 68     <!-- JPA事务管理器  -->
 69     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
 70         <property name="entityManagerFactory" ref="entityManagerFactory" />
 71     </bean>
 72 
 73     <!-- 整合spring data jpa-->
 74     <jpa:repositories base-package="com.buwei.mapper" transaction-manager-ref="transactionManager"
 75                       entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
 76 
 77     <!-- 4.txAdvice-->
 78     <tx:advice id="txAdvice" transaction-manager="transactionManager">
 79         <tx:attributes>
 80             <tx:method name="save*" propagation="REQUIRED"/>
 81             <tx:method name="insert*" propagation="REQUIRED"/>
 82             <tx:method name="update*" propagation="REQUIRED"/>
 83             <tx:method name="delete*" propagation="REQUIRED"/>
 84             <tx:method name="get*" read-only="true"/>
 85             <tx:method name="find*" read-only="true"/>
 86             <tx:method name="*" propagation="REQUIRED"/>
 87         </tx:attributes>
 88     </tx:advice>
 89 
 90     <!-- 5.aop-->
 91     <aop:config>
 92         <aop:pointcut id="pointcut" expression="execution(* com.buwei.service.*.*(..))" />
 93         <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
 94     </aop:config>
 95 
 96     <!-- 6.配置包扫描 -->
 97     <context:component-scan base-package="com.buwei"></context:component-scan>
 98 
 99     <!--组装其它 配置文件-->
100 
101 </beans>

  3. 使用JPA注解配置映射关系

 1 /**
 2  * 所有的注解都是使用JPA的规范提供的注解,
 3  * 所以在导入注解包的时候,一定要导入javax.persistence下的
 4  */
 5 @Entity //声明实体类
 6 @Table(name="cst_customer") //建立实体类和表的映射关系
 7 public class Customer implements Serializable {
 8     @Id//声明当前私有属性为主键
 9     @GeneratedValue(strategy= GenerationType.IDENTITY) //配置主键的生成策略
10     @Column(name="cust_id") //指定和表中cust_id字段的映射关系
11     private Long custId;
12 
13     @Column(name="cust_name") //指定和表中cust_name字段的映射关系
14     private String custName;
15 
16     @Column(name="cust_source")//指定和表中cust_source字段的映射关系
17     private String custSource;
18 
19     @Column(name="cust_industry")//指定和表中cust_industry字段的映射关系
20     private String custIndustry;
21 
22     @Column(name="cust_level")//指定和表中cust_level字段的映射关系
23     private String custLevel;
24 
25     @Column(name="cust_address")//指定和表中cust_address字段的映射关系
26     private String custAddress;
27 
28     @Column(name="cust_phone")//指定和表中cust_phone字段的映射关系
29     private String custPhone;
30 
31     //省略getter和setter方法
32 }

  2.3 使用Spring Data JPA完成需求

  1. 编写符合Spring Data JPA规范的Dao层接口

  Spring Data JPA是spring提供的一款对于数据访问层(DAO)的框架,使用Spring Data JPA,只需要按照框架的规范提供DAO接口,不需要实现类就可以完成数据库的增删改查、分页查询等方法的定义。

  在Spring Data JPA中,对于定义符合规范的DAO接口,我们只需要遵循以下几点就可以了:

  1.创建一个DAO层接口,并实现JapReponsitory和JpaSpecificationExecutor

  2.提供相应的泛型

1 /**
2  * JpaRepository<实体类类型,主键类型>:用来完成基本CRUD操作
3  * JpaSpecificationExecutor<实体类类型>:用于复杂查询(分页等查询操作)
4  */
5 public interface CustomerDAO extends
6         JpaRepository<Customer, Long>,JpaSpecificationExecutor<Customer> {
7 
8 }

  2.编写测试类完成基本CRUD操作

 1 @RunWith(SpringJUnit4ClassRunner.class)
 2 @ContextConfiguration(locations = "classpath:applicationContext.xml")
 3 public class CustomerDaoTest {
 4     @Autowired
 5     private CustomerDAO customerDao;
 6 
 7     /**
 8      * 保存:调用save(obj)方法
 9      * 对于save方法,当执行此方法的对象中id无值,及为新增操作
10      */
11     @Test
12     public void testInsert(){
13         // 创建一个新的用户
14         Customer customer = new Customer();
15         customer.setCustName("不为");
16         // 新增
17         customerDao.save(customer);
18     }
19 
20     /**
21      * 根据ID查询:调用findOne方法
22      */
23     @Test
24     public void testFindById(){
25         Customer customer = customerDao.findOne(1L);
26         System.out.println(customer);
27     }
28 
29     /**
30      * 修改:调用save(obj)方法
31      * 对于save方法,当执行此方法的对象中id有值,及为更新操作
32      */
33     @Test
34     public void testUpdate(){
35         // 查询id为1的用户
36         Customer customer = customerDao.findOne(1L);
37         // 修改客户名称
38         customer.setCustName("不为——为");
39         // 更新
40         customerDao.save(customer);
41     }
42 
43     /**
44      * 根据id删除:调用delete(id)方法
45      */
46     @Test
47     public void testDelete(){
48         customerDao.delete(1L);
49     }
50 }

三、Spring Data JPA的内部原理剖析

  3.1 Spring Data JPA的常用接口分析

  在上面的案例中,我们发现对于customerDao,我们并没有提供任何方法就可以调用增删改查方法,是因为接口继承了JpaReponsitory和JpaSpecificationExecutor,我们使用的方法就是上面两个接口中的方法。

  3.2 Spring Data JPA的实现过程

  等理解清楚了再来作补充。。。。也欢迎大家留言。。。。

四、Spring Data JPA的查询方式

  4.1 使用Spring DataJPA中接口定义的方法进行查询

  上面用到的方法直接使用了JpaReponsitory与JpaSpecificationExecutor接口中的方法,源码如下:

 1 @NoRepositoryBean
 2 public interface JpaRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID> {
 3     List<T> findAll();
 4 
 5     List<T> findAll(Sort var1);
 6 
 7     List<T> findAll(Iterable<ID> var1);
 8 
 9     <S extends T> List<S> save(Iterable<S> var1);
10 
11     void flush();
12 
13     <S extends T> S saveAndFlush(S var1);
14 
15     void deleteInBatch(Iterable<T> var1);
16 
17     void deleteAllInBatch();
18 
19     T getOne(ID var1);
20 }

 

 1 public interface JpaSpecificationExecutor<T> {
 2     T findOne(Specification<T> var1);
 3 
 4     List<T> findAll(Specification<T> var1);
 5 
 6     Page<T> findAll(Specification<T> var1, Pageable var2);
 7 
 8     List<T> findAll(Specification<T> var1, Sort var2);
 9 
10     long count(Specification<T> var1);
11 }

  4.2 使用JPQL的方式查询

  使用Spring Data JPA提供的查询方法已经可以解决大部分的应用场景,但是对于有些业务,我们还需要灵活的构造查询条件,这时就可以使用@Query注解,结合JPQL语句完成查询。

  @Query注解的使用非常简单,只需要在方法上面标注该注解,同时童工一个JPQL查询语句即可。

 1 public interface CustomerDAO extends
 2         JpaRepository<Customer, Long>,JpaSpecificationExecutor<Customer> {
 3 
 4     /**
 5      *  @Query 使用jpql的方式查询。
 6      */
 7     @Query(value="from Customer")
 8     public List<Customer> findAllCustomer();
 9 
10     /**
11      * @Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
12      * @param custName
13      * @return
14      */
15     @Query(value="from Customer where custName = ?1")
16     public Customer findCustomer(String custName);
17 
18     /**
19      * @Modifying是标识该操作为修改查询操作
20      * @param custName
21      * @param custId
22      */
23     @Query(value="update Customer set custName = ?1 where custId = ?2")
24     @Modifying
25     public void updateCustomer(String custName,Long custId);
26 }

  4.3 使用SQL语句查询

  使用SQL语句查询如下:

1     /**
2      * nativeQuery : 标识使用本地sql的方式查询
3      */
4     @Query(value="select * from cst_customer",nativeQuery=true)
5     public void findBySql();

  4.4 方法命名规则查询

  按照Spring Data JPA定义的规则,查询方法一FindBy开头,设计条件查询时,条件的属性用条件关键词连接,方法名命名需符合小驼峰规则,框架会自动对方法名进行解析。

1     /**
2      * 方法命名方式查询(根据客户名称查询客户)
3      * @param custName
4      * @return
5      */
6     public Customer findByCustName(String custName);

  对应的具体的关键字适用方法和对应的SQL如下表所示

Keyword

Sample

JPQL

 

 

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

 

 

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

 

 

Is,Equals

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 ages)

… where x.age in ?1

 

 

NotIn

findByAgeNotIn(Collection 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)

 

 

posted @ 2018-11-19 20:16  Java梦工厂  阅读(439)  评论(0编辑  收藏  举报