SpringData JPA 详解(自定义查询、分页、事务控制)
简介
SpringData JPA是 JPA的一种实现,极大的简化了JPA的开发,原始JPA的开发,需要创建实体管理工厂,使用实体管理器定义各种查询进行CRUD操作,而SpringData JPA只需要通过核心接口Repository和它的子类就能很方便的操作数据库。
Repository
1. Repository:最顶层的接口,一个空的接口,统一所有的Repository类型,并且能够让组件扫描的时候能够自动识别
2. CrudRepository: Repository的子接口,提供CRUD的操作
3. PagingAndSortingRepository: CrudRepository的子接口,添加了分页和排序的功能
4. JpaRepository: 是PagingAndSortingRepository的子接口,增加一些实用的功能,比如批量操作
5. JpaSpecificationExecutor:来定义复杂查询
使用SpringData JPA
将SpringDataJPA整合Spring,将EntityManagerFactory的创建交给Spring容器,只需要在xml中配置JPA的Repository的接口位置,就可以很方便的获取到Repository的bean,使用时候直接在service层注入定义的repository.
配置文件:
<?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.xsdhttp://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- 配置自动扫描的包 --><context:component-scan base-package="cn.bing"/><!-- 配置数据库资源文件的位置--><context:property-placeholder location="classpath:db.properties"/><bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><!-- jdbc.properties 中的key必须定义为 jdbc.username,格式开头的 --><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/><property name="url" value="${jdbc.url}"/><property name="driverClassName" value="${jdbc.driverClassName}"/></bean><!-- 2. 配置 JPA 的 EntityManagerFactory --><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><!-- 配置实体所在的包 --><property name="packagesToScan" value="cn.bing.pojo"/><!-- 配置jpa的属性 --><property name="jpaProperties"><props><!-- 二级缓存相关 --><!--<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop><prop key="net.sf.ehcache.configurationResourceName">ehcache-hibernate.xml</prop>--><!-- 生成的数据表的列的映射策略 --><prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop><!-- hibernate 基本属性 --><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><!-- 3. 配置事务管理器 --><bean id="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager"><property name="entityManagerFactory" ref="entityManagerFactory"/></bean><!-- 4. 配置支持注解的事务 --><tx:annotation-driven transaction-manager="transactionManager"/><!-- 5. 配置 SpringData --><!-- 加入 jpa 的命名空间 --><!-- base-package: 扫描 Repository Bean 所在的 package --><jpa:repositories base-package="cn.bing.dao"entity-manager-factory-ref="entityManagerFactory"/></beans>
1 . 引入Jar
2. 创建实体
@Entity表示这个类是一个实体类,参与JPA和数据库表的映射
@Table表示具体映射的表名
@Id表示这个字段是主键,@GeneratedValue表示这个主键的生成策略
@Column表示映射到数据库的表的字段名,字段名和表字段不一致,修改注解@Column的name属性
@Entity
@Table(name = "user")
public class User {@Id@GeneratedValue(strategy = GenerationType.AUTO)private Integer id;@Columnprivate Integer age;@Columnprivate String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
3. 编写接口继承Repository的子类,并且需要在spring的配置文件配置
<!-- 5. 配置 SpringData --><!-- 加入 jpa 的命名空间 --><!-- base-package: 扫描 Repository Bean 所在的 package --><jpa:repositories base-package="cn.bing.dao" entity-manager-factory-ref="entityManagerFactory"/>
一般都是选择继承JpaRepository方便直接调用现有的方法进行CRUD,继承JpaSpecificationExecutor则是方便定义一些复杂的查询。
JpaRespository<T,D> T 表示实体,D表示实体的主键ID类型
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {}
自定义接口继承父类的Repository后,自动获取的操作数据的API,只能进行简单的操作,需要自定义查询。
repository.findOne(1);//根据id查询
repository.findAll();//查询
repository.delete(new User());//delete操作
repository.saveAndFlush(new User());//insert操作
关于SpringData JPA查询的定义
1. spring data 对于定义方法的查询策略
查询策略是spring data 根据方法名称取解析用户的查询意图,第一种,根据方法的命名规则解析,第二种是通过Query去解析,如果两种同时存在时,springdata按照那种解析方法名,这就是spring data的查询策略,查询策略可以在<jpa:repositorys/> 属性query-lookup-strategy 配置
CREATE: 通过解析方法的名称来创建查询,也就是下面的规则1
USE_DECLARED_QUERY:根据定义好的语句去查询,如果找不到,抛出异常信息。查询语句定义在某个注解或者方法上。
CREATE_IF_NOT_FOUND:优先查询方法上是否有定义好的查询语句,如果没有,则按照方法名称解析,这是默认的策略。
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {//根据springData的关键字命名方法名称,可以不用写实现类List<User> findByNameAndAge(String name, Integer age);List<User> findByNameLikeAndAge(String name, Integer age);//@Query注解里面写JPQL语句,定义查询@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")User readId(Integer id);//Query注解也可以定义SQL语句,只要将nativeQuery属性改为true@Query(nativeQuery = true, value = "select name from user where id = :id")String findNamebyId(@Param("id")Integer id);//@Modifying修饰方法,告知SpringData,这是一个UPATE或者DELETE操作//在service层的方法上添加事务操作@Modifying@Query(nativeQuery = true,value = "update user set name = ?1 where id = ?2 ")int updateUserNameById(String name,Integer id);}
规则1:根据SpringData JPA的关键字定义方法名,方法的参数顺序和关键字的顺序一致,名称可以不一致。
Spring Data JPA对方法名称进行解析的时候,会将一些无用的前缀名自动去除,比如find、findBy、read、readBy,然后根据关键字解析成对应JPQL语句。也要注意方法的参数顺序和定义的关键字的顺序一致。
规则2:定义方法时候,上面加上注解@Query,默认nativeQuery是false,此时value填入的是JPQL语句,修改nativeQuery是true,就能够写入SQL语句
//@Query注解里面写JPQL语句,定义查询@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")User readId(Integer id);//Query注解也可以定义SQL语句,只要将nativeQuery属性改为true@Query(nativeQuery = true, value = "select name from user where id = :id")String findNamebyId(@Param("id")Integer id);
注意参数注入的方式有两种:
1. ?下标,下标从1开始
2. :xxx ...:yyy,xxx和yyy必须是实体的属性名,并且方法参数上加上对应的注解@Param("xxx")和@Param('yyy')
@Modify和事务
可以通过JPQL语句定义update/delete,此时在@Query注解中定义,必须加上@Modify,告诉spring data 这是一个update/delete操作。
update/delete操作需要事务支持,必须在service层,添加事务,因为spring data,默认情况下每个方法是只读事务,不能完成update/delete操作。
public interface UserRepository extends JpaRepository<User,Integer>, JpaSpecificationExecutor<User> {//根据springData的关键字命名方法名称,可以不用写实现类List<User> findByNameAndAge(String name, Integer age);List<User> findByNameLikeAndAge(String name, Integer age);//@Query注解里面写JPQL语句,定义查询@Query(nativeQuery = false,value = " SELECT p FROM User p WHERE id = ?1")User readId(Integer id);//Query注解也可以定义SQL语句,只要将nativeQuery属性改为true@Query(nativeQuery = true, value = "select name from user where id = :id")String findNamebyId(@Param("id")Integer id);//@Modifying修饰方法,告知SpringData,这是一个UPATE或者DELETE操作//在service层的方法上添加事务操作@Modifying@Query(nativeQuery = true,value = "update user set name = ?1 where id = ?2 ")int updateUserNameById(String name,Integer id);
}
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserRepository repository;//对于SpringData jpa的update或者delete操作,必须在service层使用事务,直接使用仓库的方法会报错//另外,SpringData jpa 的 JPQL语法不支持insert@Transactional(propagation = Propagation.REQUIRED)public int updateUserNameById(String name,Integer id){return repository.updateUserNameById(name,id);}}
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringDataTest {@Autowiredprivate UserRepository repository;@Autowiredprivate UserService service;@Testpublic void test(){service.updateUserNameById("张三",1);}
}
分页和模糊查询
模糊查询
需要注意的是%%外面不需要再加上''
//模糊查询@Query(nativeQuery = true,value = " select * from user where name like %?1% ")User findUserByLikeName(String name);
分页对象
1. 要求自定义的Repository必须继承了PagingAndSortingRepository或者他的子类JpaRepository
2. 分页对象是Pageable接口的实现类PageRequest
public class PageRequest implements Pageable, Serializable {private static final long serialVersionUID = 8280485938848398236L;private final int page;//页码,从0开始,0表示第一页,1表示第二页,以此类推private final int size;//每页显示的记录数private final Sort sort;//排序规则
Sort对象,定义排序规则,常用的是下面这种构造函数,支持可变参数的
public Sort(Sort.Direction direction, String... properties) {this(direction, (List)(properties == null ? new ArrayList() : Arrays.asList(properties)));}
定义分页查询,只需要将查询的参数和分页对象作为参数。
Page<User> findByNameLike(String str , Pageable pageable);
@RunWith(value = SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class SpringDataTest {@Autowiredprivate UserRepository repository;@Testpublic void test(){/*** SpringData jpa 的分页* Pageable接口的实现类是PageRequest,Page接口的实现类是PageImpl。*/Pageable page = new PageRequest(0,2,new Sort(Sort.Direction.DESC,"id"));Page<User> personList = repository.findByNameLike("张%",page);System.out.println("总记录数" + personList.getTotalElements());System.out.println("当前第几页: " + (personList.getNumber() + 1));System.out.println("总页数: " + personList.getTotalPages());System.out.println("当前页面的记录数:" + personList.getContent());System.out.println("当前页面的记录数: " + personList.getNumberOfElements());}
}
SpringData JPA 详解(自定义查询、分页、事务控制)相关推荐
- Mybatis Plus 入门 简单的CRUD 使用详解 条件查询 分页查询 DML操作 MP代码生成器
Mybatis Plus入门 MP是 MybatisPlus,简称MP,是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变.MP为简化开发.提高效率而生. 它已经封装好了 ...
- mvc jquery ajax分页实例,jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解,mvcpagerajax分页...
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解,mvcpagerajax分页 简单的两个步骤即可实现分页功能 //回调里面进行业务处理 function lo ...
- 【转载】CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数)...
CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数) 2017-08-19 胡恩伟 汽车电子expert成长之路 内容提要 ...
- 详解 Spring 声明式事务
一.引言 Spring的事务机制包括声明式事务和编程式事务. 编程式事务管理:Spring推荐使用 TransactionTemplate,实际开发中使用声明式事务较多. 声明式事务管理:将我们从复杂 ...
- Mysql高手系列 - 第8篇:详解排序和分页(order by limit),及存在的坑
这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...
- Mysql系列 - 第八篇 :详解排序和分页(order by limit),及存在的坑
这是Mysql系列第7篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...
- 玩转Mysql系列 - 第8篇:详解排序和分页(order by limit),及存在的坑
打算提升sql技能的,可以加我微信itsoku,带你成为sql高手. 这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选 ...
- Spring事务管理详解_基本原理_事务管理方式
Spring事务管理详解_基本原理_事务管理方式 1. 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象 ...
- Linux systemctl 详解自定义 systemd unit
Linux systemctl 详解&自定义 systemd unit systemctl 序 大家都知道,我们安装了很多服务之后,使用 systemctl 来管理这些服务,比如开启.重启.关 ...
最新文章
- [kuangbin带你飞]专题四 最短路练习 B( POJ 2253) Frogger(spfa)
- .NET常用工具类(Utils.cs)
- Python全栈开发:socket
- 云原生持续交付的模式和实践
- 开发者编程时应该围着“程序”转吗?
- [python]pytest实现WEB UI自动化
- 由深圳的大树所想到的
- 《Java语言程序设计与数据结构》编程练习答案(第一章)
- 至强3系列服务器cpu吗,做3D MAX是要求CPU好一点 还是显卡好一点? CPU的话是界面CPU(i 系列)好还是服务器CPU(至强系列)好?...
- GPS精确授时方法研究-基于ublox GPS
- 手机怎么将视频制作成GIF?手机端动态图片制作的方法
- 华丽成长为IT高富帅、IT白富美(五)
- Android跳转第三方App,淘宝,微信,QQ等。
- AutoCAD 2018安装教程
- woj 1567 - D - Sloth's Angry(贪心)
- 这么多编程语言,初学者选择哪个比较好?
- 嵌入式学习笔记(5)驱动设计的硬件基础-接口和总线
- 杜君立:紧箍咒与纸枷锁
- 3天学会HTML:day1 基础
- Zookeeper-3.4.5安装步骤及异常处理
热门文章
- thinkpad装linux无线网卡驱动,ThinkPad E530 Fedora 20 下无线网卡驱动的安装
- Truffle+ganache进行区块链项目开发
- 中级会计职称考试可以带计算机么,中级会计师无纸化考试允许带计算器入场吗?...
- NYOJ - [第八届河南省程序设计大赛]引水工程(最小生成树)
- 黄金原野的 “去中心化认证“技术
- Using CAR for Smurf Attack Mitigation,使用承诺速率控制预防smurf攻击
- Python进行克里金插值可视化
- 【DevCloud · 敏捷智库】软件开发团队如何管理琐碎、突发性任务(内附下载材料)
- Webservice与Servlet
- 习题 3-6 纵横字谜的答案