
SpringData-JPA
一,springdata简介
1,orm思想
主要的目的就是操作实体类就相当于操作数据库表
实现:需要建立映射关系
实体类和表的映射关系
实体类中属性和表中字段的映射关系
不需要重点去关注SQL语句
实现了orm思想的框架: MyBatis(半自动ORM); hibernate(全自动)
2,hibernate框架
hibernate是一个开源的对象关系映射框架,对JDBC进行了非常轻量化的对象封装,使POJO和数据库表建立映射关系,可以自动生成SQL语句,自动执行
3,JPA规范
jpa是一套规范全称(Java Persistence API )既Java持久化操作, sun公司研发 供各大厂商实现这套规范,内部是有接口和抽象类组成
Jpa的优势:
1.标准化 是一套规范
2.容器级特性的支持,
支持大数据集,事务,并发等容器级的事务
3.
二,JPA的基本操作
1.)创建persistence.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<!--需要配置persistence-unit节点
持久化单元:
name:持久化单元名称
transaction-type:事务管理的方式
JTA:分布式事务管理
RESOURCE_LOCAL:本地事务管理
-->
<persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
<!--jpa的实现方式 -->
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<!--可选配置:配置jpa实现方的配置信息-->
<properties>
<!-- 数据库信息
用户名,javax.persistence.jdbc.user
密码, javax.persistence.jdbc.password
驱动, javax.persistence.jdbc.driver
数据库地址 javax.persistence.jdbc.url
-->
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="980311"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql:///jpa"/>
<!--配置jpa实现方(hibernate)的配置信息
显示sql : false|true
自动创建数据库表 : hibernate.hbm2ddl.auto
create : 程序运行时创建数据库表(如果有表,先删除表再创建)
update :程序运行时创建表(如果有表,不会创建表)
none :不会创建表
-->
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
2.)创建实体类和映射关系
/**
* @author 李phCode
* @create 2020 -08 -07 13:38
* 客户的实体类
* 配置映射关系
* 1.实体类和表的映射关系
* 2.实体类中属性和表中字段的映射关系
*/
@Entity
@Table(name = "cst_customer")//标注数据库表
public class Customer {
/*
* @Id 声明主键的配置
* @GeneratedValue 配置主键的生成策略
* GenerationType.IDENTITY 自增 适合MySQL
* 底层数据库必须支持自动增长
* GenerationType.SEQUENCE 序列 适合Oracle
* 底层数据库必须支持序列
* GenerationType.TABLE jpa提供的一种机制,通过一张数据库表的形式帮我们完成自动增长
* GenerationType.AUTO 由程序自动的帮助我们选择主键的生成策略
* */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;//客户主键
@Column(name = "cust_name")
private String custName;//客户名称
3).创建demo测试保存
/*
* 测试jpa的保存
* 保存一个客户到数据库中
* jpa的操作步骤
* 1.加载配置文件创建工厂(实体类管理工厂)
* Persistence:静态方法(根据持久化单元名称创建实体类管理工厂)
* <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
* createEntityManagerFactory(持久化单元名称)
* 作用:创建实体管理工厂
* 2.通过实体类管理器工厂获取实体类管理器
* EntityManagerFactory:获取EntityManager对象
* createEntityManager:维护
* 数据库信息,缓存信息,所有实体管理对象
* 再创建EntityManagerFactory的过程中会根据配置创建数据库表
* 但是EntityManagerFactory创建的过程中会浪费资源(耗时,因为维护太多东西)
* 特点:
* 是线程安全的对象,多个线程访问同一个EntityManagerFactory不会有线程安全问题
* 解决:
* 创建公共的EntityManagerFactory的对象,使用静态代码块
* 3.获取事务对象,开启事务
* merge(更新);
* remove(删除);
* find/getReference(根据id查询)
* 4.完成CRUD
* 5.提交事务(回滚事务)
* 6.释放资源
* */
@Test
public void testSave() {
//1.加载配置文件创建工厂(实体类管理工厂)
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
//2.通过实体类管理器工厂获取实体类管理器
EntityManager entityManager = factory.createEntityManager();
//3.获取事务对象,开启事务我
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();//开启事务
//4.完成CRUD 保存
Customer customer = new Customer();
customer.setCustName("百度");
customer.setCustIndustry("工具");
customer.setCustAddress("北京");
customer.setCustSource("传真");
customer.setCustLevel("3");
customer.setCustPhone("34232432532");
entityManager.persist(customer);//保存
//5.提交事务(回滚事务)
transaction.commit();
//6.释放资源
entityManager.close();
factory.close();
}
4.)解决EntityManagerFactory耗时
/**
* @author 李ph Code
* @create 2020 -08 -08 14:46
* 通过代码快的方式,当程序第一次访问这个类的时候,会创建一个公共的实体管理工厂对象
* 第一次访问getEntityManager方法:经过静态块创建一个factory对象,在调用方法创建一个EntityManager对象
* 第二次访问getEntityManager方法:直接通过一个已经创建好的factory对象,创建EntityManager对象
*/
public class JpaUtils {
private static EntityManagerFactory entityManagerFactory;
static {
//1.加载配置文件 创建enityManagerFactory
entityManagerFactory = Persistence.createEntityManagerFactory("");
}
/*
* 获取EntityManager对象
* */
public static EntityManager getEntityManager() {
return entityManagerFactory.createEntityManager();
}
}
5.)使用工具类
/*
* 根据id查询
* */
@Test
public void testFind() {
//1.获取工具类的entity Manager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
1 //3.增删改查 根据id查询
Customer customer = entityManager.find(Customer.class, 1l);
System.out.println("customer = " + customer);
2 //先查询在删除
Customer customer = entityManager.find(Customer.class, 2l);
entityManager.remove(customer);
3 //先查询在修改
Customer customer = entityManager.find(Customer.class, 1l);
customer.setCustName("百度u");
4 //查询全部
String jpql = "from org.ph.Bean.Customer";
Query query = entityManager.createQuery(jpql);
List resultList = query.getResultList();
for (Object o : resultList) {
System.out.println("o = " + o);
}
5 //分页
String jpql = "from Customer";
Query query = entityManager.createQuery(jpql);
//起始分页
query.setFirstResult(1);
//每页查询的条数
query.setMaxResults(2);
List resultList = query.getResultList();
for (Object o : resultList) {
System.out.println("o = " + o);
}
6 //like 查询
String jpql = "from Customer where custName like ? ";
Query query = entityManager.createQuery(jpql);
//占位符参数 从1开始
query.setParameter(1, "测%"); //以北开头的
List resultList = query.getResultList();
for (Object o : resultList) {
System.out.println("o = " + o);
}
//4.提交事务
transaction.commit();
//5.释放资源
entityManager.close();
}
6.Find和getReference
/*
* 根据id查询
* Find方法查询:
* 调用fin方法的时候就会发送SQL语句到数据库
* */
@Test
public void testFind() {
//1.获取工具类的entity Manager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.增删改查
Customer customer = entityManager.find(Customer.class, 1l);
System.out.println("customer = " + customer);
//4.提交事务
transaction.commit();
//5.释放资源
entityManager.close();
}
/*
* 根据id查询
* getReference方法 懒加载
* 1.这个方法会获取动态代理对象
* 2.调用getReference方法不会立即查询SQL
* 当调用查询结果的时候才会查询SQL语句,也就什么时候用 什么时候查询数据库
*
* */
@Test
public void testReference() {
//1.获取工具类的entity Manager
EntityManager entityManager = JpaUtils.getEntityManager();
//2.开启事务
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
//3.增删改查
Customer customer = entityManager.getReference(Customer.class, 1l);
System.out.println("customer = " + customer);
//4.提交事务
transaction.commit();
//5.释放资源
entityManager.close();
}
三,SpringDataJpa
1.创建spring-data-jpademo
1.)springdatajpa的maven依赖
<properties>
<spring.version>4.2.4.RELEASE</spring.version>
<hibernate.version>5.0.7.Final</hibernate.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<c3p0.version>0.9.1.2</c3p0.version>
<mysql.version>5.1.6</mysql.version>
</properties>
<dependencies>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<!-- spring beg -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring end -->
<!-- hibernate beg -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.2.1.Final</version>
</dependency>
<!-- hibernate end -->
<!-- c3p0 beg -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>${c3p0.version}</version>
</dependency>
<!-- c3p0 end -->
<!-- log end -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<!-- el beg 使用spring data jpa 必须引入 -->
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>javax.el</artifactId>
<version>2.2.4</version>
</dependency>
<!-- el end -->
</dependencies>
2.)springdata jap整合创建application.xml的配置文件
<?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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<!--spring 和 spring data jpa的配置-->
<!-- 1.创建entityManagerFactory对象交给spring容器管理-->
<bean id="entityManagerFactoty" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--配置的扫描的包(实体类所在的包) -->
<property name="packagesToScan" value="org.ph.Bean"/>
<!-- jpa的实现厂家 -->
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider"/>
</property>
<!--jpa的供应商适配器 -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!--配置是否自动创建数据库表 -->
<property name="generateDdl" value="false"/>
<!--指定数据库类型 是枚举类型
public enum Database {
DEFAULT, DB2, DERBY, H2, HSQL,
INFORMIX, MYSQL, ORACLE, POSTGRESQL,
SQL_SERVER, SYBASE;
-->
<property name="database" value="MYSQL"/>
<!--数据库方言:支持的特有语法 -->
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
<!--是否显示sql -->
<property name="showSql" value="true"/>
</bean>
</property>
<!--jpa的方言 :高级的特性 -->
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
</bean>
<!--2.创建数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="980311"></property>
<property name="jdbcUrl" value="jdbc:mysql:///jpa"></property>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
</bean>
<!--3.整合spring dataJpa-->
<jpa:repositories base-package="cn.itcast.dao" transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactoty"></jpa:repositories>
<!--4.配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactoty"></property>
</bean>
<!-- 4.txAdvice-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="insert*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 5.aop-->
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* cn.itcast.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
</aop:config>
<!--5.声明式事务 -->
<!-- 6. 配置包扫描-->
<context:component-scan base-package="cn.itcast"></context:component-scan>
</beans>
3.)实体类
/**
* @author 李phCode
* @create 2020 -08 -07 13:38
* 客户的实体类
* 配置映射关系
* 1.实体类和表的映射关系
* 2.实体类中属性和表中字段的映射关系
*/
@Entity
@Table(name = "cst_customer")
@Proxy(lazy = false)
public class Customer {
/*
* @Id 声明主键的配置
* @GeneratedValue 配置主键的生成策略
* GenerationType.IDENTITY 自增 适合MySQL
* 底层数据库必须支持自动增长
* GenerationType.SEQUENCE 序列 适合Oracle
* 底层数据库必须支持序列
* GenerationType.TABLE jpa提供的一种机制,通过一张数据库表的形式帮我们完成自动增长
* GenerationType.AUTO 由程序自动的帮助我们选择主键的生成策略
* */
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "cust_id")
private Long custId;//客户主键
@Column(name = "cust_name")
private String custName;//客户名称
@Column(name = "cust_source")
private String custSource;//客户来源
@Column(name = "cust_level")
private String custLevel;//客户级别
@Column(name = "cust_industry")
private String custIndustry;//客户所属行业
@Column(name = "cust_phone")
private String custPhone;//客户的联系方式
@Column(name = "cust_address")
private String custAddress;//客户地址
...set get
4.)Dao接口
springdatajpa不需要实现类,不需要定义接口 继承
/**
* @author 李phCode
* @create 2020 -08 -09 19:03
* SpringDataJpa的dao接口的规范
* JpaRepository<操作的实体类对象类型,实体类中主键属性的类型>
* 封装了基本的CRUD操作
* JpaSpecificationExecutor<操作实体类类型>
* 封装了复杂操作(分页,,)
*/
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
}
5.)测试CRUD
@RunWith(SpringJUnit4ClassRunner.class)//声明spring提供的单元测试环境
@ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
public class CustomerDaoTest {
@Autowired
private CustomerDao customerDao;//获取容器中的dao
/*更新*/
@Test
public void UpdaCus() {
Customer one = customerDao.findOne(2l); //先查询
one.setCustName("Java");
one.setCustAddress("上海");
one.setCustLevel("4");
customerDao.save(one);
}
/*根据id查询*/
@Test
public void SeleIDOne() {
Customer one = customerDao.getOne(1l);
System.out.println("one = " + one);
}
/*删除*/
customerDao.delete(4l);
/*查询所有*/
List<Customer> all = customerDao.findAll();
for (Customer customer : all) {
System.out.println("customer = " + customer);
}
/*保存
* save:
* if(id!=null){
* query and update
* }else{
* save
* }
* */
Customer customer = new Customer();
customer.setCustName("Java");
customer.setCustAddress("上海");
customer.setCustLevel("2");
customerDao.save(customer);
2.SpringData-Jpa的运行过程和原理
1.通过的JdkDynamicAopProxy的invoke方法创建了一个动态代理对象(接口实现的那两个)
(SimpleJpaRepository<T, ID extends Serializable> implements JpaRepository<T, ID>, JpaSpecificationExecutor)
2.SimpleJpaRepository当中封装了JPA的操作(借助jpa的api实现CURD)
3.通过hibernate完成数据库的操作
3.复杂查询
/*
* 根据id查询
* findOne:
* em.find() :立即加载
* getOne:
* em.getReference :延迟加载
* 返回的是一个客户的动态代理对象
* @Transactional:保证正常运行
*
* */
@Test
@Transactional
public void GetOne() {
Customer one = customerDao.getOne(1l);
System.out.println("one = " + one); //使用输出的时候在查询数据库:延迟加载
}
1.借助接口的定义好的方法完成查询
2.jpql的查询(jpa query language)
语法类似SQL语句,但是jpql查询的是类的属性字段
用法:
需要在接口上配置jpql语句,使用注解@query
/*
* 根据客户名称和id查询
* jpql: from Customer where custName= ? nad custid= ?
* @Query(value = "from Customer where custName= ?1 and custId= ?2")
* 还可以根据坐标指定下标
* */
@Query(value = "from Customer where custName= ? and custId= ?")
Customer FindCustNameAndId(String name, Long id);
/*更新语句*/
@Query(value = "update Customer set custName= ? ,custAddress = ? where custId=?")
@Modifying
int CustUpda(String name, String address, Long id);
4.SQL语句的查询
使用:
1.在dao接口上配置方法
2.只用注解配置SQL语句
3.使用@Query
value:jpql语句
nativeQuery: false(使用jpql语句)/ true(使用本地查询:SQL语句)
/*使用SQL语句查询*/
@Query(value ="select * from cst_customer" ,nativeQuery = true)
List<Customer> Finfall();
/*使用SQL语句模糊查询*/
@Query(value = "select * from cst_customer where cust_name like ?", nativeQuery = true)
List<Customer> FindLike(String name);
5.方法名规则查询
是对jpql更深一层的封装
只需要按照springdataJpa 提供的方法名规则定义方法不需要在配置jpql语句
用法规则:
findBy开头代表查询
对象属性名首字母大写 查询的条件
/*使用SpringDataJpa的方法名约定
* findBy :查询
* 对象名首字母大写,查询的条件
* CustName
* 默认情况使用等于查询
* finByCUstName
* 根据客户的名称查询
* 1.findBy + 属性名称 (根据属性名称进行完成匹配的查询)
* 2.findBy + 属性名称 + 查询方式 (like IsNull)
* 3.多条件查询
* finBY + 属性名 + 查询方式 + 多条件的连接符(and or )+ 属性名 + 查询方式
* */
6.Specifications动态查询
1.)Specifications动态查询
public interface JpaSpecificationExecutor<T> {
//查询单个对象
T findOne(Specification<T> spec);
//查询全部
List<T> findAll(Specification<T> spec);
//查询分页 Pageable 分页参数
//Page 返回值 分页PageBean(page是springdatajpa提供的内置对象)
Page<T> findAll(Specification<T> spec, Pageable pageable);
//查询全部 Sort 排序参数
List<T> findAll(Specification<T> spec, Sort sort);
//统计数量
long count(Specification<T> spec);
Specification://查询条件
//需要我们自己定义Specification实现类
//Root:查询的根对象(查询的任何属性都可以在跟对象内获取)
//CriteriaQuery:顶层查询对象,自定义的查询方式
//CriteriaBuilder:查询的构造器,封装了很多的查询条件
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
实现简单的单字段查询
@Test
public void testSpe() {
/*构建查询条件
* new 匿名内部类
* 自定义查询条件
* 1/实现Specification接口(提供泛型:查询的对象类型)
* 2/实现toPredicate方法(构造查询条件)
* 3/需要借助方法参数中的两个对象属性
* Root:获取所需要的对象属性
* CriteriaQuery:构造查询条件的,内部封装了很多的查询条件
*
* 实现根据客户名查询
* 查询条件
* 1.查询方式
* CriteriaQuery对象
* 2.比较的属性名称
* Root对象
* */
Specification<Customer> specification = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//1.获取比较的属性s
Path<Object> custName = root.get("custName");
//2.构造查询条件:select *from cst_customer where cust_name = '百度'
/*
* 第一个参数:需要比较的属性(path对象)
* 第二个参数:当前需要比较的值
* */
Predicate 百度 = cb.equal(custName, "百度u");
return 百度;
}
};
Customer one = customerDao.findOne(specification);
System.out.println("one = " + one);
}
//多字段的查询
@Test
public void testSpec1(){
Specification<Customer> specification=new Specification<Customer>() {
/*
* root 获取属性
* 客户名
* 所属行业
* cb 构造查询
* 1.构造客户名的精准匹配
* 2.构造所属行业的精准匹配查询
* 3.将以上的两个查询联系起来
*
* */
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
Path<Object> custName = root.get("custName");
Path<Object> custIndustry = root.get("custIndustry");
//1.构造客户的精准匹配查询
Predicate n1 = cb.equal(custName, "测试");
//2.构造所属行业的精准匹配查询
Predicate n2 = cb.equal(custIndustry, "test");
//3.将多个查询条件组合到一起
Predicate and = cb.and(n1, n2);
return and;
}
};
Customer one = customerDao.findOne(specification);
System.out.println("one = " + one);
}
2.)多表之间的关系和操作多表的操作步骤
一对多
多对多
// 创建分页对象
PageRequest page = PageSort.pageRequest(Sort.Direction.ASC);
return employeeRepository.findAll(new Specification<Employee>() {
@Override
public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cd) {
List<Predicate> employeeList = new ArrayList<>();
if (employee.getName() != null) {
employeeList.add(cd.equal(root.get("name").as(Long.class), employee.getName()));
}
if (employee.getStatus() != null) {
employeeList.add(cd.equal(root.get("status").as(Byte.class), employee.getStatus()));
}
if (employee.getDept() != null) {
Dept dept = employee.getDept();
List<Long> deprIn = new ArrayList<>();
deprIn.add(dept.getId());
List<Dept> deptList = deptService.getListByPidLikeOk(dept.getId());
deptList.forEach(item -> deprIn.add(item.getId()));
Join<Employee, Dept> employeeDeptJoin = root.join("dept", JoinType.INNER);
CriteriaBuilder.In<Long> in = cd.in(employeeDeptJoin.get("id").as(Long.class));
deprIn.forEach(in::value);
employeeList.add(in);
}
Predicate[] pres = new Predicate[employeeList.size()];
return criteriaQuery.where(employeeList.toArray(pres)).getRestriction();
}
}, page);