• Spring Data JPA


    一、JPA概述:

      JPA的全称是Java Persistence API, 即Java 持久化API,是SUN公司推出的一套基于ORM的规范,内部是由一系列的接口和抽象类构成。JPA通过JDK 5.0注解描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。

      JPA的优势:标准化、容器级特性的支持、简单方便、查询能力、高级特性

    二、JPA与Hibernate的关系:

      JPA规范本质上就是一种ORM规范,注意不是ORM框架——因为JPA并未提供ORM实现,它只是制订了一些规范,提供了一些编程的API接口,但具体实现则由服务厂商来提供实现。JPAHibernate的关系就像JDBCJDBC驱动的关系,JPA是规范,Hibernate除了作为ORM框架之外,它也是一种JPA实现。

    三、JPA环境搭建:

    1、创建一个maven工程,在pom.xml中导入对应的坐标

     1    <properties>
     2         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     3         <project.hibernate.version>5.0.7.Final</project.hibernate.version>
     4     </properties>
     5 
     6     <dependencies>
     7         <!-- junit -->
     8         <dependency>
     9             <groupId>junit</groupId>
    10             <artifactId>junit</artifactId>
    11             <version>4.12</version>
    12             <scope>test</scope>
    13         </dependency>
    14 
    15         <!-- hibernate对jpa的支持包 -->
    16         <dependency>
    17             <groupId>org.hibernate</groupId>
    18             <artifactId>hibernate-entitymanager</artifactId>
    19             <version>${project.hibernate.version}</version>
    20         </dependency>
    21 
    22         <!-- c3p0 -->
    23         <dependency>
    24             <groupId>org.hibernate</groupId>
    25             <artifactId>hibernate-c3p0</artifactId>
    26             <version>${project.hibernate.version}</version>
    27         </dependency>
    28 
    29         <!-- log日志 -->
    30         <dependency>
    31             <groupId>log4j</groupId>
    32             <artifactId>log4j</artifactId>
    33             <version>1.2.17</version>
    34         </dependency>
    35 
    36         <!-- Mysql and MariaDB -->
    37         <dependency>
    38             <groupId>mysql</groupId>
    39             <artifactId>mysql-connector-java</artifactId>
    40             <version>5.1.6</version>
    41         </dependency>
    42     </dependencies>

    2、编写实体类和数据表的映射配置,创建实体类以后,使用对应的注释配置映射关系

         @Entity
                作用:指定当前类是实体类。
            @Table
                作用:指定实体类和表之间的对应关系。
                属性:
                    name:指定数据库表的名称
            @Id
                作用:指定当前字段是主键。
            @GeneratedValue
                作用:指定主键的生成方式。。
                属性:
                    strategy :指定主键生成策略。
            @Column
                作用:指定实体类属性和数据库表之间的对应关系
                属性:
                    name:指定数据库表的列名称。
                    unique:是否唯一  
                    nullable:是否可以为空  
                    inserttable:是否可以插入  
                    updateable:是否可以更新  
                    columnDefinition: 定义建表时创建此列的DDL  
                    secondaryTable: 从表名。如果此列不建在主表上(默认建在主表),该属性定义该列所在从表的名字搭建开发环境[重点]

    3、配置JPA的核心配置文件

    在java工程的src路径下创建一个名为META-INF的文件夹,在此文件夹下创建一个名为persistence.xml的配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  
        http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0">
        <!--配置持久化单元 
            name:持久化单元名称 
            transaction-type:事务类型
                 RESOURCE_LOCAL:本地事务管理 
                 JTA:分布式事务管理 -->
        <persistence-unit name="myJpa" transaction-type="RESOURCE_LOCAL">
            <!--配置JPA规范的服务提供商 -->
            <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
            <properties>
                <!-- 数据库驱动 -->
                <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
                <!-- 数据库地址 -->
                <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/jpa" />
                <!-- 数据库用户名 -->
                <property name="javax.persistence.jdbc.user" value="root" />
                <!-- 数据库密码 -->
                <property name="javax.persistence.jdbc.password" value="111111" />
    
                <!--jpa提供者的可选配置:我们的JPA规范的提供者为hibernate,所以jpa的核心配置中兼容hibernate的配 -->
    <property name="hibernate.show_sql" value="true" /> <property name="hibernate.format_sql" value="true" />
            
           <!--自动创建数据库表:create(运行时创建表),update(如过有表则不创建表),none(不创建表) <property name="hibernate.hbm2ddl.auto" value="create" /> </properties> </persistence-unit> </persistence>

    4、测试数据库操作

    通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作

    方法说明:    
        getTransaction : 获取事务对象
        persist : 保存操作
        merge : 更新操作
        remove : 删除操作
        find/getReference : 根据id查询
     1 @Test
     2     public void test() {
     3         /**
     4          * 创建实体管理类工厂,借助Persistence的静态方法获取
     5          *         其中传递的参数为持久化单元名称,需要jpa配置文件中指定
     6          */
     7         EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
     8         //创建实体管理类
     9         EntityManager em = factory.createEntityManager();
    10         //获取事务对象
    11         EntityTransaction tx = em.getTransaction();
    12         //开启事务
    13         tx.begin();
    14         Customer c = new Customer();
    15         c.setCustName("天地壹号");
    16         //保存操作
    17         em.persist(c);
    18         //提交事务
    19         tx.commit();
    20         //释放资源
    21         em.close();
    22         factory.close();
    23     }

    6、抽取JPAUtil工具类,通过工具类生成实体类管理器对象

    package top.biyenanhai.dao;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    
    public final class JPAUtil {
        // JPA的实体管理器工厂:相当于Hibernate的SessionFactory
        private static EntityManagerFactory em;
        // 使用静态代码块赋值
        static {
            // 注意:该方法参数必须和persistence.xml中persistence-unit标签name属性取值一致
            em = Persistence.createEntityManagerFactory("myPersistUnit");
        }
    
        /**
         * 使用管理器工厂生产一个管理器对象
         * 
         * @return
         */
        public static EntityManager getEntityManager() {
            return em.createEntityManager();
        }
    }

    三、Spring Data JPA概述:

      Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据库的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!Spring Data JPA 让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它来实现,在实际的工作工程中,推荐使用Spring Data JPA + ORM(如:hibernate)完成操作,这样在切换不同的ORM框架时提供了极大的方便,同时也使数据库层操作更加简单,方便解耦。

    四、Spring Data JPA 与 JPA和hibernate之间的关系:

      JPA是一套规范,内部是有接口和抽象类组成的。hibernate是一套成熟的ORM框架,而且Hibernate实现了JPA规范,所以也可以称hibernate为JPA的一种实现方式,我们使用JPA的API编程,意味着站在更高的角度上看待问题(面向接口编程)。Spring Data JPA是Spring提供的一套对JPA操作更加高级的封装,是在JPA规范下的专门用来进行数据持久化的解决方案。

    五、Spring Data JPA快速搭建开发环境:

    1、创建maven工程,导入Spring Data JPA的坐标

      1    <properties>
      2         <spring.version>4.2.4.RELEASE</spring.version>
      3         <hibernate.version>5.0.7.Final</hibernate.version>
      4         <slf4j.version>1.6.6</slf4j.version>
      5         <log4j.version>1.2.12</log4j.version>
      6         <c3p0.version>0.9.1.2</c3p0.version>
      7         <mysql.version>5.1.6</mysql.version>
      8     </properties>
      9 
     10     <dependencies>
     11         <!-- junit单元测试 -->
     12         <dependency>
     13             <groupId>junit</groupId>
     14             <artifactId>junit</artifactId>
     15             <version>4.12</version>
     16             <scope>test</scope>
     17         </dependency>
     18         
     19         <!-- spring beg -->
     20         <dependency>
     21             <groupId>org.aspectj</groupId>
     22             <artifactId>aspectjweaver</artifactId>
     23             <version>1.6.8</version>
     24         </dependency>
     25 
     26         <dependency>
     27             <groupId>org.springframework</groupId>
     28             <artifactId>spring-aop</artifactId>
     29             <version>${spring.version}</version>
     30         </dependency>
     31 
     32         <dependency>
     33             <groupId>org.springframework</groupId>
     34             <artifactId>spring-context</artifactId>
     35             <version>${spring.version}</version>
     36         </dependency>
     37 
     38         <dependency>
     39             <groupId>org.springframework</groupId>
     40             <artifactId>spring-context-support</artifactId>
     41             <version>${spring.version}</version>
     42         </dependency>
     43 
     44         <dependency>
     45             <groupId>org.springframework</groupId>
     46             <artifactId>spring-orm</artifactId>
     47             <version>${spring.version}</version>
     48         </dependency>
     49 
     50         <dependency>
     51             <groupId>org.springframework</groupId>
     52             <artifactId>spring-beans</artifactId>
     53             <version>${spring.version}</version>
     54         </dependency>
     55 
     56         <dependency>
     57             <groupId>org.springframework</groupId>
     58             <artifactId>spring-core</artifactId>
     59             <version>${spring.version}</version>
     60         </dependency>
     61         
     62         <!-- spring end -->
     63 
     64         <!-- hibernate beg -->
     65         <dependency>
     66             <groupId>org.hibernate</groupId>
     67             <artifactId>hibernate-core</artifactId>
     68             <version>${hibernate.version}</version>
     69         </dependency>
     70         <dependency>
     71             <groupId>org.hibernate</groupId>
     72             <artifactId>hibernate-entitymanager</artifactId>
     73             <version>${hibernate.version}</version>
     74         </dependency>
     75         <dependency>
     76             <groupId>org.hibernate</groupId>
     77             <artifactId>hibernate-validator</artifactId>
     78             <version>5.2.1.Final</version>
     79         </dependency>
     80         <!-- hibernate end -->
     81 
     82         <!-- c3p0 beg -->
     83         <dependency>
     84             <groupId>c3p0</groupId>
     85             <artifactId>c3p0</artifactId>
     86             <version>${c3p0.version}</version>
     87         </dependency>
     88         <!-- c3p0 end -->
     89 
     90         <!-- log end -->
     91         <dependency>
     92             <groupId>log4j</groupId>
     93             <artifactId>log4j</artifactId>
     94             <version>${log4j.version}</version>
     95         </dependency>
     96 
     97         <dependency>
     98             <groupId>org.slf4j</groupId>
     99             <artifactId>slf4j-api</artifactId>
    100             <version>${slf4j.version}</version>
    101         </dependency>
    102 
    103         <dependency>
    104             <groupId>org.slf4j</groupId>
    105             <artifactId>slf4j-log4j12</artifactId>
    106             <version>${slf4j.version}</version>
    107         </dependency>
    108         <!-- log end -->
    109 
    110         
    111         <dependency>
    112             <groupId>mysql</groupId>
    113             <artifactId>mysql-connector-java</artifactId>
    114             <version>${mysql.version}</version>
    115         </dependency>
    116 
    117         <dependency>
    118             <groupId>org.springframework.data</groupId>
    119             <artifactId>spring-data-jpa</artifactId>
    120             <version>1.9.0.RELEASE</version>
    121         </dependency>
    122 
    123         <dependency>
    124             <groupId>org.springframework</groupId>
    125             <artifactId>spring-test</artifactId>
    126             <version>4.2.4.RELEASE</version>
    127         </dependency>
    128         
    129         <!-- el beg 使用spring data jpa 必须引入 -->
    130         <dependency>  
    131             <groupId>javax.el</groupId>  
    132             <artifactId>javax.el-api</artifactId>  
    133             <version>2.2.4</version>  
    134         </dependency>  
    135           
    136         <dependency>  
    137             <groupId>org.glassfish.web</groupId>  
    138             <artifactId>javax.el</artifactId>  
    139             <version>2.2.4</version>  
    140         </dependency> 
    141         <!-- el end -->
    142 
    143         <dependency>
    144             <groupId>javax.xml.bind</groupId>
    145             <artifactId>jaxb-api</artifactId>
    146             <version>2.3.0</version>
    147         </dependency>
    148         <dependency>
    149             <groupId>com.sun.xml.bind</groupId>
    150             <artifactId>jaxb-impl</artifactId>
    151             <version>2.3.0</version>
    152         </dependency>
    153         <dependency>
    154             <groupId>com.sun.xml.bind</groupId>
    155             <artifactId>jaxb-core</artifactId>
    156             <version>2.3.0</version>
    157         </dependency>
    158         <dependency>
    159             <groupId>javax.activation</groupId>
    160             <artifactId>activation</artifactId>
    161             <version>1.1.1</version>
    162         </dependency>
    163     </dependencies>
    164         

    2、整合Spring Data JPA与Spring

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
     6     xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:task="http://www.springframework.org/schema/task"
     7     xsi:schemaLocation="
     8         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
     9         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
    10         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
    11         http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
    12         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
    13         http://www.springframework.org/schema/data/jpa 
    14         http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
    15     
    16     <!-- 1.dataSource 配置数据库连接池-->
    17     <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    18         <property name="driverClass" value="com.mysql.jdbc.Driver" />
    19         <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/jpa" />
    20         <property name="user" value="root" />
    21         <property name="password" value="111111" />
    22     </bean>
    23     
    24     <!-- 2.配置entityManagerFactory -->
    25     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    26         <property name="dataSource" ref="dataSource" />
    27         <property name="packagesToScan" value="cn.itcast.entity" />
    28         <property name="persistenceProvider">
    29             <bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
    30         </property>
    31         <!--JPA的供应商适配器-->
    32         <property name="jpaVendorAdapter">
    33             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    34                 <property name="generateDdl" value="false" />
    35                 <property name="database" value="MYSQL" />
    36                 <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
    37                 <property name="showSql" value="true" />
    38             </bean>
    39         </property>
    40         <property name="jpaDialect">
    41             <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    42         </property>
    43     </bean>
    44     
    45     
    46     <!-- 3.事务管理器-->
    47     <!-- JPA事务管理器  -->
    48     <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    49         <property name="entityManagerFactory" ref="entityManagerFactory" />
    50     </bean>
    51     
    52     <!-- 整合spring data jpa-->
    53     <jpa:repositories base-package="top.biyenanhai.mapper"
    54         transaction-manager-ref="transactionManager"
    55         entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    56         
    57     <!-- 4.txAdvice-->
    58     <tx:advice id="txAdvice" transaction-manager="transactionManager">
    59         <tx:attributes>
    60             <tx:method name="*" propagation="REQUIRED"/>
    61             <tx:method name="get*" read-only="true"/>
    62             <tx:method name="find*" read-only="true"/>
    63         </tx:attributes>
    64     </tx:advice>
    65     
    66     <!-- 5.aop-->
    67     <aop:config>
    68         <aop:pointcut id="pointcut" expression="execution(* top.biyenanhai.service.*.*(..))" />
    69         <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" />
    70     </aop:config>
    71     
    72     <context:component-scan base-package="cn.itcast"></context:component-scan>
    73     <!--6、配置包扫描-->
    74     <context:component-scan base-package="top.biyenanhai"/>
    75     <!--组装其它 配置文件-->
    76     
    77 </beans>

    3、使用JPA注解配置映射关系

    package top.biyenanhai.entity;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    /**
     * 
     *      * 所有的注解都是使用JPA的规范提供的注解,
     *      * 所以在导入注解包的时候,一定要导入javax.persistence下的
     */
    @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")//指定和表中cust_source字段的映射关系
        private String custSource;
        
        @Column(name="cust_industry")//指定和表中cust_industry字段的映射关系
        private String custIndustry;
        
        @Column(name="cust_level")//指定和表中cust_level字段的映射关系
        private String custLevel;
        
        @Column(name="cust_address")//指定和表中cust_address字段的映射关系
        private String custAddress;
        
        @Column(name="cust_phone")//指定和表中cust_phone字段的映射关系
        private String custPhone;
        
        //添加get,set方法,toString方法
    }

    3、编写符合Spring Data JPA规范的Dao层接口,继承JpaRepository<T,ID>和JpaSpecificationExecutor<T>

     *     JpaRepository<操作的实体类类型,实体类中主键属性的类型>
     *              *封装了基本CURD操作
     *     JpaSpecificationExecutor<操作的实体类类型>
     *              *封装了复杂查询(分页)
    package top.biyenanhai.dao;
    
    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 top.biyenanhai.domain.Customer;
    
    import java.util.List;
    
    /**
     * Created with IntelliJ IDEA.
     *
     * @Auther: 毕业男孩
     *
     * 符合SpringDataJpa的dao接口规范
     *      JpaRepository<操作的实体类类型,实体类中主键属性的类型>
     *              *封装了基本CURD操作
     *      JpaSpecificationExecutor<操作的实体类类型>
     *              *封装了复杂查询(分页)
     *
     */
    public interface CustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
    
        /**
         * 案例:根据客户名称查询客户
         *      使用jpql的形式查询
         *
         *  jpql:from Customer where custName = ?
         *
         *  配置jpql语句,使用@Query注解
         */
        @Query(value="from Customer where custName = ? ")
        Customer findJpql(String custName);
    
        /**
         * 案例:根据客户名称和客户id查询客户
         *      jqpl:from Customer where cutName = ? and custId = ?
         *
         *   对于多个占位符参数
         *          赋值的时候,默认的情况下,占位符的位置需要和方法参数中的位置保持一致
         *   可以指定占位符参数的位置
         *          ?索引的方式,指定此占位的取值来源
         */
        @Query(value = "from Customer where custName=?2 and custId=?1")
        Customer findCustNameAndCustId(Long id,String name);
    
    
        /**
         * 使用jpql完成更新操作
         *      案例:根据id更新,客户的名称
         *          更新4号客户的名称,将名称改为“老男孩”
         *
         *
         * sql:update cst_customer set cust_name = ?where cust_id=?
         * jpql:update Customer set custName=? where custId=?
         *
         * @Query:代表的是进行查询
         *      声明此方法是用来更新操作
         * @Modifying:当前执行的是一个更新操作
         */
        @Query(value = "update Customer set custName=?2 where custId=?1")
        @Modifying
        void updateCustomer(long id, String custName);
    
    
        /**
         * 使用sql的形式查询:
         *      查询全部的客户
         *      sql:select * from cst_custimer;
         *      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) //条件查询
        List<Object[]> findSql(String name);
    
    
        /**
         * 方法名的约定:
         *      findBy:查询
         *          对象中的属性名(首字母大写):查询的条件
         *          CustName
         *          *默认情况:使用 等于的方式查询
         *              特殊的查询方式
         * findByCustName --  根据客户名称查询
         *
         * 在springdataJpa的运行阶段
         *      会根据方法名称进行解析  findBy  from xxx(实体类)
         *                                  属性名称    where custName =
         *
         *
         *      1、findBy + 属性名称(根据属性名称进行完成匹配的查询=)
         *      2、findBy + 属性名称 + “查询方式(Like|isnull)”
         *      3、多条件查询
         *          findBy + 属性名 + "查询条件" + "多条件的连接符(and|or)" + 属性名 + “查询方式”
         *
         */
        Customer findByCustName(String custName);
    
        List<Customer> findByCustNameLike(String name);
    
        List<Customer> findByCustNameLikeAndCustIndustry(String name, String industry);
    
    }

    4、测试基本CRUD操作

    @RunWith(SpringJUnit4ClassRunner.class) //声明spring提供的单元测试环境
    @ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
    public class CustomerDaoTest {
    
        @Autowired
        private CustomerDao customerDao;
    
        /**
         * 根据id查询
         */
        @Test
        public void testFindOne(){
            Customer customer = customerDao.findOne(1l);
            System.out.println(customer);
        }
    ......
        
        /**
         * 测试jqpl的更新操作
         * 更新和删除操作要加上事务的注解
         *
         * springDataJpa中使用jpql完成  更新/删除操作
         *          需要手动添加事务的支持
         *          默认回执行结束之后,回滚事务
         *    @Rollback:设置是否自动回滚
         */
        @Test
        @Transactional//添加事务的支持
        @Rollback(false)
        public void testUpdate(){
            customerDao.updateCustomer(1l, "航空航天科技有限公司");
        }
    ......

    5、具体关键字,使用方法和生产成SQL如下表所示

    Keyword

    Sample

    JPQL

    And

    findByLastnameAndFirstname

    … where x.lastname = ?1 and x.firstname = ?2

    Or

    findByLastnameOrFirstname

    … where x.lastname = ?1 or x.firstname = ?2

    Is,Equals

    findByFirstnameIs,

    findByFirstnameEquals

    … where x.firstname = ?1

    Between

    findByStartDateBetween

    … where x.startDate between ?1 and ?2

    LessThan

    findByAgeLessThan

    … where x.age < ?1

    LessThanEqual

    findByAgeLessThanEqual

    … where x.age ?1

    GreaterThan

    findByAgeGreaterThan

    … where x.age > ?1

    GreaterThanEqual

    findByAgeGreaterThanEqual

    … where x.age >= ?1

    After

    findByStartDateAfter

    … where x.startDate > ?1

    Before

    findByStartDateBefore

    … where x.startDate < ?1

    IsNull

    findByAgeIsNull

    … where x.age is null

    IsNotNull,NotNull

    findByAge(Is)NotNull

    … where x.age not null

    Like

    findByFirstnameLike

    … where x.firstname like ?1

    NotLike

    findByFirstnameNotLike

    … where x.firstname not like ?1

    StartingWith

    findByFirstnameStartingWith

    … where x.firstname like ?1 (parameter bound with appended %)

    EndingWith

    findByFirstnameEndingWith

    … where x.firstname like ?1 (parameter bound with prepended %)

    Containing

    findByFirstnameContaining

    … where x.firstname like ?1 (parameter bound wrapped in %)

    OrderBy

    findByAgeOrderByLastnameDesc

    … where x.age = ?1 order by x.lastname desc

    Not

    findByLastnameNot

    … where x.lastname <> ?1

    In

    findByAgeIn(Collection ages)

    … where x.age in ?1

    NotIn

    findByAgeNotIn(Collection age)

    … where x.age not in ?1

    TRUE

    findByActiveTrue()

    … where x.active = true

    FALSE

    findByActiveFalse()

    … where x.active = false

    IgnoreCase

    findByFirstnameIgnoreCase

    … where UPPER(x.firstame) = UPPER(?1)

    六、Specifications动态查询:

      有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。

    /**
        *    root    :Root接口,代表查询的根对象,可以通过root获取实体中的属性
        *    query    :代表一个顶层查询对象,用来自定义查询
        *    cb        :用来构建查询,此对象里有很多条件方法
        **/
        public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

    案例:使用Specifications完成条件查询

    //依赖注入customerDao
        @Autowired
        private CustomerDao customerDao;    
        @Test
        public void testSpecifications() {
              //使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
            Specification <Customer> spec = new Specification<Customer>() {
                public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    //cb:构建查询,添加查询方式   like:模糊匹配
                    //root:从实体Customer对象中按照custName属性进行查询
                    return cb.like(root.get("custName").as(String.class), "航天航空%");
                }
            };
            Customer customer = customerDao.findOne(spec);
            System.out.println(customer);
        }

    案例:基于Specifications的分页查询

    @Test
        public void testPage() {
            //构造查询条件
            Specification<Customer> spec = new Specification<Customer>() {
                public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                    return cb.like(root.get("custName").as(String.class), "航天%");
                }
            };
            
            /**
             * 构造分页参数
             *         Pageable : 接口
             *             PageRequest实现了Pageable接口,调用构造方法的形式构造
             *                 第一个参数:页码(从0开始)
             *                 第二个参数:每页查询条数
             */
            Pageable pageable = new PageRequest(0, 5);
            
            /**
             * 分页查询,封装为Spring Data Jpa 内部的page bean
             *         此重载的findAll方法为分页方法需要两个参数
             *             第一个参数:查询条件Specification
             *             第二个参数:分页参数
             */
            Page<Customer> page = customerDao.findAll(spec,pageable);
            
        }

    对于Spring Data JPA中的分页查询,是其内部自动实现的封装过程,返回的是一个Spring Data JPA提供的pageBean对象。其中的方法说明如下:

    //获取总页数
    int getTotalPages();
    //获取总记录数    
    long getTotalElements();
    //获取列表数据
    List<T> getContent();

    方法对应关系:

    方法名称

    Sql对应关系

    equal

    filed = value

    gt(greaterThan )

    filed > value

    lt(lessThan )

    filed < value

    ge(greaterThanOrEqualTo )

    filed >= value

    le( lessThanOrEqualTo)

    filed <= value

    notEqual

    filed != value

    like

    filed like value

    notLike

    filed not like value

    七、JPA中的一对多:

    实体类(一对多,一的实体类)

    /**
     * 客户的实体类
     * 明确使用的注解都是JPA规范的
     * 所以导包都要导入javax.persistence包下的
     */
    @Entity//表示当前类是一个实体类
    @Table(name="cst_customer")//建立当前实体类和表之间的对应关系
    public class Customer implements Serializable {
        
        @Id//表明当前私有属性是主键
        @GeneratedValue(strategy=GenerationType.IDENTITY)//指定主键的生成策略
        @Column(name="cust_id")//指定和数据库表中的cust_id列对应
        private Long custId;
        @Column(name="cust_name")//指定和数据库表中的cust_name列对应
        private String custName;
        
        //配置客户和联系人的一对多关系
        @OneToMany(targetEntity=LinkMan.class)
        @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
        private Set<LinkMan> linkmans = new HashSet<LinkMan>();

    ...get,set方法

    实体类(一对多,多的实体类)

    /**
     * 联系人的实体类(数据模型)
     */
    @Entity
    @Table(name="cst_linkman")
    public class LinkMan implements Serializable {
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="lkm_id")
        private Long lkmId;
        @Column(name="lkm_name")
        private String lkmName;
        @Column(name="lkm_gender")
        private String lkmGender;
        @Column(name="lkm_phone")
        private String lkmPhone;
    
        //多对一关系映射:多个联系人对应客户
        @ManyToOne(targetEntity=Customer.class)
        @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
        private Customer customer;//用它的主键,对应联系人表中的外键

    ...get,set方法

    八、JPA中的多对多:

    /**
     * 用户的数据模型
     */
    @Entity
    @Table(name="sys_user")
    public class SysUser implements Serializable {
        
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="user_id")
        private Long userId;
        @Column(name="user_name")
        private String userName;
    
        
        //多对多关系映射
        @ManyToMany(mappedBy="users")
        private Set<SysRole> roles = new HashSet<SysRole>();
    /**
     * 角色的数据模型
     */
    @Entity
    @Table(name="sys_role")
    public class SysRole implements Serializable {
        
        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY)
        @Column(name="role_id")
        private Long roleId;
        @Column(name="role_name")
        private String roleName;
        
        //多对多关系映射
        @ManyToMany
        @JoinTable(name="user_role_rel",//中间表的名称
                  //中间表user_role_rel字段关联sys_role表的主键字段role_id
                  joinColumns={@JoinColumn(name="role_id",referencedColumnName="role_id")},
                  //中间表user_role_rel的字段关联sys_user表的主键user_id
                  inverseJoinColumns={@JoinColumn(name="user_id",referencedColumnName="user_id")}
        )
        private Set<SysUser> users = new HashSet<SysUser>();

    映射的注解说明

    @OneToMany:
           作用:建立一对多的关系映射
        属性:
            targetEntityClass:指定多的多方的类的字节码
            mappedBy:指定从表实体类中引用主表对象的名称。
            cascade:指定要使用的级联操作
            fetch:指定是否采用延迟加载
    
    @ManyToOne
        作用:建立多对一的关系
        属性:
            targetEntityClass:指定一的一方实体类字节码
            cascade:指定要使用的级联操作
            fetch:指定是否采用延迟加载
            optional:关联是否可选。如果设置为false,则必须始终存在非空关系。
    
    @JoinColumn
         作用:用于定义主键字段和外键字段的对应关系。
         属性:
            name:指定外键字段的名称
            referencedColumnName:指定引用主表的主键字段名称
            unique:是否唯一。默认值不唯一
            nullable:是否允许为空。默认值允许。
            insertable:是否允许插入。默认值允许。
            updatable:是否允许更新。默认值允许。
            columnDefinition:列的定义信息。

    九、Spring Data JPA中的多表查询:

      对象导航查询:对象导航检索方式是根据已经加载的对象,导航到他的关联对象。它利用类与类之间的关系来检索对象。例如:我们通过ID查询方式查出一个客户,可以调用Customer类中的getLinkMans()方法来获取该客户的所有联系人。对象导航查询的使用要求是:两个对象之间必须存在关联关系。

    //查询一个客户,获取该客户下的所有联系人
    @Autowired
    private CustomerDao customerDao;
        
    @Test
    //由于是在java代码中测试,为了解决no session问题,将操作配置到同一个事务中
    @Transactional 
    public void testFind() {
        Customer customer = customerDao.findOne(5l);
        Set<LinkMan> linkMans = customer.getLinkMans();//对象导航查询
        for(LinkMan linkMan : linkMans) {
              System.out.println(linkMan);
        }
    }
    //查询一个联系人,获取该联系人的所有客户
    @Autowired
    private LinkManDao linkManDao;
        
    @Test
    public void testFind() {
        LinkMan linkMan = linkManDao.findOne(4l);
        Customer customer = linkMan.getCustomer(); //对象导航查询
        System.out.println(customer);
    }

    采用延迟加载的思想。通过配置的方式来设定当我们在需要使用时,发起真正的查询。

    配置方式:

    /**
     * 在客户对象的@OneToMany注解中添加fetch属性
     *     FetchType.EAGER    :立即加载
     *     FetchType.LAZY            :延迟加载
     */
     @OneToMany(mappedBy="customer",fetch=FetchType.EAGER)
     private Set<LinkMan> linkMans = new HashSet<>();
        
    /**
     * 在联系人对象的@ManyToOne注解中添加fetch属性
     *         FetchType.EAGER    :立即加载
     *         FetchType.LAZY    :延迟加载
     */
     @ManyToOne(targetEntity=Customer.class,fetch=FetchType.EAGER)
     @JoinColumn(name="cst_lkm_id",referencedColumnName="cust_id")
     private Customer customer;

    使用Specification查询

    /**
     * Specification的多表查询
     */
    @Test
    public void testFind() {
        Specification<LinkMan> spec = new Specification<LinkMan>() {
            public Predicate toPredicate(Root<LinkMan> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //Join代表链接查询,通过root对象获取
                //创建的过程中,第一个参数为关联对象的属性名称,第二个参数为连接查询的方式(left,inner,right)
                //JoinType.LEFT : 左外连接,JoinType.INNER:内连接,JoinType.RIGHT:右外连接
                Join<LinkMan, Customer> join = root.join("customer",JoinType.INNER);
                return cb.like(join.get("custName").as(String.class),"航空航天");
            }
        };
        List<LinkMan> list = linkManDao.findAll(spec);
        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
    }

     

  • 相关阅读:
    逗号操作符使用小技巧
    字符解码?
    画图 wx.Window pen
    进程和线程
    内存管理
    简单的文本编辑器
    迭代器 Iterator
    文件操作
    ebay api学习
    一,wxpython入门
  • 原文地址:https://www.cnblogs.com/biyenanhai/p/13167246.html
Copyright © 2020-2023  润新知