关于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) |
|
|
来源:oschina
链接:https://my.oschina.net/u/4408791/blog/3746031