• spring data jpa


    jpa:java persistence api java持久化api

    orm思想

    • 操作实体类相当于操作数据库表,不在重点关注sql语句
    • 两个映射:1-实体类和表 2-属性和字段
    • 实现orm思想的框架如:mybatis、hibernate

    jpa规范

    • jdbc规范:封装好具体操作数据库接口、方法,只需修改对应驱动
    • 内部由接口和抽象类组成
    • jpa规范不干活,依托实现方式(如:hibernate)来操作。

    jpa使用操作

    • 1-jar依赖
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.hibernate.version>5.0.7.Final</project.hibernate.version>
    </properties>
    
    <dependencies>
        <!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    
        <!-- hibernate对jpa的支持包 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>
    
        <!-- c3p0 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${project.hibernate.version}</version>
        </dependency>
    
        <!-- log日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    
        <!-- Mysql and MariaDB -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    
    </dependencies>
    
    • 2-配置文件 需在class目录下的META-INF目录及名称为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>
    
            <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>
                <property name="javax.persistence.jdbc.password" value="root"></property>
                <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"></property>
                <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///mydb"></property>
    
                <!--可选配置:配置jpa实现方式的配置信息
                    显示sql    true=显示  false=不显示
                    自动创建数据库表 :
                        create=程序运行时创建数据库表,有表先删再创建
                        update=程序运行时创建数据库表  有表不会创建
                        none=不会创建数据库表
                 -->
                <property name="hibernate.show_sql" value="true"></property>
                <property name="hibernate.hbm2ddl.auto" value="update"></property>
            </properties>
        </persistence-unit>
    
    </persistence>
    
    • 3-实体类与表映射
    package com.xiaoai.domain;
    
    import javax.persistence.*;
    
    /**
     * 客户实体类   需要配置映射关系
     *      1-实体类和表映射
     *      2-属性和字段映射
     *
     *  主键生成策略
     *      IDENTITY=自增   底层必须支持自增      mysql
     *      SEQUENCE=序列   底层必须支持序列      oracle
     *      TABLE=jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
     *      AUTO=由程序自动帮助我们选择主键生成策略
     */
    @Entity   //1-1声明此类为实体类
    @Table(name = "mjfs14_customer")   //1-2配置实体类和表映射
    public class Customer {
    
        //2-1配置属性字段映射
        @Id  //声明主键
        @GeneratedValue(strategy = GenerationType.IDENTITY)  //配置主键生成策略  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;//客户地址
    
        ......对应属性get和set方法以及toString方法
    
    
    • 4-具体CRUD操作
      EntityManager相关方法
    • presist(对象) 保存
    • merge(对象) 更新 先查询得到对象,修改对象然后执行修改
    • remove(对象) 删除 先查询得到对象,传入对象进行删除
    • find(待封装对象class,id)/getRefrence(待封装对象class,id) 根据id查询 find立即加载,getRefrence延时加载(懒加载)
    package com.xiaoai.test;
    
    
    import com.sun.xml.internal.txw2.TXW;
    import com.xiaoai.domain.Customer;
    import com.xiaoai.utils.JpaUtils;
    import org.junit.Test;
    
    import javax.persistence.*;
    
    /**
     * jpa相应操作
     *
     * jpa操作步骤:
     *      1-加载配置文件创建工厂(实体管理器工厂)对象
     *          EntityManagerFactory创建过程比较浪费资源
     *          特点:线程安全对象:多个线程访问同一个EntityManagerFactory不会有线程安全问题
     *          ---解决EntityManagerFactory创建过程浪费资源(耗时)问题?
     *          思路:创建公共EntityManagerFactory对象   解决:java中可以使用静态代码块形式创建EntityManagerFactory
     *      2-通过实体管理类工厂获取实体管理器
     *          方法:createEntityManager
     *          内部维护很多内容:数据库信息、缓存信息、所有实体类管理器对象等
     *
     *          createEntityManager对象:实体类管理器   方法:
     *              beginTransaction=创建事务对象
     *              presist=保存
     *              merge=更新
     *              remove=删除
     *              find/getRefrence=根据id查询
     *      3-获取事务对象,开启事务
     *          EntityTransaction 事务对象
     *              begin=开启事务
     *              commit=提交事务
     *              rellback=回滚
     *      4-完成相关增删改查操作
     *      5-提交事务(回滚事务)
     *      6-释放资源
     */
    public class JpaTest {
    
        /**
         *  -----测试jpa的增加 presist
         */
        @Test
        public  void testSave(){
            //1-加载配置文件创建工厂(实体管理器工厂)  根据持久化单元名称创建实体类工厂
            EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
            //2-获取实体类管理器
            EntityManager em = factory.createEntityManager();
            //3-获取事务管理    打开事务
            EntityTransaction tx = em.getTransaction();
            tx.begin();
            //4-执行操作  增加 presist
            Customer customer = new Customer();
            customer.setCustName("xiaoai");
            customer.setCustIndustry("it");
            em.persist(customer);
            //5-提交事务
            tx.commit();
            //6-释放资源
            em.close();
            factory.close();
        }
    
        /**
         * -----根据id查询  使用find方法
         *  1-查询对象就是当前待查询对象本身
         *  2-调用find方法时,就会发送sql语句查询数据库
         *
         *  立即加载:得到的即对象本身,调用方法就完成加载
         */
        @Test
        public void testFind(){
            //获取管理器
            EntityManager entityManager = JpaUtils.getEntityManager();  //通过JpaUtils封装生成同一EntityManagerFactory对象,减少资源耗费及耗时
            //获取事务 打开事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
            Customer customer = entityManager.find(Customer.class, 1l);
            System.out.println(customer);
            //提交事务
            tx.commit();
            //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
            entityManager.close();
        }
    
        /**
         * -----根据id查询  使用getReference方法
         *  1-查询对象是一个动态代理对象
         *  2-不会即时发送sql语句查询数据库,当调用查询结果对象的时候,才会发送查询的sql语句(即什么时候用什么时候发送)
         *  延时加载(懒加载):得到的是一个动态代理对象  什么时候用什么时候加载
         *
         *  一般使用延时加载,
         */
        @Test
        public void testGetReference(){
            //获取管理器
            EntityManager entityManager = JpaUtils.getEntityManager();
            //获取事务 打开事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
            Customer customer = entityManager.getReference(Customer.class, 1l);//getReference
            System.out.println(customer);
            //提交事务
            tx.commit();
            //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
            entityManager.close();
        }
    
        //-----删除   remove
        @Test
        public void testRemove(){
            //获取管理器
            EntityManager entityManager = JpaUtils.getEntityManager();
            //获取事务 打开事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作  删除 先查后删
            //--1-根据id查询客户
            Customer customer = entityManager.find(Customer.class, 1l);//getReference
            //--2-传入所查询结果删除
            entityManager.remove(customer);
            //提交事务
            tx.commit();
            //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
            entityManager.close();
        }
    
        //-----更新   merge
        @Test
        public void testUpdate(){
            //获取管理器
            EntityManager entityManager = JpaUtils.getEntityManager();
            //获取事务 打开事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作  更新  先查询获取对象,修改对象后更新对象
            //--1-根据id查询客户
            Customer customer = entityManager.find(Customer.class, 2l);//getReference
            //--2-修改对象信息
            customer.setCustIndustry("net");
            //--2-传入所查询结果删除
            entityManager.merge(customer);
            //提交事务
            tx.commit();
            //关闭  由于使用同一个EntityManagerFactory对象,所以其暂时不能关闭
            entityManager.close();
        }
    }
    
    

    EntityManagerFactory封装

    package com.xiaoai.utils;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    
    /**
     * 解决实体管理器工厂的浪费资源和耗时问题
     *  通过静态代码块的形式,当程序第一次访问此工具类是,创建一个公共的实体管理器工厂对象
     *
     *  1-第一次访问getEntityManager方法,经静态代码块创建factory对象,再调用方法创建一个EntityManager对象
     *  2-第二次访问getEntityManager方法,直接通过一个已经创建好的factory对象创建EntityManager对象
     */
    public class JpaUtils {
        private static EntityManagerFactory factory;
    
        static {
            //加载配置文件,创建EntityManagerFactory
            factory  = Persistence.createEntityManagerFactory("myJpa");
        }
    
        /**
         * 用来获取EntityManager对象
         */
        public static EntityManager getEntityManager(){
            return factory.createEntityManager();
        }
    }
    

    jpql查询 java persistence query language jpa提供的一种查询语句 和sql差不多

    sql:查询的是表和表中的字段
    jpql:查询的是实体类和类中属性

    步骤:

    • 1-EntityManagerFactory 工厂
    • 2-EntityManager 实体类管理器
    • 3-EntityTransaction 打开事务
    • 4-Query:jpql具体查询语句获取query对象,query对象执行查询 (jpa直接通过EntityManager对象进行操作)
    • 5-提交事务
    • 6-释放资源
    package com.xiaoai.test;
    
    import com.xiaoai.utils.JpaUtils;
    import org.junit.Test;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Query;
    import java.util.List;
    
    /**
     * jpql查询
     */
    public class JpqlTest {
    
        /**
         * -----查询全部
         *      sql:select * from mjfs14_customer
         *      jqpl:from com.xiaoai.domain.Customer(可以使用全限定类名也可以简写: from Customer)
         */
        @Test
        public void testFindAll(){
            //获取entityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
                //--1获取query对象
                String jpql = "from com.xiaoai.domain.Customer";
                Query query = entityManager.createQuery(jpql);
                //--2具体操作,封装结果集
                List list = query.getResultList();
                for (Object obj:list ) {
                    System.out.println(obj);
                }
            //提交事务
            tx.commit();
            //释放资源
            entityManager.close();
    
            /*结果如下:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    
        /**
         * -----倒叙查询
         *      sql: select * from mjfs14_customer order by cust_id DESC
         *      jpql: from Customer order by custId desc
         */
        @Test
        public void testOrders(){
            //获取entityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
                //--1获取query对象
                String jpql = "from Customer order by custId desc";
                Query query = entityManager.createQuery(jpql);
                //--2具体操作,封装结果集
                List list = query.getResultList();
                for (Object obj:list ) {
                    System.out.println(obj);
                }
            //提交事务
            tx.commit();
            //释放资源
            entityManager.close();
    
            /*结果如下:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ order by customer0_.cust_id desc
            Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    
        /**
         * -----统计查询
         *      sql: select count(cust_id) from mjfs14_customer
         *      jpql: select count(custId) from Customer
         */
        @Test
        public void testCount(){
            //获取entityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
                //--1获取query对象
                String jpql = "select count(custId) from Customer";
                Query query = entityManager.createQuery(jpql);
                //--2具体操作,封装结果集
                Object result = query.getSingleResult();//得到唯一的结果集
            System.out.println(result);
            //提交事务
            tx.commit();
            //释放资源
            entityManager.close();
    
            /*结果如下:
            Hibernate: select count(customer0_.cust_id) as col_0_0_ from mjfs14_customer customer0_
            4
            */
        }
    
        /**
         * -----分页查询
         *      sql: select * from mjfs14_customer limit ?,?
         *      jpql: from Customer
         */
        @Test
        public void testPaged(){
            //获取entityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
                //--1获取query对象
                String jpql = "from Customer";
                Query query = entityManager.createQuery(jpql);
                //--2具体操作,封装结果集
                //----设置参数(分页参数)
                query.setFirstResult(0);//从下标0开始查
                query.setMaxResults(2);//每次查询两条
                List list = query.getResultList();
                for (Object obj:list ) {
                    System.out.println(obj);
                }
            //提交事务
            tx.commit();
            //释放资源
            entityManager.close();
    
            /*结果如下:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ limit ?
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    
        /**
         * -----条件查询
         *      sql: select * from mjfs14_customer where cust_name like ?
         *      jpql: from Customer where custName like ?
         */
        @Test
        public void testCondition(){
            //获取entityManager对象
            EntityManager entityManager = JpaUtils.getEntityManager();
            //开启事务
            EntityTransaction tx = entityManager.getTransaction();
            tx.begin();
            //操作
                //--1获取query对象
                String jpql = "from Customer where custName like ?";
                Query query = entityManager.createQuery(jpql);
                //--2具体操作,封装结果集
                //----设置参数(占位符参数)
                query.setParameter(1,"xiaoai%");//参数:1=第几个占位符  2=代替值
                List list = query.getResultList();
                for (Object obj:list ) {
                    System.out.println(obj);
                }
            //提交事务
            tx.commit();
            //释放资源
            entityManager.close();
    
            /*结果如下:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name like ?
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    }
    
    

    spring data jpa

    相互关系:我们写的java代码——》spring data jpa——》jpa规范——》hibernate(封装jdbc)——》数据库

    基础使用

    • 导入jar
    <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>
    
    • 配置spring配置文件(配置spring data jpa整合)
    <?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对象-->
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource"></property><!--数据源-->
            <property name="packagesToScan" value="com.xiaoai.domain"></property><!--扫描实体类所在包-->
            <property name="persistenceProvider">
                <bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean><!--配置jpa的实现厂家-->
            </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" /><!--数据库方言:数据库支持的特有语法-->
                    <property name="showSql" value="true" /><!--是否显示sql语句:即是否打印到控制台-->
                </bean>
            </property>
            <!--jpa方言,高级特性-->
            <property name="jpaDialect">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"></bean>
            </property>
        </bean>
        <!--2=创建数据库连接池-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="user" value="root"></property>
            <property name="password" value="root"></property>
            <property name="jdbcUrl" value="jdbc:mysql:///mydb?useUnicode=true&amp;characterEncoding=UTF-8"></property>
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        </bean>
        <!--3=整合spring dataJpa-->
        <jpa:repositories base-package="com.xiaoai.dao"
                          transaction-manager-ref="transactionManager"
                            entity-manager-factory-ref="entityManagerFactory">
        </jpa:repositories>
    
        <!--4=配置事务管理器-->
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"></property>
        </bean>
    
        <!--5=spring声明式事务-->
        <!--6=配置包扫描-->
        <context:component-scan base-package="com.xiaoai"></context:component-scan>
    </beans>
    
    • 编写实体类及映射 同jpa一致
    • 编写dao层
      • 只要编写dao接口,不需编写实现类
      • 接口需继承两接口:JpaRepository, JpaSpecificationExecutor 接口需提供响应泛型
        • JpaRepository<操作的实体类类型,实体类类型主键属性的类型> 封装了基本curd操作
        • JpaSpecificationExecutor<操作的实体类类型> 封装了复杂查询(分页等)
    package com.xiaoai.dao;
    
    import com.xiaoai.domain.Customer;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    
    public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {
    
    }
    
    • 注入接口对象,直接使用

    接口相关方法

    • findOne(id) 根据id查询
    • save(对象) 对象标识主键 不存在=新增 存在=修改(修改需要先查询然后修改,不要直接创建相同id的对象然后直接执行修改)
    • delete(id) 根据id删除
    • findAll() 查询所有
    • count() 统计总数量
    • exists(id) 查询id为xx的数据是否存在
      • 思路1:查询id为xx数据,判断值是否为空
      • 思路2:判断id为xx的数据数量,数量为0即不存在 JPA即是该种思路
    • getOne(id) 根据id查询 测试方法上需要 @Transactional支持
      • 与findOne区别:findOne底层调用entityManager的find()方法即立即加载,GetOne底层调用entityManager的getRefrence()方法即延时加载。为了延时加载正常执行需要加上事务支持
    package com.xiaoai.test;
    
    import com.xiaoai.dao.CustomerDao;
    import com.xiaoai.domain.Customer;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.util.List;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class CustomerDaoTest {
    
        @Autowired
        CustomerDao customerDao;
    
        /**
         * -----根据id查询
         */
        @Test
        public void testFindOne(){
            Customer one = customerDao.findOne(3l);
            System.out.println(one);
    
            /*结果
            Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
            Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
        /**
         * -----save:保存或者更新,根据传入的对象主键id是否存在判断新增或更新
         */
        @Test
        public void testSave(){
            //新增
            Customer customer = new Customer();
            customer.setCustName("程序员");
            customer.setCustLevel("3");
            customer.setCustIndustry("it");
            customerDao.save(customer);
        }
        /**
         * -----save:保存或者更新,根据传入的对象主键id是否存在判断新增或更新
         */
        @Test
        public void testUpdate(){
    //        Customer customer = new Customer();
    //        customer.setCustId(5l); //id为5的数据已经存在,
    //        customer.setCustName("程序员");
    //        customerDao.save(customer);
            //如果像上面那样修改,则id为5的数据名称改为了程序员,但其他属性将变为空。
            // 因为修改是查询然后修改,这里直接定义了新对象设置了名称其他属性都为空,即用其替换了原来的5号数据
            //应该先查询获得对象,然后修改对象再执行修改。
            Customer customer = customerDao.findOne(5l);
            customer.setCustName("程序员");//修改编号5数据的名称为程序员
            customerDao.save(customer);
        }
         /**
         * -----删除
         */
        @Test
        public void testDelete(){
            customerDao.delete(6l);
        }
        /**
         * -----查询所有
         */
        @Test
        public void testFindAll(){
            List<Customer> all = customerDao.findAll();
            for (Customer c : all) {
                System.out.println(c);
            }
            /* 测试结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=3, custName='xiaoai3', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=5, custName='程序员', custSource='null', custIndustry='it', custLevel='3', custAddress='null', custPhone='null'}
            */
    
        }
        /**
         *-----统计查询
         */
        @Test
        public void testCount(){
            long count = customerDao.count();
            System.out.println(count);
            /*测试结果:
            Hibernate: select count(*) as col_0_0_ from mjfs14_customer customer0_
            5
            */
        }
        /**
         * -----判断数据是否存在
         */
        @Test
        public void testExists(){
            boolean exists = customerDao.exists(4l);
            System.out.println("是否存在:"+exists);
            /*测试结果:
            Hibernate: select count(*) as col_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=? and 1=1
            是否存在:true
            */
        }
        /**
         * -----根据id查询
         */
        @Test
        @Transactional  //保证getOne正常运行
        public void testGetOne(){
            Customer one = customerDao.getOne(4l);
            System.out.println(one);
            /*测试结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
            Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    }
    

    定义jpql/sql语句查询

    • 特有查询:需要在dao接口上配置方法
    • 新添加的方法上使用注解形式配置jpql语句
    • 注解:@query
      • 注解属性value=jpql语句或sql语句
      • 注解属性nativeQuery=false(使用jqpl查询)或true(使用本地查询:即sql查询)
    • jpql更深层封装:只需要按照springDataJpa提供的方法名称规则定义方法,不需要去配置jpql语句,也可以完成查询
      • findBy+属性名称() = 查询 如:findByCustName 根据方法名称(findBy)解析要查询 from 实体类 where 属性名称(如custName) = 参数
      • findBy+属性名称+查询方式(like、isnull) 如:findByCustNameLike
      • findBy+属性名+查询方式+多条件连接符(and、or)+属性名+查询方式(精准匹配可以省略查询方式) 如:findByCustNameLikeAndCustIndustry
        接口定义的方法
    package com.xiaoai.dao;
    
    import com.xiaoai.domain.Customer;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.jpa.repository.Query;
    
    import java.util.List;
    
    /**
     * 定义符合springdataJpa的dao层接口规范
     *      JpaRepository<操作的实体类类型,实体类类型主键属性的类型>
     *          封装了基本curd操作
     *     JpaSpecificationExecutor<操作的实体类类型>
     *         封装了复杂查询(分页)
     */
    public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {
    
        //===============================================================自定义jpql执行方法
        //使用注解@Query
    
        //-----根据客户名称查询客户
        @Query(value = "from Customer where custName=?")
        public Customer jpqlFindByName(String custName);
    
        //-----根据客户名称id查询客户
        // 需要注意多占位符的匹配关系问题
        // 默认情况下,占位符位置需要和方法参数中位置保持一致
        // 但也可以指定占位符参数位置:通过【?索引】的方式指定此占位符的取值来源 如?1 表示该占位符取方法第一个参数
        @Query(value = "from Customer where custName=?1 and custId=?2")
        public Customer jpqlFindByNameAndId(String name,Long id);
    
        //-----根据id更新客户名称
        @Query(value = "update Customer set custName=?2 where custId=?1")
        @Modifying //声明此方法是用来进行更新操作
        public void jpqlUpdateNameById(Long custId,String custName);
    
        //===============================================================自定义sql语句执行方法
        // @Query  属性:value=jpql语句或sql语句   nativeQuery=false(使用jqpl查询)或true(使用本地查询:即使用sql查询)
    
        //-----查询所有
        @Query(value = "select * from mjfs14_customer",nativeQuery = true)
        public List<Object[]> findSql();
    
        //-----根据名称模糊查询
        @Query(value = "select * from mjfs14_customer where cust_name like ?1",nativeQuery = true)
        public List<Object[]> findSqlByName(String name);
    
        //===============================================================jpql的深层封装:根据springDataJpa提供的命名方法
        // findByXxx = 查询  Xxx即对象属性即查询条件  如:findByCustName   根据方法名称(findBy)解析要查询 from 实体类 where xxx(属性名称如custName) = 参数
    
        //-----根据名称查询
        public Customer findByCustName(String custName);
    
        //-----根据名称模糊查询
        public List<Customer> findByCustNameLike(String custName);
    
        //-----查询客户名模糊匹配和客户所属行业精准匹配
        public List<Customer> findByCustNameLikeAndCustIndustry(String custName,String custIndustry);
    
    }
    
    

    测试

    package com.xiaoai.test;
    
    import com.xiaoai.dao.CustomerDao;
    import com.xiaoai.domain.Customer;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.annotation.Rollback;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.management.Query;
    import java.util.Arrays;
    import java.util.List;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:applicationContext.xml")
    public class JpqlTest {
    
        @Autowired
        CustomerDao customerDao;
    
        //-----自定义jpql:根据名称查询
        @Test
        public void testJpqlFindByName(){
            Customer customer = customerDao.jpqlFindByName("xiaoai");
            System.out.println(customer);
            /* 执行结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=?
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
        //-----自定义jpql:根据名称和id查询
        @Test
        public void testJpqlFindByNameAndId(){
            Customer customer = customerDao.jpqlFindByNameAndId("xiaoai",2l);
            System.out.println(customer);
            /* 执行结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=? and customer0_.cust_id=?
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
        //-----自定义jpql:根据id更新客户名称
        @Test
        @Transactional //spring data jpa 使用jpql完成更新、删除操作需要手动添加事务支持 执行结束后其会自动回滚事务
        @Rollback(value = false) //设置不自动回滚
        public void testJpqlUpdateNameById(){
           customerDao.jpqlUpdateNameById(3l,"程序员小艾");
            Customer customer = customerDao.findOne(3l);
            System.out.println(customer);
            /* 执行结果:
            Hibernate: update mjfs14_customer set cust_name=? where cust_id=?
            Hibernate: select customer0_.cust_id as cust_id1_0_0_, customer0_.cust_address as cust_add2_0_0_, customer0_.cust_industry as cust_ind3_0_0_, customer0_.cust_level as cust_lev4_0_0_, customer0_.cust_name as cust_nam5_0_0_, customer0_.cust_phone as cust_pho6_0_0_, customer0_.cust_source as cust_sou7_0_0_ from mjfs14_customer customer0_ where customer0_.cust_id=?
            Customer{custId=3, custName='程序员小艾', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    
        //-----自定义sql:查询所有
        @Test
        public void testFindSql(){
            List<Object[]> list = customerDao.findSql();
            for (Object[] obj : list) {
                System.out.println(Arrays.toString(obj));
            }
            /* 执行结果:
            Hibernate: select * from mjfs14_customer
            [1, xiaoai2, null, it, null, null, null]
            [2, xiaoai, null, net, null, null, null]
            [3, 程序员小艾, null, 无业游民, null, null, null]
            [4, 小艾, null, 教育, null, null, null]
            [5, 程序员, null, it, 3, null, null]
            */
        }
         //-----自定义sql:根据名称模糊查询
        @Test
        public void testFindSqlByName(){
            List<Object[]> list = customerDao.findSqlByName("xiaoai%");
            for (Object[] obj : list) {
                System.out.println(Arrays.toString(obj));
            }
            /* 执行结果:
            Hibernate: select * from mjfs14_customer where cust_name like ?
            [1, xiaoai2, null, it, null, null, null]
            [2, xiaoai, null, net, null, null, null]
            */
        }
    
        //-----jpql进一步封装:根据名称查询
        @Test
        public void testFindByName(){
            Customer customer = customerDao.findByCustName("小艾");
            System.out.println(customer);
            /* 执行结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name=?
            Customer{custId=4, custName='小艾', custSource='null', custIndustry='教育', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
        //-----jpql进一步封装:根据名称模糊查询
        @Test
        public void testFindByNameLike(){
            List<Customer> customers = customerDao.findByCustNameLike("xiaoai%");
            for (Customer c : customers) {
                System.out.println(c);
            }
            /* 执行结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where customer0_.cust_name like ?
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
        //-----jpql进一步封装:客户名模糊匹配和客户所属行业精准匹配
        @Test
        public void testFindByNAndI(){
            List<Customer> customers = customerDao.findByCustNameLikeAndCustIndustry("xiaoai%","it");
            for (Customer c : customers) {
                System.out.println(c);
            }
            /* 执行结果:
            Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ where (customer0_.cust_name like ?) and customer0_.cust_industry=?
            Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
            */
        }
    }
    
    

    specifications动态查询

    Specification即查询条件
    即接口继承的JpaSpecificationExecutor类所提供的方法列表:

    • T findOne(Specification var1); 单个查询
    • List findAll(Specification var1); 查询列表
    • Page findAll(Specification var1, Pageable var2); 分页查询 pageable=分页参数
    • List findAll(Specification var1, Sort var2); 查询列表 sort=排序参数
    • long count(Specification var1); 统计查询

    **使用**

    • 创建Specification对象,通过匿名内部类构建查询条件,再把对象传入JpaSpecificationExecutor提供的方法中完成查询
      • 匿名内部类方法参数:Root 获取查询的对象属性 get()=获取属性
      • 匿名内部类方法参数:CriteriaBuilder 用于构建条件 .equal()=精准查询 .like()=模糊查询 .and()=连接属性
    • equal:直接得到path对象,然后进行比较
    • gt,lt,ge,le,like:得到path对象,根据path指定比较的参数类型,再去进行比较 指定参数类型格式:path对象.as(类型字节码对象) 如: Predicate like = criteriaBuilder.like(custName.as(String.class), "xiaoai%");
    • 排序:创建排序对象做参数传入对应方法 Sort sort = new Sort(Sort.Direction.DESC,"custId");//倒序
    • 分页:创建分页对象做参数传入对应方法
    @Test
    public void testSpec5(){
        //添加分页
        Pageable pageable = new PageRequest(0,3); //创建分页对象 参数:1=当前查询的页数(从0开始) 2=每页查询数量
        Page<Customer> pageCustomer = customerDao.findAll(null, pageable);//Specification传入空,表示查询全部
        System.out.println("总条数:"+pageCustomer.getTotalElements());
        System.out.println("总页数:"+pageCustomer.getTotalPages());
        List<Customer> content = pageCustomer.getContent();//获取当前页数据列表
        for (Customer c : content) {
            System.out.println(c);
        }
    
        /*执行结果:
        Hibernate: select count(customer0_.cust_id) as col_0_0_ from mjfs14_customer customer0_
        Hibernate: select customer0_.cust_id as cust_id1_0_, customer0_.cust_address as cust_add2_0_, customer0_.cust_industry as cust_ind3_0_, customer0_.cust_level as cust_lev4_0_, customer0_.cust_name as cust_nam5_0_, customer0_.cust_phone as cust_pho6_0_, customer0_.cust_source as cust_sou7_0_ from mjfs14_customer customer0_ limit ?
        总条数:5
        总页数:2
        Customer{custId=1, custName='xiaoai2', custSource='null', custIndustry='it', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=2, custName='xiaoai', custSource='null', custIndustry='net', custLevel='null', custAddress='null', custPhone='null'}
        Customer{custId=3, custName='程序员小艾', custSource='null', custIndustry='无业游民', custLevel='null', custAddress='null', custPhone='null'}
        */
    }
    

    多表操作

    一对多

    • 主要是配置实体类映射时和其他实体类的关系
      • 一对一
      • 一对多、多对一 注:在一的一方维护外键即可,不需要一和多都维护外键
      • 多对多
    • 可以添加实体类属性并配置其关系映射可完成多表操作
      • 配置相互关系可用实体类间的包含关系,即在实体类中添加另一个实体类作为属性。并需要配置其关系:1-声明表关系 2-配置外键
    多的一方:
    @OneToMany(targetEntity = LinkMan.class)  //配置一对多关系  需对方字节码对象
    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")  //name=从表的外键字段,referencedColumnName=主表的主键字段
    private Set<LinkMan> linkmans = new HashSet<>();
    
    一的一方:
    //配置联系人到客户多对一关系   1-声明表关系  2-配置外键
    @ManyToOne(targetEntity = Customer.class)
    @JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id") //name=从表的外键字段,referencedColumnName=本表的主键字段
    private Customer customer;
    
    多的一方放弃维护外键:mappedBy="对方配置关系的属性名" 
    @OneToMany(mappedBy="customer")
    private Set<LinkMan> linkmans = new HashSet<>();  //放弃外键维护权,表关系交给一的一方维护
    
    
    • 一对多删除:删除【一一方】需要考虑,因为有可能【多一方】引入了【一一方】 在【一一方】删除时则需要使用级联删除
      • 级联:操作一个对象的同时操作他的关联对象
      • 级联删除:删除【一一方】的同时删除关联其的【多一方】的所有数据。想级联删除需要在操作的主体即【一一方】的实体类上添加级联属性(配置级联:cascade)
    配置级联:
    @OneToMany(mappedBy="customer",cascade = CascadeType.ALL) //CascadeType.ALL=所有操作(insert、delete等)都可级联
    private Set<LinkMan> linkmans = new HashSet<>();
    

    多对多

    • 创建实体类配置映射,通过包含关系加入另一实体类做属性,配置实体类间多对多关系
    //建立关联   1-声明表关系   2-配置中间表(包含两个外键)
    @ManyToMany(targetEntity = Role.class)
    @JoinTable(name = "mjfs14_user_role", //中间表名称     @JoinColumn和@inverseJoinColumns参数:name=对应外键字段  referencedColumnName=对应主键字段
            joinColumns = {@JoinColumn(name = "center_user_id",referencedColumnName = "user_id")}, // 当前对象在中间表中对应外键配置
            inverseJoinColumns = {@JoinColumn(name = "center_role_id",referencedColumnName = "role_id")} //对方对象在中间表中对应外键配置
    )
    private Set<Role> roles = new HashSet<>();
    
    • 放弃外键维护权:两方都是多,随便一方都可以放弃外键维护权 但是一般被选择一方放弃 放弃维护权和【一对多】一致
    • 级联操作:删除对象以及对象关联的对象以及中间表中关联的数据 操作和一对多一致

    对象导航查询

    • 查询一个对象时,通过此对象查询其关联对象 操作即:直接通过对象.getxxx()方法即之前创建关联的对象属性时的get方法获取即可 内部自动查询好了
    • 一方查询多方:默认使用延迟加载(因为在一方查询多方,有可能多方有太多数据,立即加载后不用则极大浪费内存) 多方查询一方:默认使用立即加载(多方查询一方时由于只多一条数据,影响不大,所以立即查询了)
    • 延迟加载: 默认即使用延迟加载的形式查询的 可以修改延迟加载为立即加载 即在实体类映射中通过@OneToMany属性fetch配置 EAGER=立即加载 LAZY=延迟加载
    配置立即加载:
    //使用注解形式配置多表关系  1-声明关系  2-配置外键
    @OneToMany(mappedBy="customer",cascade = CascadeType.ALL,fetch = FetchType.EAGER ) //CascadeType.ALL=所有操作(insert、delete等)都可级联  FetchType.EAGER
    private Set<LinkMan> linkmans = new HashSet<>();
    
  • 相关阅读:
    POJ 1436 Horizontally Visible Segments (线段树+区间覆盖)
    HDU 4671 Backup Plan (构造)
    POJ 3325 Help with Intervals (线段树(难))
    HDU 4649 Professor Tian (位运算 + 按位DP)
    HDU 4662 MU Puzzle (YY+枚举)
    HDU 4638 Group (线段树 + 离线)
    深入浅出Node.js (附录A)
    JS的变量声明和函数声明提升
    JS基础:翻转数组
    JS基础:求一组数中的最大最小值,以及所在位置
  • 原文地址:https://www.cnblogs.com/xiaoaiying/p/13566310.html
Copyright © 2020-2023  润新知