• 黑马程序员spring data jpa 2019年第一版本


    第一步首先创建一个maven工程,导入对于的pom依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.cib.com</groupId>
      <artifactId>heimaspringdatajpa</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      
      <properties>
            <!--版本锁定-->
            <spring.version>5.0.2.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.12</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>
    
            <!-- spring对orm框架的支持包-->
            <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-c3p0</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 -->
    
         
         
    
            <!-- 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>
    
            <!-- spring data jpa 的坐标-->
            <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>${spring.version}</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>
    </project>

    1、接下来创建jpa的核心配置文件

    jpa的核心配置文件必须放在类路径的meta-info文件夹下面,命名也必须满足对于的规则

    PA规范要求在类路径的META-INF目录下放置persistence.xml, 文件的名称是固定的,配置模板如下:

    <!--必须要有name属性,不能为空 -->
    <persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">

    这里

     如果是分布式事务管理,这里就要配置为JTA,这里只操作一个数据库,这里不存在分布式事务,这里设置为RESOURCE_LOCAl

     

     

     persistence.xml的内容如下所示

    <?xml version="1.0" encoding="UTF-8"?>
     <persistence version="2.0" 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">
        
        <!--必须要有name属性,不能为空 -->
         <persistence-unit name="myJap" transaction-type="RESOURCE_LOCAL">
              <!--可选 -->
              <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?useUnicode=true&amp;characterEncoding=UTF-8" />
                <property name="javax.persistence.jdbc.user" value="root" />
                <property name="javax.persistence.jdbc.password" value="123456" />
                <property name="hibernate.show_sql" value="true" />
                <property name="hibernate.hbm2ddl.auto" value="update" />
            </properties>
         </persistence-unit>
                 
     </persistence>

    接下来,我们要编写实体类,创建对于的数据库表

    创建客户的数据库表

    drop table if exists cst_customer;
    /*创建客户表*/
    CREATE TABLE cst_customer (
      cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
      cust_name varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
      cust_source varchar(32) DEFAULT NULL COMMENT '客户信息来源',
      cust_industry varchar(32) DEFAULT NULL COMMENT '客户所属行业',
      cust_level varchar(32) DEFAULT NULL COMMENT '客户级别',
      cust_address varchar(128) DEFAULT NULL COMMENT '客户联系地址',
      cust_phone varchar(64) DEFAULT NULL COMMENT '客户联系电话',
      PRIMARY KEY (`cust_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=UTF8MB4;
    
    ————————————————
    版权声明:本文为CSDN博主「底层_码农」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_40794973/article/details/98895832

    注:表可以不用创建

    3)创建、编写实体类和数据库表的映射配置[重点]

    注解描述

    @Entity:声明实体类】
    @Table : 配置实体类和表的映射关系 , name : 配置数据库表的名称
    /**
         * @Id:声明主键的配置
         * @GeneratedValue:配置主键的生成策略
         *      strategy
         *          GenerationType.IDENTITY :自增,mysql
         *                 * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
         *          GenerationType.SEQUENCE : 序列,oracle
         *                  * 底层数据库必须支持序列
         *          GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
         *          GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
         * @Column:配置属性和字段的映射关系
         *      name:数据库表中字段的名称
         */
        /**
         * 客户编号(主键)
         */

    GenerationType.IDENTITY :自增,mysql
    * * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增) 必须和mysql中的  AUTO_INCREMENT一一对象,cust_id bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',

    @Column:配置属性和字段的映射关系
    * name:数据库表中字段的名称

    package com.itcast.domain;
    
    import java.io.Serializable;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.Table;
    
    /**
     * 客户的实体类
     *      配置映射关系
     *
     *   1.实体类和表的映射关系
     *      @Entity:声明实体类
     *      @Table : 配置实体类和表的映射关系
     *          name : 配置数据库表的名称
     *   2.实体类中属性和表中字段的映射关系
     */
    @Entity
    @Table(name = "cst_customer")
    public class Customer implements Serializable {
     
        /**
         * @Id:声明主键的配置
         * @GeneratedValue:配置主键的生成策略
         *      strategy
         *          GenerationType.IDENTITY :自增,mysql
         *                 * 底层数据库必须支持自动增长(底层数据库支持的自动增长方式,对id自增)
         *          GenerationType.SEQUENCE : 序列,oracle
         *                  * 底层数据库必须支持序列
         *          GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增
         *          GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略
         * @Column:配置属性和字段的映射关系
         *      name:数据库表中字段的名称
         */
        /**
         * 客户编号(主键)
         */
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "cust_id")
        private Long custId;
        /**
         * 客户名称(公司名称)
         */
        @Column(name = "cust_name")
        private String custName;
        /**
         * 客户信息来源
         */
        @Column(name="cust_source")
        private String custSource;
        /**
         * 客户所属行业
         */
        @Column(name="cust_industry")
        private String custIndustry;
        /**
         * 客户级别
         */
        @Column(name="cust_level")
        private String custLevel;
        /**
         * 客户联系地址
         */
        @Column(name="cust_address")
        private String custAddress;
        /**
         * 客户联系电话
         */
        @Column(name="cust_phone")
        private String custPhone;
        public Long getCustId() {
            return custId;
        }
        public void setCustId(Long custId) {
            this.custId = custId;
        }
        public String getCustName() {
            return custName;
        }
        public void setCustName(String custName) {
            this.custName = custName;
        }
        public String getCustSource() {
            return custSource;
        }
        public void setCustSource(String custSource) {
            this.custSource = custSource;
        }
        public String getCustIndustry() {
            return custIndustry;
        }
        public void setCustIndustry(String custIndustry) {
            this.custIndustry = custIndustry;
        }
        public String getCustLevel() {
            return custLevel;
        }
        public void setCustLevel(String custLevel) {
            this.custLevel = custLevel;
        }
        public String getCustAddress() {
            return custAddress;
        }
        public void setCustAddress(String custAddress) {
            this.custAddress = custAddress;
        }
        public String getCustPhone() {
            return custPhone;
        }
        public void setCustPhone(String custPhone) {
            this.custPhone = custPhone;
        }
        
        
    }

    接下来我们就可以编写一个测试类,测试对于的jpa的操作


    /**
    * 测试jpa的保存
    * 案例:保存一个客户到数据库中
    * Jpa的操作步骤
    * 1.加载配置文件创建工厂(实体管理器工厂)对象
    * 2.通过实体管理器工厂获取实体管理器
    * 3.获取事务对象,开启事务
    * 4.完成增删改查操作
    * 5.提交事务(回滚事务)
    * 6.释放资源
    */

    package com.itcast.cn;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    import org.junit.Test;
    
    import com.itcast.domain.Customer;
    
    public class TestJpa {
    
        
        /**
         * 测试jpa的保存
         *      案例:保存一个客户到数据库中
         *  Jpa的操作步骤
         *     1.加载配置文件创建工厂(实体管理器工厂)对象
         *     2.通过实体管理器工厂获取实体管理器
         *     3.获取事务对象,开启事务
         *     4.完成增删改查操作
         *     5.提交事务(回滚事务)
         *     6.释放资源
         */
        @Test
        public void testSave() {
            //1.加载配置文件创建工厂(实体管理器工厂)对象
            EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
            //2.通过实体管理器工厂获取实体管理器
            EntityManager em = factory.createEntityManager();
         
            //3.获取事务对象,开启事务
            EntityTransaction tx = em.getTransaction(); //获取事务对象
            tx.begin();//开启事务
            try{
                //4.完成增删改查操作:保存一个客户到数据库中
                Customer customer = new Customer();
                customer.setCustName("蔡徐坤");
                customer.setCustIndustry("明星");
                customer.setCustSource("bibi");
                //保存
                em.persist(customer); //保存操作
                //5.提交事务
                tx.commit();
            }catch (Exception e){
                tx.rollback();//回滚事务
                e.printStackTrace();
            }finally {
                //6.释放资源
                em.close();
                //关闭工厂
                factory.close();
            }
         
        }
    }

    运行的sql语句如下所示

    log4j:WARN No appenders could be found for logger (org.jboss.logging).
    log4j:WARN Please initialize the log4j system properly.
    Hibernate: insert into cst_customer (cust_address, cust_industry, cust_level, cust_name, cust_phone, cust_source) values (?, ?, ?, ?, ?, ?)

    GenerationType.TABLE : jpa提供的一种机制,通过一张数据库表的形式帮助我们完成主键自增,jpa会另外生成一张表帮助我们进行主键的管理

     GenerationType.AUTO : 由程序自动的帮助我们选择主键生成策略

     

     多个线程在内存中共享一份Factory对象,减少Factory对象创建消耗资源

     采用静态代码块的方法,减少Factory资源创建消耗性能的问题

    1. 抽取JPAUtil工具类

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

    我们在编写一个测试类进行测试

    解决创建 EntityManagerFactory  浪费资源问题 

    3. 测试查询
    查询有两个方法,注意区别

    package com.itcast.cn;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Persistence;
    
    import org.junit.Test;
    
    import com.itcast.domain.Customer;
    import com.itcast.utils.JpaUtils;
    
    public class TestJpa {
    
        
        /**
         * 测试jpa的保存
         *      案例:保存一个客户到数据库中
         *  Jpa的操作步骤
         *     1.加载配置文件创建工厂(实体管理器工厂)对象
         *     2.通过实体管理器工厂获取实体管理器
         *     3.获取事务对象,开启事务
         *     4.完成增删改查操作
         *     5.提交事务(回滚事务)
         *     6.释放资源
         */
        @Test
        public void testSave() {
            //1.加载配置文件创建工厂(实体管理器工厂)对象
            EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJap");
            //2.通过实体管理器工厂获取实体管理器
            EntityManager em = factory.createEntityManager();
         
            //3.获取事务对象,开启事务
            EntityTransaction tx = em.getTransaction(); //获取事务对象
            tx.begin();//开启事务
            try{
                //4.完成增删改查操作:保存一个客户到数据库中
                Customer customer = new Customer();
                customer.setCustName("蔡徐坤");
                customer.setCustIndustry("明星");
                customer.setCustSource("bibi");
                //保存
                em.persist(customer); //保存操作
                //5.提交事务
                tx.commit();
            }catch (Exception e){
                tx.rollback();//回滚事务
                e.printStackTrace();
            }finally {
                //6.释放资源
                em.close();
                //关闭工厂
                factory.close();
            }
         
        }
        
        @Test
        public void testtestSave02(){
            //1.获取工厂(实体管理器工厂)对象
            EntityManager em = JpaUtils.getEntityManager();
            //3.获取事务对象,开启事务
            EntityTransaction tx = em.getTransaction(); //获取事务对象
            tx.begin();//开启事务
            //4.完成增删改查操作:保存一个客户到数据库中
            Customer customer = new Customer();
            customer.setCustName("蔡徐坤");
            customer.setCustIndustry("明星");
            customer.setCustSource("bibi");
            //保存
            em.persist(customer); //保存操作
            //5.提交事务
            tx.commit();
            //6.释放资源
            em.close();
        }
        
        /**
         * 根据id查询客户
         *  使用find方法查询:
         *      1.查询的对象就是当前客户对象本身
         *      2.在调用find方法的时候,就会发送sql语句查询数据库
         *
         *  立即加载
         */
        @Test
        public  void testFind() {
            //1.通过工具类获取entityManager
            EntityManager entityManager = JpaUtils.getEntityManager();
            //3.增删改查 -- 根据id查询客户
            /**
             * find : 根据id查询数据
             *      class:查询数据的结果需要包装的实体类类型的字节码
             *      id:查询的主键的取值
             * 没有返回 null
             */
            Customer customer = entityManager.find(Customer.class, 1L);//打断点
            //不管打不打印(使用),执行到上一条语句时,都会发送SQL语句
            //System.out.print(customer);
            //class com.bug.domain.Customer
            System.out.println(customer.toString());
            //5.释放资源
            entityManager.close();
    
        }
        
        /**
         * 根据id查询客户
         *      getReference方法
         *          1.获取的对象是一个动态代理对象
         *          2.调用getReference方法不会立即发送sql语句查询数据库
         *              * 当调用查询结果对象的时候,才会发送查询的sql语句:什么时候用,什么时候发送sql语句查询数据库
         *
         * 延迟加载(懒加载)
         *      * 得到的是一个动态代理对象
         *      * 什么时候用,什么使用才会查询
         */
        @Test
        public  void testReference() {
            //1.通过工具类获取entityManager
            EntityManager entityManager = JpaUtils.getEntityManager();
            //3.增删改查 -- 根据id查询客户
            /**
             * getReference : 根据id查询数据
             *      class:查询数据的结果需要包装的实体类类型的字节码
             *      id:查询的主键的取值
             */
            Customer customer = entityManager.getReference(Customer.class, 1L);//打断点
            //这里不打印(不使用)就不会发送SQL语句
            //System.out.print(customer);
            //class com.bug.domain.Customer_$$_jvst88e_0 代理对象
            System.out.println("
    
    ");
            System.out.println(customer.toString());
            //5.释放资源
            entityManager.close();
        }
    
    
    }

    //3.增删改查 -- 根据id查询客户
    /**
    * getReference : 根据id查询数据
    * class:查询数据的结果需要包装的实体类类型的字节码
    * id:查询的主键的取值
    */

    getReference 是懒加载,在find查询语句的时候不会发起sql语句查询,在实际使用使用System.out.print(customer)的时候才发起sql语句进行查询,返回的查询结果是一个代理对象

    4. 测试删除

    @Test
        public  void testRemove() {
            //1.通过工具类获取entityManager
            EntityManager entityManager = JpaUtils.getEntityManager();
            //3.增删改查 -- 删除客户
            //3.获取事务对象,开启事务
            EntityTransaction tx = entityManager.getTransaction(); //获取事务对象
            tx.begin();//开启事务
            //i 根据id查询客户
            Customer customer = entityManager.find(Customer.class, 1L);
            System.out.println(customer);
            if(customer != null){
                //ii 调用remove方法完成删除操作
                entityManager.remove(customer);
            }
            //5.提交事务
            tx.commit();
            //5.释放资源
            entityManager.close();
        }

    7.JPA中的复杂查询
    JPQL全称Java Persistence Query Language,Java持久化查询语言(JPQL),它是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以被编译成所有主流数据库服务器上的SQL。

    其特征与原生SQL语句类似,并且完全面向对象,通过类名和属性访问,而不是表名和表的属性。

     jpql语句不能写select *,但是能够写select 加上对象的属性值

    查询数据库 表中存在多少条记录

    //统计查询
        @Test
        public void findCount() {
            EntityManager em = null;
            EntityTransaction tx = null;
            try {
                //获取实体管理对象
                em = JPAUtil.getEntityManager();
                //获取事务对象
                tx = em.getTransaction();
                tx.begin();
                // 查询全部客户
                // 1.创建query对象
                String jpql = "select count(custId) from Customer";
                Query query = em.createQuery(jpql);
                // 2.查询并得到返回结果
                Object count = query.getSingleResult(); // 得到集合返回类型
                System.out.println(count);
                tx.commit();
            } catch (Exception e) {
                // 回滚事务
                tx.rollback();
                e.printStackTrace();
            } finally {
                // 释放资源
                em.close();
            }
        }
     
    ————————————————
    版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zlx_508/article/details/97005499

    记录总数只有一条记录,使用getSingleResult,返回一条记录

    分页查询

     0表示查询第一页,2表示第一页显示2条记录

    //分页查询客户
        @Test
        public void findPaged () {
            EntityManager em = null;
            EntityTransaction tx = null;
            try {
                //获取实体管理对象
                em = JPAUtil.getEntityManager();
                //获取事务对象
                tx = em.getTransaction();
                tx.begin();
     
                //创建query对象
                String jpql = "from Customer";
                Query query = em.createQuery(jpql);
                //起始索引
                query.setFirstResult(0);
                //每页显示条数
                query.setMaxResults(2);
                //查询并得到返回结果
                List list = query.getResultList(); //得到集合返回类型
                for (Object object : list) {
                    System.out.println(object);
                }
                tx.commit();
            } catch (Exception e) {
                // 回滚事务
                tx.rollback();
                e.printStackTrace();
            } finally {
                // 释放资源
                em.close();
            }
        }
    ————————————————
    版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zlx_508/article/details/97005499

    接下来我们讲解条件查询

    //条件查询
        @Test
        public void findCondition () {
            EntityManager em = null;
            EntityTransaction tx = null;
            try {
                //获取实体管理对象
                em = JPAUtil.getEntityManager();
                //获取事务对象
                tx = em.getTransaction();
                tx.begin();
                //创建query对象
                String jpql = "from Customer where custName like ? ";
                Query query = em.createQuery(jpql);
                //对占位符赋值,从1开始
                query.setParameter(1, "传智播客%");
                //查询并得到返回结果
                Object object = query.getSingleResult(); //得到唯一的结果集对象
                System.out.println(object);
                tx.commit();
            } catch (Exception e) {
                // 回滚事务
                tx.rollback();
                e.printStackTrace();
            } finally {
                // 释放资源
                em.close();
            }
        }
    ————————————————
    版权声明:本文为CSDN博主「I Java」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/zlx_508/article/details/97005499

     接下来重点讲解spring -data-jpa

    这里配置文件有点问题,不清楚的看佟刚spring data的视频教程

     

     pom.xml的依赖如下

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.cib.com</groupId>
      <artifactId>heimaspringdatajpa</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      
      <properties>
            <!--版本锁定-->
            <spring.version>5.0.2.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.12</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>
    
            <!-- spring对orm框架的支持包-->
            <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-c3p0</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 -->
    
         
         
    
            <!-- 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>
    
            <!-- spring data jpa 的坐标-->
            <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>${spring.version}</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>
    </project>

    db.properties的配置如下

    jdbc.user=root
    jdbc.password=123456
    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.jdbcUrl=jdbc:mysql:///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: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.atguigu.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.atguigu.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.atguigu.springdata"
            entity-manager-factory-ref="entityManagerFactory"></jpa:repositories>
    
    </beans>

    这里有几个配置很关键

    <jpa:repositories base-package="com.atguigu.springdata" 指定扫描@Reporisty注解的包

    <property name="packagesToScan" value="com.atguigu.springdata"></property>指定@Entiry注解的包

    <context:component-scan base-package="com.atguigu.springdata"></context:component-scan>指定spring @service @compent所在的包路径

    接下来我们创建包com.atguigu.springdata,所有在的操作都在这个包下面

    接下来我们创建实体类

    package com.atguigu.springdata;
    import javax.persistence.Column;
    
    import javax.persistence.Entity;
    
    import javax.persistence.GeneratedValue;
    
    import javax.persistence.GenerationType;
    
    import javax.persistence.Id;
    
    import javax.persistence.Table;
    
    @Entity // 声明此类是个实体类 需要导入javax.persistence.Entity;
    
    @Table(name = "cst_customer") //需要将该类对应到数据库中的哪一个表中,name中填表的名称
    
    public class Customer {
    
    
    
    @Id //声明主键 
    
    @GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增
    
    //mysql使用自增模式,orcle 使用序列模式
    
    @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 cusIndustry;
    
     
    
    @Column(name = "cust_phone")
    
    private String custPhone;
    
     
    
    @Column(name = "cust_address")
    
    private String custAddress;
    
    
    
    public Long getCustId() {
    
    return custId;
    
    }
    
    
    
    public void setCustId(Long custId) {
    
    this.custId = custId;
    
    }
    
    
    
    public String getCustName() {
    
    return custName;
    
    }
    
    
    
    public void setCustName(String custName) {
    
    this.custName = custName;
    
    }
    
    
    
    public String getCustSource() {
    
    return custSource;
    
    }
    
    
    
    public void setCustSource(String custSource) {
    
    this.custSource = custSource;
    
    }
    
    
    
    public String getCustLevel() {
    
    return custLevel;
    
    }
    
    
    
    public void setCustLevel(String custLevel) {
    
    this.custLevel = custLevel;
    
    }
    
    
    
    public String getCusIndustry() {
    
    return cusIndustry;
    
    }
    
    
    
    public void setCusIndustry(String cusIndustry) {
    
    this.cusIndustry = cusIndustry;
    
    }
    
    
    
    public String getCustPhone() {
    
    return custPhone;
    
    }
    
    
    
    public void setCustPhone(String custPhone) {
    
    this.custPhone = custPhone;
    
    }
    
    
    
    public String getCustAddress() {
    
    return custAddress;
    
    }
    
    
    
    public void setCustAddress(String custAddress) {
    
    this.custAddress = custAddress;
    
    }
    
    
    
    @Override
    
    public String toString() {
    
    return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
    
    + ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone
    
    + ", custAddress=" + custAddress + "]";
    
    }
    
     
    
    }

    实体类创建成功之后,接下来我们就可以编写jpa的接口进行增删改查的操作了,只需要编写jpa接口,不需要编写jpa的实现类

    关键点:

    1.编写dao层的接口就可以了,不需要dao接口的实现类

    2、编写的dao接口的规范如下

     SpringDataJPA通过实现接口(代理的形式)进行简单的CRUD

    https://blog.csdn.net/qq_42041712/article/details/94451572

    JpaRepository<Customer,Long> 第一个参数是我们要操作的实体类类型,第二个参数是实体类的主键

    JpaSpecificationExecutor<Customer> 参数是我们要操作的实体类的类型

    package com.atguigu.springdata;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
     
    }

    接下来编写好接口之后,就可以进行增加删除操作数据库了,注意CustomerDao没有使用注解,只要放在<jpa:repositories base-package="com.atguigu.springdata"对于的包下面就可以了

     我们可以编写一个测试类进行操作,首先保证数据库中存在数据

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    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 javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    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 org.springframework.data.jpa.domain.Specification;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.atguigu.springdata.CustomerDao;
    import com.itcast.domain.Customer;
    import com.itcast.utils.JpaUtils;
    
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations="classpath:applicationContext.xml")
    public class SpringDataTest {
    
        @Autowired
        private CustomerDao dao;
        
        @Test
        public  void testFind() {
            
          com.atguigu.springdata.Customer customer = dao.findOne((long) 2);
          System.out.println(customer.toString());
        }
        
    }

    测试的结果如下

    在eclipse中查看一个类及其父类中的所有方法和属性
    只需要连续按两次Ctrl+O

    JpaRepository默认实现了下面的方法

    在eclipse中查看一个类的集成关系
    只需要连续按两次Ctrl+T

     JpaRepository继承自PagingAndSortingRepository,PagingAndSortingRepository继承自CrudRepository,CrudRepository集成自Repository

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    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 javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    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 org.springframework.data.jpa.domain.Specification;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.atguigu.springdata.Customer;
    import com.atguigu.springdata.CustomerDao;
    import com.itcast.utils.JpaUtils;
    
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations="classpath:applicationContext.xml")
    public class SpringDataTest {
    
        @Autowired
        private CustomerDao customerDao;
        
        @Test
        public  void testFind() {
            
          com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
          System.out.println(customer.toString());
        }
        
        /**
    
         * 保存客户:调用save(obj)方法
    
         */
    
        @Test
    
        public void testSave() {
    
            Customer c = new Customer();
    
            c.setCustName("传智播客");
    
            customerDao.save(c);
    
        }
    
       
    
        /**
    
         * 修改客户:调用save(obj)方法
    
         *      对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新   
    
         *                      如果执行此方法中对象中不存在id属性,即为保存操作
    
         *         
    
         */
    
        @Test
    
        public void testUpdate() {
    
            //根据id查询id为1的客户
    
            Customer customer = customerDao.findOne(1l);
    
            //修改客户名称
    
            customer.setCustName("传智播客顺义校区");
    
            //更新
    
            customerDao.save(customer);
    
        }
        
    }

    /**

    * 根据id删除:调用delete(id)方法

    */

    @Test

    public void testDelete() {

    customerDao.delete(1l);

    }

     

     

     

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    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 javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    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 org.springframework.data.jpa.domain.Specification;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.atguigu.springdata.Customer;
    import com.atguigu.springdata.CustomerDao;
    import com.itcast.utils.JpaUtils;
    
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations="classpath:applicationContext.xml")
    public class SpringDataTest {
    
        @Autowired
        private CustomerDao customerDao;
        
        @Test
        public  void testFind() {
            
          com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
          System.out.println(customer.toString());
        }
        
        /**
    
         * 保存客户:调用save(obj)方法
    
         */
    
        @Test
    
        public void testSave() {
    
            Customer c = new Customer();
    
            c.setCustName("传智播客");
    
            customerDao.save(c);
    
        }
    
       
    
        /**
    
         * 修改客户:调用save(obj)方法
    
         *      对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新   
    
         *                      如果执行此方法中对象中不存在id属性,即为保存操作
    
         *         
    
         */
    
        @Test
    
        public void testUpdate() {
    
            //根据id查询id为1的客户
    
            Customer customer = customerDao.findOne(1l);
    
            //修改客户名称
    
            customer.setCustName("传智播客顺义校区");
    
            //更新
    
            customerDao.save(customer);
    
        }
        
        @Test
    
        public void testCount() {
              long count = customerDao.count();
              System.out.println(count);
        }
        
        @Test
    
        public void testExits() {
              boolean exists = customerDao.exists((long) 2);
              
              System.out.println(exists);
        }
        
        
        
    }

     
        @Test
    
        @Transactional
        public void testGetOne() {
              Customer one = customerDao.getOne((long) 2);
              
              System.out.println(one);
        }
        

    getOne是懒加载,findOne是直接加载,懒加载的实现需要依赖事务,所有使用getOne方法的时候,一定要引入事务管理的依赖,这里使用 @Transactiona,否则代码会报错

    3.2 使用JPQL的方式查询
    使用Spring Data JPA提供的查询方法已经可以解决大部分的应用场景,但是对于某些业务来说,我们还需要灵活的构造查询条件,这时就可以使用@Query注解,结合JPQL的语句方式完成查询

    package com.atguigu.springdata;
    
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
    import org.springframework.data.jpa.repository.Query;
    import org.springframework.stereotype.Repository;
    
    import antlr.collections.List;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
     
    }

       //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引

     2表示的是输入参数为name,1表示输入的参数是id

     

     此外,也可以通过使用 @Query 来执行一个更新操作,为此,我们需要在使用 @Query 的同时,用 @Modifying 来将该操作标识为修改查询,这样框架最终会生成一个更新的操作,而非查询

    package com.atguigu.springdata;
    
    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 org.springframework.stereotype.Repository;
    
    import antlr.collections.List;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
    
        @Modifying
    
        public void updateCustomer(String custName,Long custId);
     
    }

    执行更新或者删除操作,必须需要添加 @Modifying,此外必须要具有事务操作

    @Test
        @Transactional
        @Rollback(value=false)
        public void testupdateCustomer() {
            customerDao.updateCustomer("我是可不2222", (long) 2);
        }
        

    执行更新删除操作需要有事务所有上面有@Transactional,此外jpa执行事务操作完成之后默认会回滚,当数据更新操作成功之后,因为jpa默认要回滚,会把更新的数据还原回去,我们要在数据库中看到更新的

    数据,我们要禁止jpa的回滚@Rollback(value=false)

    3.3 使用SQL语句查询
    Spring Data JPA同样也支持sql语句的查询,如下:

     

    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying
        public void updateCustomer(String custName,Long custId);
     
        
        /**
    
         * nativeQuery : 使用本地sql的方式查询
    
         */
    
        @Query(value="select * from cst_customer",nativeQuery=true)
    
        public List<Object[]> findSql();
        
    }

    这里千万要注意返回的是一个List<Object[]>,每一个元素是一个Object类型的数组,不能写成List<Customer[]>

    @Test
        public void testfindSql() {
              List<Object[]> datas = customerDao.findSql();
              
              for(Object[] data:datas){
                  
                  System.out.println(Arrays.toString(data));
              }
              
        }
    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying
        public void updateCustomer(String custName,Long custId);
     
        
        /**
    
         * nativeQuery : 使用本地sql的方式查询
    
         */
    
        @Query(value="select * from cst_customer",nativeQuery=true)
    
        public List<Object[]> findSql();
        
        
        @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
        public List<Object []> findSql2(String name);
        
    }

    测试代码

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    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 javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    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 org.springframework.data.jpa.domain.Specification;
    import org.springframework.data.jpa.repository.Query;
    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 com.atguigu.springdata.Customer;
    import com.atguigu.springdata.CustomerDao;
    import com.itcast.utils.JpaUtils;
    
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations="classpath:applicationContext.xml")
    public class SpringDataTest {
    
        @Autowired
        private CustomerDao customerDao;
        
        @Test
        public  void testFind() {
            
          com.atguigu.springdata.Customer customer = customerDao.findOne((long) 2);
          System.out.println(customer.toString());
        }
        
        /**
    
         * 保存客户:调用save(obj)方法
    
         */
    
        @Test
    
        public void testSave() {
    
            Customer c = new Customer();
    
            c.setCustName("传智播客");
    
            customerDao.save(c);
    
        }
    
       
    
        /**
    
         * 修改客户:调用save(obj)方法
    
         *      对于save方法的解释:如果执行此方法是对象中存在id属性,即为更新操作会先根据id查询,再更新   
    
         *                      如果执行此方法中对象中不存在id属性,即为保存操作
    
         *         
    
         */
    
        @Test
    
        public void testUpdate() {
    
            //根据id查询id为1的客户
    
            Customer customer = customerDao.findOne(1l);
    
            //修改客户名称
    
            customer.setCustName("传智播客顺义校区");
    
            //更新
    
            customerDao.save(customer);
    
        }
        
        @Test
    
        public void testCount() {
              long count = customerDao.count();
              System.out.println(count);
        }
        
        @Test
    
        public void testExits() {
              boolean exists = customerDao.exists((long) 2);
              
              System.out.println(exists);
        }
        
        
        @Test
    
        @Transactional
        public void testGetOne() {
              Customer one = customerDao.getOne((long) 2);
              
              System.out.println(one);
        }
        
        @Test
        @Transactional
        @Rollback(value=false)
        public void testupdateCustomer() {
            customerDao.updateCustomer("我是可不2222", (long) 2);
        }
        
        @Test
        public void testfindSql() {
              List<Object[]> datas = customerDao.findSql();
              
              for(Object[] data:datas){
                  
                  System.out.println(Arrays.toString(data));
              }
              
        }
        
      //测试sql查询
        @Test
        public void testFindSql()
        {
    
            List<Object[]> list = customerDao.findSql2("迅腾软件%");//模糊查询
            for(Object[] obj: list){
    
                System.out.println(Arrays.toString(obj));
            }
        }
    
        
    }

    3.4   方法命名规则查询

    顾名思义,方法命名规则查询就是根据方法的名字,就能创建查询。只需要按照Spring Data JPA提供的方法命名规则定义方法的名称,就可以完成查询工作。Spring Data JPA在程序执行的时候会根据方法名称进行解析,并自动生成查询语句进行查询

    按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写。框架在进行方法名解析时,会先把方法名多余的前缀截取掉,然后对剩下部分进行解析。

    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying
        public void updateCustomer(String custName,Long custId);
     
        
        /**
    
         * nativeQuery : 使用本地sql的方式查询
    
         */
    
        @Query(value="select * from cst_customer",nativeQuery=true)
    
        public List<Object[]> findSql();
        
        
        @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
        public List<Object []> findSql2(String name);
        
        
        //方法命名方式查询(根据客户名称查询客户)
    
        public Customer findByCustName(String custName);
        
    }

    测试代码如下

     @Test
        public void testFindSql22()
        {
    
           Customer customer = customerDao.findByCustName("3333");
           System.out.println(customer.toString());
        }

     

     

     

     我们使用下Like查看下模糊查询

    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying
        public void updateCustomer(String custName,Long custId);
     
        
        /**
    
         * nativeQuery : 使用本地sql的方式查询
    
         */
    
        @Query(value="select * from cst_customer",nativeQuery=true)
    
        public List<Object[]> findSql();
        
        
        @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
        public List<Object []> findSql2(String name);
        
        
        //方法命名方式查询(根据客户名称查询客户)
    
        public Customer findByCustName(String custName);
        
        public List<Customer> findByCustNameLike(String custName);
        
    }

    测试代码如下

      
        @Test
        public void testFindSql22()
        {
    
           List<Customer> customers = customerDao.findByCustNameLike("3333%");
           for(Customer customer:customers){
               System.out.println(customer.toString());
           }
           
        }

     

     这里没有占位符,两个参数顺利不能弄错了

    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface CustomerDao  extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> 
    {
        
    
    
       
    
        //@Query 使用jpql的方式查询。?1代表参数的占位符,其中1对应方法中的参数索引
    
        @Query(value="from Customer where custName = ?1")
    
        public Customer findCustomer(String custName);
        
        
        @Query(value="update Customer set custName = ?1 where custId = ?2")
        @Modifying
        public void updateCustomer(String custName,Long custId);
     
        
        /**
    
         * nativeQuery : 使用本地sql的方式查询
    
         */
    
        @Query(value="select * from cst_customer",nativeQuery=true)
    
        public List<Object[]> findSql();
        
        
        @Query(value = "select *    from  cst_customer where cust_name like ?1",nativeQuery = true)
        public List<Object []> findSql2(String name);
        
        
        //方法命名方式查询(根据客户名称查询客户)
    
        public Customer findByCustName(String custName);
        
        public List<Customer> findByCustNameLike(String custName);
        
        public List<Customer> findByCustNameLikeAndCusIndustry(String custName,String cusIndustry);
        
    }

    测试代码如下

     @Test
        public void testFindSql22()
        {
    
           List<Customer> customers = customerDao.findByCustNameLikeAndCusIndustry("3333%","明星");
           for(Customer customer:customers){
               System.out.println(customer.toString());
           }
           
        }
    Hibernate: 
        select
            customer0_.cust_id as cust_id1_0_,
            customer0_.cust_industry as cust_ind2_0_,
            customer0_.cust_address as cust_add3_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
            cst_customer customer0_ 
        where
            (
                customer0_.cust_name like ?
            ) 
            and customer0_.cust_industry=?

     我们重点来看下JpaSpecificationExecutor方法

     这个接口有上面的几个方法,T findOne(Specification<T> spec);之前的JpaRepository接口也有findOne方法只能依据主键查询,但是没有携带Specification参数,这里携带了Specification参数

    我们可以按照主键查询,也可以安装名称查询,我们可以自定义查询条件

     

    /**
     * Specification in the sense of Domain Driven Design.
     * 
     * @author Oliver Gierke
     * @author Thomas Darimont
     */
    public interface Specification<T> {
    
        /**
         * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
         * {@link Root} and {@link CriteriaQuery}.
         * 
         * @param root
         * @param query
         * @return a {@link Predicate}, must not be {@literal null}.
         */
        Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
    }

    我们来测试下上面的几个接口

     

     对象CriteriaBuilder有下面这样多的比较的方式

     

     @Test
        public void testFindSql223333()
        {
    
         Specification<Customer> spec = new Specification<Customer>() {
    
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // TODO Auto-generated method stub
                Path<Object> custName = root.get("custName");
                Predicate predicate = cb.equal(custName, "3333");
                return predicate;
            }
        };
           
         Customer customer = customerDao.findOne(spec);
         System.out.println(customer.toString());
        }

    多个查询条件的拼接

    @Test
        public void testFindSql223333222()
        {
    
         Specification<Customer> spec = new Specification<Customer>() {
    
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // TODO Auto-generated method stub
                Path<Object> custName = root.get("custName");
                Path<Object> cusIndustry = root.get("cusIndustry");
                Predicate predicate1 = cb.equal(custName, "3333");
                Predicate predicate2 = cb.equal(cusIndustry, "2222");
                Predicate predicate3 = cb.and(predicate1,predicate2);
                return predicate3;
            }
        };
           
         Customer customer = customerDao.findOne(spec);
         System.out.println(customer.toString());
        }

    @Test
        public void testFindSql223333222wwww()
        {
    
         Specification<Customer> spec = new Specification<Customer>() {
    
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // TODO Auto-generated method stub
                Path<Object> custName = root.get("custName");
                Predicate predicate = cb.like(custName.as(String.class), "33%");
                return predicate;
            }
        };
           
         List<Customer> customer = customerDao.findAll(spec);
         System.out.println(customer.toString());
        }

    对于 List<Customer> customer = customerDao.findAll(spec)返回的数据是一个集合,我们可以指定返回的集合中的数据按照某种方式进行排序

     @Test
        public void testFindSql223333222wwwwww()
        {
    
         Specification<Customer> spec = new Specification<Customer>() {
    
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // TODO Auto-generated method stub
                Path<Object> custName = root.get("custName");
                Predicate predicate = cb.like(custName.as(String.class), "33%");
                return predicate;
            }
        };
           
        Sort sort = new Sort(Sort.Direction.ASC,"custId");
         List<Customer> customer = customerDao.findAll(spec,sort);
         System.out.println(customer.toString());
        }

    按照"custId"的Sort.Direction.ASC进行排序

     

        /**
         * 目标: 实现带查询条件的分页. id > 5 的条件
         * 
         * 调用 JpaSpecificationExecutor 的 Page<T> findAll(Specification<T> spec, Pageable pageable);
         * Specification: 封装了 JPA Criteria 查询的查询条件
         * Pageable: 封装了请求分页的信息: 例如 pageNo, pageSize, Sort
         */
        @Test
        public void testJpaSpecificationExecutorss(){
            int pageNo = 3 - 1;
            int pageSize = 5;
            Sort sort = new Sort(Sort.Direction.ASC,"custId");
            //封装分页的信息
            PageRequest pageable = new PageRequest(pageNo, pageSize,sort);
            
             Specification<Customer> spec = new Specification<Customer>() {
    
                    public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                        // TODO Auto-generated method stub
                        Path<Object> custName = root.get("custName");
                        Predicate predicate = cb.like(custName.as(String.class), "33%");
                        return predicate;
                    }
                };
                   
                
            
            Page<Customer> page = customerDao.findAll(spec, pageable);
            
            System.out.println("总记录数: " + page.getTotalElements());
            System.out.println("当前第几页: " + (page.getNumber() + 1));
            System.out.println("总页数: " + page.getTotalPages());
            System.out.println("当前页面的 List: " + page.getContent());
            List<Customer> content = page.getContent();
            System.out.println("当前页面的记录数: " + page.getNumberOfElements());
            /*List<Person> collect = page.getContent().stream().map(stat->(Person)stat).collect(Collectors.toList());
            System.out.println("当前页面的 List1: " + collect);*/
        }

    打印结果如下

    Hibernate: 
        select
            count(customer0_.cust_id) as col_0_0_ 
        from
            cst_customer customer0_ 
        where
            customer0_.cust_name like ?
    总记录数: 1
    当前第几页: 3
    总页数: 1
    当前页面的 List: []
    当前页面的记录数: 0

     

     

     

     客户个联系人是一对多的关系

     

     

    3.2 实战Hibernate一对多关联映射
    3.2.1 创建数据表(客户----联系人)
    客户表:
    
    CREATE TABLE `cst_customer` (
    
      `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
    
      `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
    
      `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
    
      `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
    
      `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
    
      `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
    
      `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
    
      PRIMARY KEY (`cust_id`)
    
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
     
    
    联系人表:
    
    CREATE TABLE `cst_linkman` (
    
      `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
    
      `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
    
      `lkm_cust_id` bigint(32) DEFAULT NULL COMMENT '客户id',
    
      `lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别',
    
      `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
    
      `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
    
      `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
    
      `lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq',
    
      `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
    
      `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
    
      PRIMARY KEY (`lkm_id`),
    
      KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`),
    
      CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
    
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

    接下来我们要新增一个联系人的实体类对象

    在customer客户端实体类中,需要配置下面的信息

    package com.atguigu.springdata;
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.Column;
    
    import javax.persistence.Entity;
    
    import javax.persistence.GeneratedValue;
    
    import javax.persistence.GenerationType;
    
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    @Entity // 声明此类是个实体类 需要导入javax.persistence.Entity;
    
    @Table(name = "cst_customer") //需要将该类对应到数据库中的哪一个表中,name中填表的名称
    
    public class Customer {
    
    
    
    @Id //声明主键 
    
    @GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增
    
    //mysql使用自增模式,orcle 使用序列模式
    
    @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 cusIndustry;
    
     
    
    @Column(name = "cust_phone")
    
    private String custPhone;
    
     
    
    @Column(name = "cust_address")
    
    private String custAddress;
    
    
    @OneToMany(targetEntity=LinkMan.class)
    @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")
    private Set<LinkMan> linkMans = new HashSet<LinkMan>();
    
    public Long getCustId() {
    
    return custId;
    
    }
    
    
    
    public void setCustId(Long custId) {
    
    this.custId = custId;
    
    }
    
    
    
    public String getCustName() {
    
    return custName;
    
    }
    
    
    
    public void setCustName(String custName) {
    
    this.custName = custName;
    
    }
    
    
    
    public String getCustSource() {
    
    return custSource;
    
    }
    
    
    
    public void setCustSource(String custSource) {
    
    this.custSource = custSource;
    
    }
    
    
    
    public String getCustLevel() {
    
    return custLevel;
    
    }
    
    
    
    public void setCustLevel(String custLevel) {
    
    this.custLevel = custLevel;
    
    }
    
    
    
    public String getCusIndustry() {
    
    return cusIndustry;
    
    }
    
    
    
    public void setCusIndustry(String cusIndustry) {
    
    this.cusIndustry = cusIndustry;
    
    }
    
    
    
    public String getCustPhone() {
    
    return custPhone;
    
    }
    
    
    
    public void setCustPhone(String custPhone) {
    
    this.custPhone = custPhone;
    
    }
    
    
    
    public String getCustAddress() {
    
    return custAddress;
    
    }
    
    
    
    public void setCustAddress(String custAddress) {
    
    this.custAddress = custAddress;
    
    }
    
    
    
    @Override
    
    public String toString() {
    
    return "Customer [custId=" + custId + ", custName=" + custName + ", custSource=" + custSource
    
    + ", custLevel=" + custLevel + ", cusIndustry=" + cusIndustry + ", custPhone=" + custPhone
    
    + ", custAddress=" + custAddress + "]";
    
    }
    
    
    
    public Set<LinkMan> getLinkMans() {
        return linkMans;
    }
    
    
    
    public void setLinkMans(Set<LinkMan> linkMans) {
        this.linkMans = linkMans;
    }
    
     
    
    }

    在联系人方需要配置如下

    package com.atguigu.springdata;
    
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    @Entity // 声明此类是个实体类 需要导入javax.persistence.Entity;
    
    @Table(name = "cst_linkman") //需要将该类对应到数据库中的哪一个表中,name中填表的名称
    public class LinkMan {
    

    @Id //声明主键
    @GeneratedValue(strategy = GenerationType.IDENTITY) //声明主键的生成策略为自动递增
    @Column(name = "lkm_id") //设置该属性和数据库中的哪一个字段对应


    private Long lkmId; @Column(name = "lkm_gender") //设置该属性和数据库中的哪一个字段对应 private Character lkmGender; @Column(name = "lkm_name") //设置该属性和数据库中的哪一个字段对应 private String lkmName; @Column(name = "lkm_phone") //设置该属性和数据库中的哪一个字段对应 private String lkmPhone; @Column(name = "lkm_email") //设置该属性和数据库中的哪一个字段对应 private String lkmEmail; @Column(name = "lkm_qq") //设置该属性和数据库中的哪一个字段对应 private String lkmQq; @Column(name = "lkm_mobile") //设置该属性和数据库中的哪一个字段对应 private String lkmMobile; @Column(name = "lkm_memo") //设置该属性和数据库中的哪一个字段对应 private String lkmMemo; @Column(name = "lkm_position") //设置该属性和数据库中的哪一个字段对应 private String lkmPosition; @ManyToOne(targetEntity=Customer.class) @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id") private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Long getLkmId() { return lkmId; } public void setLkmId(Long lkmId) { this.lkmId = lkmId; } public Character getLkmGender() { return lkmGender; } public void setLkmGender(Character lkmGender) { this.lkmGender = lkmGender; } public String getLkmName() { return lkmName; } public void setLkmName(String lkmName) { this.lkmName = lkmName; } public String getLkmPhone() { return lkmPhone; } public void setLkmPhone(String lkmPhone) { this.lkmPhone = lkmPhone; } public String getLkmEmail() { return lkmEmail; } public void setLkmEmail(String lkmEmail) { this.lkmEmail = lkmEmail; } public String getLkmQq() { return lkmQq; } public void setLkmQq(String lkmQq) { this.lkmQq = lkmQq; } public String getLkmMobile() { return lkmMobile; } public void setLkmMobile(String lkmMobile) { this.lkmMobile = lkmMobile; } public String getLkmMemo() { return lkmMemo; } public void setLkmMemo(String lkmMemo) { this.lkmMemo = lkmMemo; } public String getLkmPosition() { return lkmPosition; } public void setLkmPosition(String lkmPosition) { this.lkmPosition = lkmPosition; } }

      @JoinColumn(name="lkm_cust_id",referencedColumnName="cust_id")中表示的是表联系人中的lkm_cust_id字段的值,来自于表客户的cust_id

    接下来,我们要编写一个操作联系人的接口类

    package com.atguigu.springdata;
    
    import java.util.List;
    
    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 org.springframework.stereotype.Repository;
    
    /*
    * 符合SpringDatajpa的dao层接口规范
    *JpaRepository<操作的实体类类型,实体类中主键属性的类型>
        *封装了基本的CRUD操作
     JpaSpecificationExecutor<操作的实体类类型>
        *封装了复杂查询操作(分页)
    * */
     
    
    public interface LinnkManDao  extends JpaRepository<LinkMan,Long>, JpaSpecificationExecutor<LinkMan> 
    {
        
    
    
       
    
    }

    整个工程的结构如下所示

     接下来我们来就可以进行测试了

     我们来看下程序的代码

    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.List;
    import java.util.stream.Collector;
    import java.util.stream.Collectors;
    
    import javax.persistence.EntityManager;
    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 javax.sql.DataSource;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    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 org.springframework.data.jpa.domain.Specification;
    import org.springframework.data.jpa.repository.Query;
    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 com.atguigu.springdata.Customer;
    import com.atguigu.springdata.CustomerDao;
    import com.atguigu.springdata.LinkMan;
    import com.atguigu.springdata.LinnkManDao;
    import com.itcast.utils.JpaUtils;
    
    
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations="classpath:applicationContext.xml")
    public class oneToManyTest {
    
        @Autowired
        private CustomerDao customerDao;
        
        
        @Autowired
        private LinnkManDao linnkManDao;
        
       
        @Test
        @Transactional
        @Rollback(value=false)
        public void save(){
            
            Customer customer = new Customer();
            customer.setCustName("百度");
            
            LinkMan linkMan = new LinkMan();
            linkMan.setLkmName("小明");
            linkMan.setCustomer(customer);
            
            customerDao.save(customer);
            
            linnkManDao.save(linkMan);
            
        }
    
    }

    这里操作了两张表要保证事务的一致性 @Transactional,其次事务操作成功之后要让更新的记录保存到数据库,不进行回滚  @Rollback(value=false)

  • 相关阅读:
    学习工作记录七
    NoSuchBeanDefinitionException:No qualifying bean of type
    学习工作记录六
    密码学考试要点
    Failed to execute goal org.springframework.boot
    学习工作记录五
    学习工作记录四
    关于打包ipa文件以及苹果证书的若干问题
    学习工作记录三
    PAT乙级(Basic Level)练习题-NowCoder数列总结
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/11737015.html
Copyright © 2020-2023  润新知