简介

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 详解(自定义查询、分页、事务控制)相关推荐

  1. Mybatis Plus 入门 简单的CRUD 使用详解 条件查询 分页查询 DML操作 MP代码生成器

    Mybatis Plus入门 MP是 MybatisPlus,简称MP,是一个 Mybatis 的增强工具,在 Mybatis 的基础上只做增强不做改变.MP为简化开发.提高效率而生. 它已经封装好了 ...

  2. mvc jquery ajax分页实例,jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解,mvcpagerajax分页...

    jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解,mvcpagerajax分页 简单的两个步骤即可实现分页功能 //回调里面进行业务处理 function lo ...

  3. 【转载】CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数)...

    CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数) 2017-08-19 胡恩伟 汽车电子expert成长之路 内容提要 ...

  4. 详解 Spring 声明式事务

    一.引言 Spring的事务机制包括声明式事务和编程式事务. 编程式事务管理:Spring推荐使用 TransactionTemplate,实际开发中使用声明式事务较多. 声明式事务管理:将我们从复杂 ...

  5. Mysql高手系列 - 第8篇:详解排序和分页(order by limit),及存在的坑

    这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...

  6. Mysql系列 - 第八篇 :详解排序和分页(order by limit),及存在的坑

    这是Mysql系列第7篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选其一. 本章内容 详解排序查询 详解limit limit存在的坑 分 ...

  7. 玩转Mysql系列 - 第8篇:详解排序和分页(order by limit),及存在的坑

    打算提升sql技能的,可以加我微信itsoku,带你成为sql高手. 这是Mysql系列第8篇. 环境:mysql5.7.25,cmd命令中进行演示. 代码中被[]包含的表示可选,|符号分开的表示可选 ...

  8. Spring事务管理详解_基本原理_事务管理方式

    Spring事务管理详解_基本原理_事务管理方式 1. 事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象 ...

  9. Linux systemctl 详解自定义 systemd unit

    Linux systemctl 详解&自定义 systemd unit systemctl 序 大家都知道,我们安装了很多服务之后,使用 systemctl 来管理这些服务,比如开启.重启.关 ...

最新文章

  1. [kuangbin带你飞]专题四 最短路练习 B( POJ 2253) Frogger(spfa)
  2. .NET常用工具类(Utils.cs)
  3. Python全栈开发:socket
  4. 云原生持续交付的模式和实践
  5. 开发者编程时应该围着“程序”转吗?
  6. [python]pytest实现WEB UI自动化
  7. 由深圳的大树所想到的
  8. 《Java语言程序设计与数据结构》编程练习答案(第一章)
  9. 至强3系列服务器cpu吗,做3D MAX是要求CPU好一点 还是显卡好一点? CPU的话是界面CPU(i 系列)好还是服务器CPU(至强系列)好?...
  10. GPS精确授时方法研究-基于ublox GPS
  11. 手机怎么将视频制作成GIF?手机端动态图片制作的方法
  12. 华丽成长为IT高富帅、IT白富美(五)
  13. Android跳转第三方App,淘宝,微信,QQ等。
  14. AutoCAD 2018安装教程
  15. woj 1567 - D - Sloth's Angry(贪心)
  16. 这么多编程语言,初学者选择哪个比较好?
  17. 嵌入式学习笔记(5)驱动设计的硬件基础-接口和总线
  18. 杜君立:紧箍咒与纸枷锁
  19. 3天学会HTML:day1 基础
  20. Zookeeper-3.4.5安装步骤及异常处理

热门文章

  1. thinkpad装linux无线网卡驱动,ThinkPad E530 Fedora 20 下无线网卡驱动的安装
  2. Truffle+ganache进行区块链项目开发
  3. 中级会计职称考试可以带计算机么,中级会计师无纸化考试允许带计算器入场吗?...
  4. NYOJ - [第八届河南省程序设计大赛]引水工程(最小生成树)
  5. 黄金原野的 “去中心化认证“技术
  6. Using CAR for Smurf Attack Mitigation,使用承诺速率控制预防smurf攻击
  7. Python进行克里金插值可视化
  8. 【DevCloud · 敏捷智库】软件开发团队如何管理琐碎、突发性任务(内附下载材料)
  9. Webservice与Servlet
  10. 习题 3-6 纵横字谜的答案