Spring整合SpringDataJpa
SpringDataJPA:
SpringDataJPA 是springdata 项目下的一个模块。提供了一套基于JPA 标准操作数据库的简化方案。底层默认的是依赖 HibernateJPA 来实现的。
SpringDataJPA 的技术特点:
只需要定义接口并继承 Spring Data JPA 中提供的接口,不需要编写接口实现类。
创建Spring Data JPA 项目
1、导入jar包
2、配置文件
<?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:aop="http://www.springframework.org/schema/aop"
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/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.8.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置resource文件的工具类 -->
<context:property-placeholder location="classpath:db.properties"/>
<!-- 配置c3p0-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="jdbcUrl" value="${db.url}"></property>
<property name="driverClass" value="${db.dirver.class}"></property>
<property name="user" value="${db.user}"></property>
<property name="password" value="${db.password}"></property>
</bean>
<!-- 创建 Hibernate 上下文对象 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
<!-- jpa适配器 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- 支持的数据库类型 -->
<property name="Database" value="MYSQL" />
<!-- 正向工程 -->
<property name="generateDdl" value="true" />
<!-- 控制台输出sql -->
<property name="showSql" value="true" />
</bean>
</property>
<!-- 包扫描 -->
<property name="packagesToScan">
<list>
<value>com.sxt.pojo</value>
</list>
</property>
</bean>
<!-- 配置Hibernate的事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>
<!-- 配置开启事务处理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!--配置springIOC注解扫描 -->
<context:component-scan base-package="com.sxt" />
<!-- base-package:扫描 dao 接口所在的包 -->
<jpa:repositories base-package="com.sxt.dao" />
</beans>
3、定义接口
4、编写测试代码
5、save 方法,可以理解为 update , 当数据表中有该值,则更新,没有,则新增。
SpringDataJPA 的接口继承结构
1、Repository接口
Repository 接口是 SpringDataJPA 中为我我们提供的所有接口中的顶层接口
Repository 提供了两种查询方式的支持
1、基于方法名称命名规则查询
2、基于@Query 注解查询
1.1、方法名称命名规则查询
规则:findBy(关键字)+属性名称(属性名称的首字母大写)+查询条件(首字母大写)
其中属性名称(属性名称的首字母大写),其余的全部都是小写。
方法名称命名规则查询适用于条件简单的查询,当条件比较复杂时,在命名的时候是及其不方便的,这时可以选择使用 @Query 注解进行查询。
1 And 并且
2 Or 或
3 Is,Equals 等于
4 Between 两者之间
5 LessThan 小于
6 LessThanEqual 小于等于
7 GreaterThan 大于
8 GreaterThanEqual 大于等于
9 After 之后(时间) >
10 Before 之前(时间) <
11 IsNull 等于Null
12 IsNotNull,NotNull 不等于Null
13 Like 模糊查询。查询件中需要自己加 %
14 NotLike 不在模糊范围内。查询件中需要自己加 %
15 StartingWith 以某开头
16 EndingWith 以某结束
17 Containing 包含某
18 OrderBy 排序
19 Not 不等于
20 In 某范围内
21 NotIn 某范围外
22 True 真
23 False 假
24 IgnoreCase 忽略大小写
测试代码
根据用户名查找用户信息,查询结果如下
1.2、基于@Query 注解的查询
1.2.1、通过 JPQL 语句查询
Dao
测试方法
1.2.2通过 SQL 语句查询
在使用 @Query 注解查询时,需要注意在 该注解中开启 nativeQuery 属性,该属性的作用是将否将 sql 语句转译。
在spring data jpa 中使用 @Query注解,会把 "from User where username = ? " 转译为标准的 sql 语句,而是用 nativceQuery 属性可以决定是否开启转译,该属性默认值为 false 。
Dao
测试方法
3、更新操作
@Modifying 注解,该注解通知了spring data jpa ,告诉该方法是一个 update 或 delete 操作 。在增删改操作中,需要在测试类中对测试方法事务开启,回滚关闭。
CrudRepository接口的使用
在该接口的实现类中,DML的操作在源码中已经添加了 @Transactional,在测试代码中对数据的 DML 操作就不再需要添加注解。
Dao
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class UserDaoImplTest {
@Autowired
private UserDao userDao;
/**添加单条数据**/
@Test
public void test01(){
User user = new User();
user.setUsername("令狐冲");
user.setUserage(25);
userDao.save(user);
}
/**添加多条数据**/
@Test
public void test02(){
User user1 = new User();
user1.setUsername("任盈盈");
user1.setUserage(18);
User user2 = new User();
user2.setUsername("风清扬");
user2.setUserage(66);
List<User> list = new ArrayList<>();
list.add(user1);
list.add(user2);
userDao.save(list);
}
/**查询全部数据**/
@Test
public void test03(){
List<User> findAll = (List<User>)userDao.findAll();
for (User user : findAll) {
System.out.println(user);
}
}
/**删除数据**/
@Test
public void test04(){
userDao.delete(1);
}
/**更新数据方式一**/
@Test
public void test05(){
User findOne = userDao.findOne(2);
findOne.setUserage(17);
userDao.save(findOne);
}
/**更新数据方式二**/
@Test
@Transactional
@Rollback(false)
public void test06(){
User findOne = userDao.findOne(2);
findOne.setUserage(16);
}
}
PagingAndSortingRepository接口
1、分页处理
该接口下的findAll方法中需要传入一个 pageable ,而 pageable 是一个接口,所以需要先创建该接口的实现类。
pageable 接口下有两个实现类
在pageRequest 中封装了当前页的索引和每页显示几条数据的设置。
dao
测试
2、排序处理
3、多列排序
其中第一个参数表示是降序还是升序(此处表示升序),第二个参数表示你要按你的entity(记住是entity中声明的变量,不是数据库中表对应的字段)中的那个变量进行排序。
4、分页排序
JpaRepository接口
JpaRepository 接口是使用的最多的接口。其特点是可以帮助将其他接口的方法的返回值做适配处理。可以在开发时更方便的使用这些方法。
JpaSpecificationExecutor接口
spring data jpa 通过创建方法名来做查询,只能做简单的查询,那如果我们要做复杂一些的查询呢,多条件分页怎么办,这里,spring data jpa为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询。
1、单条件查询
dao 层接口,在使用 JpaSpecificationExcutor 接口时,需要配置 Repository 接口中的任意一个接口。JpaSpecificationExcutor 接口是一个独立的接口。在 jpa 的底层动态代理时,如果是一个 JpaSpecificationExcutor 接口,是无法将代理注入的。
测试类
* toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb)
* Predicate 定义了查询条件
* Root<User> root :根对象。封装了查询条件的对象
* CriteriaQuery<?> query:定义了一个基本的查询.一般不使用
* CriteriaBuilder cb:创建一个查询条件
2、多条件查询 - 方式一and
在该方式一中,将查询条件封装到了集合中,将集合进行了返回,但是该静态内容类需要返回的对象是 Predicate ,
所以这里定义了一个 Predicate 数组,其数组的长度是集合的size()。
3、多条件查询 - 方式二or
4、分页查询
自定义 Repository接口
1、创建接口
2、让 UserDao 接口继承该接口。
3、编写实现类,注意。
这里的实现类不是自定义接口的实现类,而是 UserDao 的实现类。
默认情况下, Spring Data 会在 base-package 中查找 "接口名Impl" 作为实现类。
所以在创建接口实现类的时候需要 加上Impl , 命名规则 接口名 + Impl 。
在 find 方法中给定的参数, 第一个是 Entity 的类型 , 第二个是拿什么作为条件进行查询。
4、代码测试