10、动态查询

动态查询

1、Specifications动态查询

方法列表:

public interface JpaSpecificationExecutor<T> {
    
    

	T findOne(Specification<T> spec); //查询单个对象

	List<T> findAll(Specification<T> spec); //查询列表

    //查询全部,分页
    //pageable:分页参数
    //返回值:分页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);//统计查询
}
  • Specfication:查询条件

    自定义我们自己的Specification实现类

    ​ 实现

    ​ //root:查询的跟对象(查询的任何属性都可以从跟对象中获取)

    ​ //CriteriaQuery:顶层查询对象,自定义查询方式(了解:一般不用)

    ​ //CriteriaBuilder:查询的构造器,封装了很多的查询条件

Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

2、搭建环境

导入坐标:

<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 aop-->
    <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>
    <!--spring ioc-->
    <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-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!--spring对orm框架的支持包-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- hibernate核心包 -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <!--hibernate对jpa实现的包-->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <!--hibernate的验证包-->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.2.1.Final</version>
    </dependency>
    <!-- c3p0  -->
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>${c3p0.version}</version>
    </dependency>
    <!-- log-->
    <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>
    <!--数据库-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!--spring data jpa的坐标-->
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>1.9.0.RELEASE</version>
    </dependency>
    <!--spring提供单元测试的坐标-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <!-- el 使用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>

编写配置文件:

<?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">

    <!-- 创建entityManagerFactory对象交给spring容器管理 -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--配置的扫描的包(实体类所在的包)-->
        <property name="packagesToScan" value="com.sddm.entity" />
        <!-- 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" />
                <!--指定数据库类型-->
                <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>

    <!-- dataSource 配置数据库连接池-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa" />
        <property name="user" value="root" />
        <property name="password" value="root" />
    </bean>

    <!-- 整合spring data jpa-->
    <jpa:repositories base-package="com.sddm.dao"
                      transaction-manager-ref="transactionManager"
                      entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

    <!-- 事务管理器-->
    <!-- JPA事务管理器  -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

    <!-- 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>

    <!-- aop-->
    <aop:config>
        <aop:pointcut id="pointcut" expression="execution(* com.sddm.service.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
    </aop:config>

    <context:component-scan base-package="com.sddm"></context:component-scan>

    <!--组装其它 配置文件-->

</beans>

创建实体类:

@Entity
@Table(name = "cst_customer")
public class Customer {
    
    
    @Id//声明当前私有属性为主键
    @GeneratedValue(strategy= GenerationType.IDENTITY) //配置主键的生成策略
    @Column(name="cust_id") //指定和表中cust_id字段的映射关系
    private Long custId;

    @Column(name="cust_name") //指定和表中cust_name字段的映射关系
    private String custName;

    @Column(name="cust_source")
    private String custSource;

    @Column(name="cust_industry")
    private String custIndustry;

    @Column(name="cust_level")
    private String custLevel;

    @Column(name="cust_address")
    private String custAddress;

    @Column(name="cust_phone")
    private String custPhone;
    
    //省略get和set方法
}

创建dao对象:

扫描二维码关注公众号,回复: 12411818 查看本文章
public interface CustomerDao extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> {
    
    }

项目结构:

在这里插入图片描述

测试案例:

1、根据客户名称查询,查询客户名称为sddm的客户

/*
 * 根据条件,查询单个对象
 * 
 */
@Test
public void testSpec(){
    
    

    Specification<Customer> spec = new Specification<Customer>() {
    
    
        //匿名内部类
        /*
            * 自定义查询条件
            *       1.实现Specification接口(提供泛型:查询的对象类型)
            *       2.实现toPredicate方法(构造查询条件)
            *       3.需要借助方法参数中的两个参数(
            *           root:获取需要查询的对象属性
            *           CriteriaQuery:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
            *       )
            *       案例:根据客户名称查询,查询客户名称为sddm的客户
            *               查询条件
            *                   1.查询方式
            *                       cb对象
            *                   2.比较的属性名称
            *                       root对象
            * */
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    
    
            //1、获取比较的属性
            Path<Object> custName = root.get("custName");
            //2、构造查询条件:   select * from cst_customer where cust_name = 'sddm'
            /*
                * 第一个参数:需要比较的属性(path对象)
                * 第二个参数:当前需要比较的取值
                * */
            Predicate predicate = cb.equal(custName,"sddm");//进行精准匹配 (比较的属性,比较的属性的取值)
            return predicate;
        }
    };

    Customer customer = customerDao.findOne(spec);
    System.out.println(customer);
}

查看结果:

在这里插入图片描述

2、多条件查询:根据客户名称(sddm)和客户所属行业查询(福州)

/*
* 多条件查询
*       案例:根据客户名称(sddm)和客户所属行业查询(福州)
* */
@Test
public void testSpec1(){
    
    
    /*
    *  root:获取属性
    *       客户名
    *       所属行业
    *  cb:构造查询
    *       1.构造客户名的精准匹配查询
    *       2.构造所属行业的精准匹配查询
    *       3.将以上两个查询联系起来
    * */
    Specification<Customer> spec = new Specification<Customer>() {
    
    
    	public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    
    
            Path<Object> custName = root.get("custName");//客户名
            Path<Object> custIndustry = root.get("custIndustry");//所属行业

            //构造查询
            //1.构造客户名的精准匹配查询
            Predicate p1 = cb.equal(custName, "sddm");//第一个参数,path(属性),第二个参数,属性的取值
            //2.构造所属行业的精准匹配
            Predicate p2 = cb.equal(custIndustry, "福州");//第一个参数,path(属性),第二个参数,属性的取值
            //3.将多个查询条件组合到一起:组合(满足条件一并且满足条件二即可:与关系;满足条件一或满足条件二即可:或关系)
            Predicate and = cb.and(p1, p2);//以与的形式拼接多个查询条件
            //cb.or();//以或的形式拼接多个查询条件
            return and;
        }
    };
    Customer customer = customerDao.findOne(spec);
    System.out.println(customer);
}

查看结果:

在这里插入图片描述

3、根据客户名称的模糊匹配,返回客户列表:

/*
* 案例:完成根据客户名称的模糊匹配,返回客户列表
*       客户名称以‘sddm’开头的
*
*  equal:直接得到path对象(属性),然后进行比较即可
*  gt,lt,ge,le,like:得到path对象,根据path指定比较的参数类型,再去进行比较
*          指定参数类型:path.ad(类型的字节码对象)
* */
@Test
public void testSpec3(){
    
    
    //构造查询条件
    Specification<Customer> spec = new Specification<Customer>() {
    
    
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    
    
            //查询属性:客户名
            Path<Object> custName = root.get("custName");
            //查询方式:模糊匹配
            Predicate predicate = cb.like(custName.as(String.class), "sddm%");
            return predicate;
        }
    };

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

查看結果:

在这里插入图片描述

4、排序:

@Test
public void testSpec3(){
    
    
    //构造查询条件
    Specification<Customer> spec = new Specification<Customer>() {
    
    
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    
    
            //查询属性:客户名
            Path<Object> custName = root.get("custName");
            //查询方式:模糊匹配
            Predicate predicate = cb.like(custName.as(String.class), "sddm%");
            return predicate;
        }
    };

    //添加排序
    //创建排序对象,需要调用构造方法实例化sort对象
    //第一个参数:排序的顺序(倒序,正序)
    //  Sort.Direction.DESC:倒序
    //  Sort.Direction.ASC:升序
    //第二个参数:排序的属性名称
    Sort sort = new Sort(Sort.Direction.DESC,"custId");
    List<Customer> customers = customerDao.findAll(spec, sort);
    for (Customer customer : customers){
    
    
    	System.out.println(customer);
    }
}

查看結果:

在这里插入图片描述

5、分页查询:

/*
* 分页查询
*       Specification:查询条件
*       Pageable:分页参数
*           分页参数:查询的页码,每页查询的条数
*           findAll(Specification,Pageable):带有条件的分页
*           findAll(Pageable):没有条件的分页
*  返回:Page(springDataJpa为我们封装好的pageBean对象,能够为我们提供数据列表,总条数)
* */
@Test
public void testSpec4(){
    
    
    Specification spec = null;
    //Pagerequest对象是Pageable接口的实现类
    /*
    * 创建PageRequest的过程中,需要调用他的构造方法传入两个参数
    *   第一个参数:当前查询的页数(从0开始)
    *   第二个参数:每页查询的数量
    * */
    Pageable pageable = new PageRequest(0,2);
    //分页查询
    Page page = customerDao.findAll(spec, pageable);
    System.out.println(page.getContent());//得到数据集合列表
    System.out.println(page.getTotalElements());//得到总条数
    System.out.println(page.getTotalPages());//得到总页数
}

查看結果:
在这里插入图片描述
方法对应关系

方法名称 Sql对应关系
equle filed = value
gt(greaterThan ) filed > value
lt(lessThan ) filed < value
ge(greaterThanOrEqualTo ) filed >= value
le( lessThanOrEqualTo) filed <= value
notEqule filed != value
like filed like value
notLike filed not like value

猜你喜欢

转载自blog.csdn.net/weixin_44230693/article/details/113033985