Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!
Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦
SpringData Jpa 极大简化了数据库访问层代码。 如何简化的呢? 使用了SpringDataJpa,我们的dao层中只需要写接口,就自动具有了增删改查、分页查询等方法。
Spring Data JPA 与 JPA和hibernate之间的关系 JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)
Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。 注意 真正干活的还是hibernate
使用Spring Data JPA,只需要按照框架的规范提供dao接口,不需要实现类就可以完成数据库的增删改查、分页查询等方法的定义,极大的简化了我们的开发过程。 规范
创建一个Dao层接口,并实现JpaRepository和JpaSpecificationExecutor提供相应的泛型 package com.zyc.springDateJpa.dao; import com.zyc.springDateJpa.entity.Customer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import java.util.List; /** * 符合SpringDataJpa的dao层接口规范 * JpaRepository<操作的实体类类型,实体类中主键属性的类型> * * 封装了基本CRUD操作 * JpaSpecificationExecutor<操作的实体类类型> * * 封装了复杂查询(分页) */ public interface CustomerDao extends JpaRepository<Customer,Long> ,JpaSpecificationExecutor<Customer> { public Customer findByCustName(String custName); }svae:保存或者更新
根据传递的对象是否存在主键id,如果没有id主键属性:保存存在id主键属性,根据id查询数据,更新数据.如果没查到,还是更新 Customer c = new Customer(); c.setCustName("zhuyc"); customerDao.save(c);springDataJpa会先查询,再删除;没查到,会报错
customerDao.deleteById(2l);在SpringDataJpa中我们只需要声明接口,框架会自动帮我们通过jdk动态代理生成接口实现类,然后注入导spring中。 动态代理对象中一般都是默认调用SimpleJpaRepository中的方法来工作的
@Query注解的使用非常简单,只需在方法上面标注该注解,同时提供一个JPQL查询语句即可
@Query(value="from Customer where custName = ?1") public Customer findJpql(String custName);通过索引
/** * 案例:根据客户名称和客户id查询客户 * jpql: from Customer where custName = ? and custId = ? * * 对于多个占位符参数 * 赋值的时候,默认的情况下,占位符的位置需要和方法参数中的位置保持一致 * * 可以指定占位符参数的位置 * ? 索引的方式,指定此占位的取值来源 */ @Query(value = "from Customer where custName = ?2 and custId = ?1") public Customer findCustNameAndId(Long id, String name);@Query : 代表的是进行查询 @Modifying:当前执行的是一个更新操作.有点组合的感觉,补充@Query
/** * * sql :update cst_customer set cust_name = ? where cust_id = ? * jpql : update Customer set custName = ? where custId = ? */ @Query(value = " update Customer set custName = ?2 where custId = ?1 ") @Modifying public void updateCustomer(long custId, String custName);@Rollback 设置是否自动回滚,本地测试:默认不回滚。
@Test @Transactional //添加事务的支持 @Rollback(value = true) public void testUpdateCustomer() { customerDao.updateCustomer(4l,"黑马程序员"); }@Query有一个nativeQuery属.
/** * sql : select * from cst_customer; * Query : 配置sql查询 * value : sql语句 * nativeQuery : 查询方式 * true : sql查询 * false:jpql查询(默认) * */ //@Query(value = " select * from cst_customer" ,nativeQuery = true) @Query(value="select * from cst_customer where cust_name like ?1",nativeQuery = true) public List<Object [] > findSql(String name);有时会用到
@Test public void testNativeQuery(){ Query query = em.createNativeQuery("select * from cst_customer "); List<Map<String,Object>> list = query.unwrap(NativeQuery.class).addScalar("cust_id", StandardBasicTypes.LONG).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list(); for(Map<String,Object> map:list){ System.out.println(map.values()); } }按照Spring Data JPA 定义的规则,查询方法以 findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。
/** * 方法名的约定: * findBy : 查询 * 对象中的属性名(首字母大写) : 查询的条件 * CustName * * 默认情况 : 使用 等于的方式查询 * 特殊的查询方式 * * findByCustName -- 根据客户名称查询 * * 再springdataJpa的运行阶段 * 会根据方法名称进行解析 findBy from xxx(实体类) * 属性名称 where custName = * * 1.findBy + 属性名称 (根据属性名称进行完成匹配的查询=) * 2.findBy + 属性名称 + “查询方式(Like | isnull)” * findByCustNameLike * 3.多条件查询 * findBy + 属性名 + “查询方式” + “多条件的连接符(and|or)” + 属性名 + “查询方式” */ public Customer findByCustName(String custName); public Customer findByCustNameLikeAndCustIndustry(String custName, String custIndustry);具体的关键字,使用方法和生产成SQL如下表所示