zoukankan      html  css  js  c++  java
  • spring data jpa

    录:

    1、Spring Data 概述
    2、Spring Data JPA HelloWorld
    3、Repository接口
    4、Repository查询方法定义规范
    5、spring data jpa-注解@Query
    6、@Modifying注解
    7、CrudRepository接口
    8、PagingAndSortingRespository接口
    9、JpaRepository接口
    10、JpaSpecificationExecutor接口
    11、spring data jpa-所有接口的方法
    12、自定义 Repository 方法
    13、一些总结

    1、Spring Data 概述    <--返回目录

      Spring Data: Spring 的一个子项目,用于简化数据库访问,支持NoSQL和关系数据存储。其主要目标是使数据库的访问变得方便快捷。

      SpringData项目所支持NoSQL存储:

        - MongoDB文档数据库

        - Neo4j图形数据库

        - Redis键值存储

        - Hbase列族数据库

      SpringData项目所支持的关系数据存储技术

        - JDBC

        - JPA

      Spring Data JPA: 致力于减少数据访问层DAO的开发量。开发者唯一要做的,就只是声明持久层的接口,其他都交给Spring Data JPA来帮你完成。  框架怎么可能代替开发者实现业务逻辑呢?  比如:当有一个UserDao.findUserById() 这样一个方法声明,大致应该能判断出这是根据给定条件的ID查询出满足条件的User对象。Spring Data JPA做的便是规范方法的名字,根据复合规范的名字来确定方法需要实现什么样的逻辑。

    2、Spring Data JPA HelloWorld    <--返回目录

      项目结构(下载地址:链接:https://pan.baidu.com/s/1SCINfgjKJ7q-tMl7nFnIxA  提取码:xehl)

        1) 配置 Spring 整合 JPA

      spring相关

      hibernate相关

       jpa相关

       c3p0相关

       mysql驱动

      在 Spring 的配置文件(applicationContext.xml)中配置 Spring Data

    <?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.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <!-- 配置自动扫描的包 -->
        <context:component-scan base-package="com.oy.springdata"></context:component-scan>
    
        <!-- 1. 配置数据源 -->
        <context:property-placeholder location="classpath:db.properties"/>
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="${jdbc.user}"></property>
            <property name="password" value="${jdbc.password}"></property>    
            <property name="driverClass" value="${jdbc.driverClass}"></property>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
            
            <!-- 配置其他属性 -->
        </bean>
    
        <!-- 2. 配置 JPA 的 EntityManagerFactory -->
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
            </property>
            <property name="packagesToScan" value="com.oy.springdata"></property>
            <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"></property>    
        </bean>
    
        <!-- 4. 配置支持注解的事务 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <!-- 5. 配置 SpringData -->
        <!-- 加入 jpa 的命名空间 -->
        <!-- base-package: 扫描 Repository Bean 所在的 package -->
        <jpa:repositories base-package="com.oy.springdata" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    
    </beans>

      db.properties

    jdbc.user=root
    jdbc.password=123456
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.jdbcUrl=jdbc:mysql:///jpa


      2) 在 Spring 配置文件中配置 Spring Data,让 Spring 为声明的接口创建代理对象。配置了 <jpa:repositories> 后,Spring 初始化容器时将会扫描 base-package  指定的包目录及其子目录,为继承 Repository 或其子接口的接口创建代理对象,并将代理对象注册为 Spring Bean,业务层便可以通过 Spring 自动封装的特性来直接使用该对象。

      同时下载 Spring Data Commons 和 Spring Data JPA 两个发布包:
        - Commons 是 Spring Data 的基础包
        - 并把相关的依赖 JAR 文件加入到 CLASSPATH 中

      spring 配置 spring data:

    <!-- 5. 配置 SpringData -->
    <!-- 加入 jpa 的命名空间 -->
    <!-- base-package: 扫描 Repository Bean 所在的 package -->
    <jpa:repositories base-package="com.oy.springdata" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>

      3) 声明持久层的接口,该接口继承  Repository,Repository 是一个标记型接口,它不包含任何方法,如必要,Spring Data 可实现 Repository 其他子接口,其中定义了一些常用的增删改查,以及分页相关的方法。

      Person 类

    package com.oy.springdata;
    
    import java.util.Date;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Table(name = "JPA_PERSONS")
    @Entity
    public class Person {
    
        private Integer id;
        private String lastName;
    
        private String email;
        private Date birth;
    
        @GeneratedValue
        @Id
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Date getBirth() {
            return birth;
        }
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    
        @Override
        public String toString() {
            return "Person [id=" + id + ", lastName=" + lastName + ", email=" + email + ", brith=" + birth + "]";
        }
    }

      PersonRepository 类

    package com.oy.springdata;
    
    import org.springframework.data.repository.Repository;
    
    //@RepositoryDefinition(domainClass=Person.class,idClass=Integer.class)
    public interface PersonRepository extends Repository<Person, Integer> {
    
        Person getByLastName(String lastName);
    
    }

      
      4) 在接口中声明需要的方法。Spring Data 将根据给定的策略(具体策略稍后讲解)来为其生成实现代码。
      在PersonRepository 类中创建 getByLastName() 方法。

      测试代码SpringDataTest:

    package com.oy.springdata.test;
    
    import java.sql.SQLException;
    
    import javax.sql.DataSource;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.springdata.Person;
    import com.oy.springdata.PersonRepository;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonRepository personRepository = null;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personRepository = ctx.getBean(PersonRepository.class);
        }
    
        /**
         * 测试 getByLastName() 方法
         * @throws Exception
         */
        @Test
        public void testHelloWorldSpringData() throws Exception {
            System.out.println(personRepository.getClass().getName());
    
            Person person = personRepository.getByLastName("aa");
            System.out.println(person);
        }
    
        /**
         * 测试是否自动生成代码
         */
        @Test
        public void testJpa() {}
    
        /**
         * 测试数据源配置是否成功
         * @throws SQLException
         */
        @Test
        public void testDataSource() throws SQLException {
            DataSource dataSource = ctx.getBean(DataSource.class);
            System.out.println(dataSource.getConnection());
        }
    }

      测试打印结果

    3、Repository接口    <--返回目录

      1)Repository 接口是 Spring Data 的一个核心接口。Repository 是一个空接口. 即是一个标记接口。
      2)若我们定义的接口继承了 Repository, 则该接口会被 IOC 容器识别为一个 Repository Bean.
    纳入到 IOC 容器中. 进而可以在该接口中定义满足一定规范的方法.
      3)实际上, 也可以通过 @RepositoryDefinition 注解来替代继承 Repository 接口

      Repository 的子接口

    基础的 Repository 提供了最基本的数据访问功能,其几个子接口则扩展了一些功能。它们的继承关系如下: 
    - Repository: 仅仅是一个标识,表明任何继承它的均为仓库接口类
    - CrudRepository: 继承 Repository,实现了一组 CRUD 相关的方法 
    - PagingAndSortingRepository: 继承 CrudRepository,实现了一组分页排序相关的方法 
    - JpaRepository: 继承 PagingAndSortingRepository,实现一组 JPA 规范相关的方法 
    自定义的 XxxxRepository 需要继承 JpaRepository,这样的 XxxxRepository 接口就具备了通用的数据访问控制层的能力。
    - JpaSpecificationExecutor: 不属于Repository体系,实现一组 JPA Criteria 查询相关的方法 

    4、Repository查询方法定义规范    <--返回目录

      支持的关键字

       查询方法解析流程

       举例

    //根据 lastName 来获取对应的 Person
    Person getByLastName(String lastName);
    
    //WHERE lastName LIKE ?% AND id < ?
    List<Person> getByLastNameStartingWithAndIdLessThan(String lastName, Integer id);
    
    //WHERE lastName LIKE %? AND id < ?
    List<Person> getByLastNameEndingWithAndIdLessThan(String lastName, Integer id);
    
    //WHERE email IN (?, ?, ?) AND birth < ?
    List<Person> getByEmailInAndBirthLessThan(List<String> emails, Date birth);
    
    //WHERE a.id > ?
    List<Person> getByAddress_IdGreaterThan(Integer id);

    5、spring data jpa-注解@Query    <--返回目录

    //查询 id 值最大的那个 Person
    //使用 @Query 注解可以自定义 JPQL 语句以实现更灵活的查询
    @Query("SELECT p FROM Person p WHERE p.id = (SELECT max(p2.id) FROM Person p2)")
    Person getMaxIdPerson();
    
    //为 @Query 注解传递参数的方式1: 使用占位符. 
    @Query("SELECT p FROM Person p WHERE p.lastName = ?1 AND p.email = ?2")
    List<Person> testQueryAnnotationParams1(String lastName, String email);
    
    //为 @Query 注解传递参数的方式1: 命名参数的方式. 
    @Query("SELECT p FROM Person p WHERE p.lastName = :lastName AND p.email = :email")
    List<Person> testQueryAnnotationParams2(@Param("email") String email, @Param("lastName") String lastName);
    
    //SpringData 允许在占位符上添加 %%. 
    @Query("SELECT p FROM Person p WHERE p.lastName LIKE %?1% OR p.email LIKE %?2%")
    List<Person> testQueryAnnotationLikeParam(String lastName, String email);
    
    //SpringData 允许在占位符上添加 %%. 
    @Query("SELECT p FROM Person p WHERE p.lastName LIKE %:lastName% OR p.email LIKE %:email%")
    List<Person> testQueryAnnotationLikeParam2(@Param("email") String email, @Param("lastName") String lastName);
    
    //设置 nativeQuery=true 即可以使用原生的 SQL 查询
    @Query(value="SELECT count(id) FROM jpa_persons", nativeQuery=true)
    long getTotalCount();

    6、@Modifying注解    <--返回目录

    //可以通过自定义的 JPQL 完成 UPDATE 和 DELETE 操作. 注意: JPQL 不支持使用 INSERT
    //在 @Query 注解中编写 JPQL 语句, 但必须使用 @Modifying 进行修饰. 以通知 SpringData, 这是一个 UPDATE 或 DELETE 操作
    //UPDATE 或 DELETE 操作需要使用事务, 此时需要定义 Service 层. 在 Service 层的方法上添加事务操作. 
    //默认情况下, SpringData 的每个方法上有事务, 但都是一个只读事务. 他们不能完成修改操作!
    @Modifying
    @Query("UPDATE Person p SET p.email = :email WHERE id = :id")
    void updatePersonEmail(@Param("id") Integer id, @Param("email") String email);

      service层代码

    @Service
    public class PersonService {
    
        @Autowired
        private PersonRepsotory personRepsotory;
        
        @Transactional
        public void updatePersonEmail(String email, Integer id){
            personRepsotory.updatePersonEmail(id, email);
        }
    }

    7、CrudRepository接口    <--返回目录

      项目结构

     

       Person

    package com.oy.springdata;
    
    import java.util.Date;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    @Table(name = "JPA_PERSONS")
    @Entity
    public class Person {
    
        private Integer id;
        private String lastName;
    
        private String email;
        private Date birth;
    
        @GeneratedValue
        @Id
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Date getBirth() {
            return birth;
        }
    
        public void setBirth(Date birth) {
            this.birth = birth;
        }
    
        @Override
        public String toString() {
            return "Person [id=" + id + ", lastName=" + lastName + ", email=" + email + ", brith=" + birth + "]";
        }
    }
    View Code

      PersonRepository

    package com.oy.springdata;
    
    import org.springframework.data.repository.CrudRepository;
    
    public interface PersonRepository extends CrudRepository<Person, Integer> {
    }

      PersonService

    package com.oy.springdata;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    @Service
    public class PersonService {
    
        @Autowired
        private PersonRepository personRepository;
    
        @Transactional
        public void savePersons(List<Person> persons) {
            personRepository.save(persons);
        }
    
    }

      测试

    package com.oy.springdata.test;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.springdata.Person;
    import com.oy.springdata.PersonService;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonService personService;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personService = ctx.getBean(PersonService.class);
        }
    
        /**
         * 测试 CrudRepository中的save()方法
         */
        @Test
        public void testCrudReposiory(){
            List<Person> persons = new ArrayList<>();
            
            for(int i = 'a'; i <= 'z'; i++){
                Person person = new Person();
                person.setBirth(new Date());
                person.setEmail((char)i + "" + (char)i + "@163.com");
                person.setLastName((char)i + "" + (char)i);
                
                persons.add(person);
            }
            
            personService.savePersons(persons);
        }
    }

      applicationContext.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: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.xsd
            http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    
        <!-- 配置自动扫描的包 -->
        <context:component-scan base-package="com.oy.springdata"></context:component-scan>
    
        <!-- 1. 配置数据源 -->
        <context:property-placeholder location="classpath:db.properties"/>
    
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="${jdbc.user}"></property>
            <property name="password" value="${jdbc.password}"></property>    
            <property name="driverClass" value="${jdbc.driverClass}"></property>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
            
            <!-- 配置其他属性 -->
        </bean>
    
        <!-- 2. 配置 JPA 的 EntityManagerFactory -->
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"></property>
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
            </property>
            <property name="packagesToScan" value="com.oy.springdata"></property>
            <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"></property>    
        </bean>
    
        <!-- 4. 配置支持注解的事务 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>
    
        <!-- 5. 配置 SpringData -->
        <!-- 加入 jpa 的命名空间 -->
        <!-- base-package: 扫描 Repository Bean 所在的 package -->
        <jpa:repositories base-package="com.oy.springdata" entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    
    </beans>
    View Code

      db.properties

    jdbc.user=root
    jdbc.password=
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.jdbcUrl=jdbc:mysql:///jpa
    View Code

      

    8、PagingAndSortingRespository接口    <--返回目录

      项目结构

     

      PersonRepository

    public interface PersonRepository extends PagingAndSortingRepository<Person, Integer> {
    }

      测试

    package com.oy.springdata.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Sort;
    import org.springframework.data.domain.Sort.Direction;
    import org.springframework.data.domain.Sort.Order;
    
    import com.oy.springdata.Person;
    import com.oy.springdata.PersonRepository;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonRepository personRepository = null;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personRepository = ctx.getBean(PersonRepository.class);
        }
    
        @Test
        public void testPagingAndSortingRespository(){
            //pageNo 从 0 开始. 
            int pageNo = 2 - 1;
            int pageSize = 5;
            //Pageable 接口通常使用的其 PageRequest 实现类. 其中封装了需要分页的信息
            //排序相关的. Sort 封装了排序的信息
            //Order 是具体针对于某一个属性进行升序还是降序. 
            Order order1 = new Order(Direction.DESC, "id");
            Order order2 = new Order(Direction.ASC, "email");
            Sort sort = new Sort(order1, order2);
            
            PageRequest pageable = new PageRequest(pageNo, pageSize, sort);
            Page<Person> page = personRepository.findAll(pageable);
            
            System.out.println("总记录数: " + page.getTotalElements());
            System.out.println("当前第几页: " + (page.getNumber() + 1));
            System.out.println("总页数: " + page.getTotalPages());
            System.out.println("当前页面的 List: " + page.getContent());
            System.out.println("当前页面的记录数: " + page.getNumberOfElements());
        }
    }

    9、JpaRepository接口    <--返回目录

      项目结构

       PersonRepository

    public interface PersonRepository extends JpaRepository<Person, Integer> {
    }

      测试代码

    package com.oy.springdata.test;
    
    import java.util.Date;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.springdata.Person;
    import com.oy.springdata.PersonRepository;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonRepository personRepository = null;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personRepository = ctx.getBean(PersonRepository.class);
        }
    
        @Test
        public void testJpaRepository(){
            Person person = new Person();
            person.setBirth(new Date());
            person.setEmail("123@163.com");
            person.setLastName("123");
            person.setId(28);
            
            Person person2 = personRepository.saveAndFlush(person);
            
            System.out.println(person == person2);
        }
    }

    10、JpaSpecificationExecutor接口    <--返回目录

       PersonRepository

    public interface PersonRepository extends JpaRepository<Person, Integer>, JpaSpecificationExecutor<Person> {
    }

      测试代码

    package com.oy.springdata.test;
    
    import javax.persistence.criteria.CriteriaBuilder;
    import javax.persistence.criteria.CriteriaQuery;
    import javax.persistence.criteria.Path;
    import javax.persistence.criteria.Predicate;
    import javax.persistence.criteria.Root;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.jpa.domain.Specification;
    
    import com.oy.springdata.Person;
    import com.oy.springdata.PersonRepository;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonRepository personRepository = null;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personRepository = ctx.getBean(PersonRepository.class);
        }
    
        /**
         * 目标: 实现带查询条件的分页. id > 5 的条件
         * 
         * 调用 JpaSpecificationExecutor 的 Page<T> findAll(Specification<T> spec, Pageable pageable);
         * Specification: 封装了 JPA Criteria 查询的查询条件
         * Pageable: 封装了请求分页的信息: 例如 pageNo, pageSize, Sort
         */
        @Test
        public void testJpaSpecificationExecutor(){
            int pageNo = 3 - 1;
            int pageSize = 5;
            PageRequest pageable = new PageRequest(pageNo, pageSize);
            
            // 通常使用 Specification 的匿名内部类
            Specification<Person> specification = new Specification<Person>() {
                /**
                 * @param *root: 代表查询的实体类. 
                 * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 还可以
                 * 来添加查询条件, 还可以结合 EntityManager 对象得到最终查询的 TypedQuery 对象. 
                 * @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂. 当然可以从中获取到 Predicate 对象
                 * @return: *Predicate 类型, 代表一个查询条件. 
                 */
                @Override
                public Predicate toPredicate(Root<Person> root,
                        CriteriaQuery<?> query, CriteriaBuilder cb) {
                    Path path = root.get("id");
                    Predicate predicate = cb.gt(path, 5);
                    return predicate;
                }
            };
            
            Page<Person> page = personRepository.findAll(specification, pageable);
            
            System.out.println("总记录数: " + page.getTotalElements());
            System.out.println("当前第几页: " + (page.getNumber() + 1));
            System.out.println("总页数: " + page.getTotalPages());
            System.out.println("当前页面的 List: " + page.getContent());
            System.out.println("当前页面的记录数: " + page.getNumberOfElements());
        }
    }

    11、spring data jpa-所有接口的方法    <--返回目录

    12、自定义 Repository 方法    <--返回目录

      项目结构

     

      PersonDao

    public interface PersonDao {
        void test();
    }

      PersonRepository

    public interface PersonRepository extends PersonDao, JpaRepository<Person, Integer>, JpaSpecificationExecutor<Person> {
    }

      PersonRepositoryImpl

    package com.oy.springdata;
    
    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    
    public class PersonRepositoryImpl implements PersonDao {
       // 获取当前线程的 EntityManager 实例
        @PersistenceContext
        private EntityManager entityManager;
    
        @Override
        public void test() {
            Person person = entityManager.find(Person.class, 11);
            System.out.println("-->" + person);
        }
    
    }

      测试代码

    package com.oy.springdata.test;
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.oy.springdata.PersonRepository;
    
    public class SpringDataTest {
    
        private ApplicationContext ctx = null;
        private PersonRepository personRepository = null;
    
        {
            ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            personRepository = ctx.getBean(PersonRepository.class);
        }
    
        @Test
        public void testCustomRepositoryMethod() {
            personRepository.test();
        }
    }

    13、一些总结    <--返回目录

    1)
        * 实体@Entity @Table(name="t_webSite")映射成表,表名为t_web_site
        * 如何设置text类型字段
            @Lob
            @Column(columnDefinition="TEXT")
            private String content; // 帖子内容
            
        * private Date publishDate; // 发布日期
            默认映射的表字段的类型为datetime
            
        * 外键关联
            @ManyToOne
            @JoinColumn(name="filmId")  这是生成字段file_id
            private Film film; // 电影
            
            @ManyToOne
            @JoinColumn(name="webSiteId")
            private WebSite webSite; // 网站

    2)不带条件的分页查询  service层实现类:

    @Override
    public List<Link> list(Integer page, Integer pageSize) {
        // page:当前页,从1开始, PageRequest(page, pageSize)中page从0开始
        page = page -1;
        return linkRepository.findAll(new PageRequest(page, pageSize)).getContent();
    }
    
    @Override
    public Long getCount() {
        return linkRepository.count();
    }


    3)【带条件分页查询及排序】  service层实现类:

    @Override
    public List<WebSite> list(WebSite webSite, Integer page, Integer pageSize) {
        // page:当前页,从1开始, PageRequest(page, pageSize)中page从0开始
        page = page -1;
        Pageable pageable=new PageRequest(page, pageSize,Sort.Direction.ASC,"id"); // 【根据id升序排序】
        Page<WebSite> pageWebSite=webSiteRepository.findAll(new Specification<WebSite>() {
            
            @Override
            public Predicate toPredicate(Root<WebSite> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate=cb.conjunction();
                if(webSite!=null){
                    if(StringUtil.isNotEmpty(webSite.getName())){
                        predicate.getExpressions().add(cb.like(root.get("name"), "%"+webSite.getName().trim()+"%"));
                    }
                    if(StringUtil.isNotEmpty(webSite.getUrl())){
                        predicate.getExpressions().add(cb.like(root.get("url"), "%"+webSite.getUrl().trim()+"%"));
                    }
                }
                return predicate;
            }
        }, pageable);
        return pageWebSite.getContent();
    }
    
    @Override
    public Long getCount(WebSite webSite) {
        Long count=webSiteRepository.count(new Specification<WebSite>() {
    
            @Override
            public Predicate toPredicate(Root<WebSite> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate=cb.conjunction();
                if(webSite!=null){
                    if(StringUtil.isNotEmpty(webSite.getName())){
                        predicate.getExpressions().add(cb.like(root.get("name"), "%"+webSite.getName().trim()+"%"));
                    }
                    if(StringUtil.isNotEmpty(webSite.getUrl())){
                        predicate.getExpressions().add(cb.like(root.get("url"), "%"+webSite.getUrl().trim()+"%"));
                    }
                }
                return predicate;
            }
        });
        return count;
    }

    ---

  • 相关阅读:
    easy ui 表单ajax和from两种提交数据方法
    easy ui 下拉级联效果 ,下拉框绑定数据select控件
    easy ui 下拉框绑定数据select控件
    easy ui 异步上传文件,跨域
    easy ui 菜单和按钮(Menu and Button)
    HTTP 错误 404.3
    EXTJS4.2 后台管理菜单栏
    HTML 背景图片自适应
    easy ui 表单元素input控件后面加说明(红色)
    EXTJS 4.2 添加滚动条
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/13844168.html
Copyright © 2011-2022 走看看