JPA(2)Spring Data JPA

mac2024-01-24  43

目录

一 概述推荐组合 二 特性和其他框架的关系二 搭建环境依赖dao测试 三 CRUD查询保存/更新删除根据id删除查询所有 四 执行过程五 复杂查询查询总数查询id是否存在getOneJPQL占位符实现更新 sql查询查询Map方法命名规则查询 参考

一 概述

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

二 搭建环境

依赖

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.zyc</groupId> <artifactId>springDateJpa</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springDateJpa</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

dao

使用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); }

测试

package com.zyc.springDateJpa; import com.zyc.springDateJpa.dao.CustomerDao; import com.zyc.springDateJpa.entity.Customer; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDateJpaApplicationTests { @Autowired private CustomerDao customerDao; @Test public void contextLoads() { Customer c = new Customer(); c.setCustName("zhuyc"); customerDao.save(c); } }

三 CRUD

查询

Optional<Customer> c = customerDao.findById(1l); System.out.println(c.get());

保存/更新

svae:保存或者更新

根据传递的对象是否存在主键id,如果没有id主键属性:保存存在id主键属性,根据id查询数据,更新数据.如果没查到,还是更新 Customer c = new Customer(); c.setCustName("zhuyc"); customerDao.save(c);

删除

根据id删除

springDataJpa会先查询,再删除;没查到,会报错

customerDao.deleteById(2l);

查询所有

List<Customer> list = customerDao.findAll(); for(Customer customer : list) { System.out.println(customer); }

四 执行过程

在SpringDataJpa中我们只需要声明接口,框架会自动帮我们通过jdk动态代理生成接口实现类,然后注入导spring中。 动态代理对象中一般都是默认调用SimpleJpaRepository中的方法来工作的

五 复杂查询

查询总数

long count = customerDao.count();

查询id是否存在

boolean exists = customerDao.existsById(4l);

getOne

findById: em.find() :立即加载getOne: em.getReference :延迟加载;返回的是一个客户的动态代理对象. 什么时候用,什么时候查询 Customer customer = customerDao.getOne(4l);

JPQL

@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,"黑马程序员"); }

sql查询

@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);

查询Map

有时会用到

@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如下表所示

参考

黑马Spring Data Jpa教学资料
最新回复(0)