springDataJPA笔记

springDataJPA笔记


第一 orm思想

主要目的:操作实体类就相当于操作数据库表
建立两个映射关系:
    实体类和表的映射关系
    实体类中属性和表中字段的映射关系
不再重点关注:sql语句

实现了ORM思想的框架:mybatis,hibernate

第二 hibernate框架介绍

Hibernate是一个开放源代码的对象关系映射框架,
    它对JDBC进行了非常轻量级的对象封装,
    它将POJO与数据库表建立映射关系,是一个全自动的orm框架

第三 JPA规范

jpa规范,实现jpa规范,内部是由接口和抽象类组成

第四 jpa的基本操作

案例:是客户的相关操作(增删改查)
    客户:就是一家公司
客户表:

jpa操作的操作步骤
    1.加载配置文件创建实体管理器工厂
        Persisitence:静态方法(根据持久化单元名称创建实体管理器工厂)
            createEntityMnagerFactory(持久化单元名称)
        作用:创建实体管理器工厂
        
    2.根据实体管理器工厂,创建实体管理器
        EntityManagerFactory :获取EntityManager对象
        方法:createEntityManager
        * 内部维护的很多的内容
            内部维护了数据库信息,
            维护了缓存信息
            维护了所有的实体管理器对象
            再创建EntityManagerFactory的过程中会根据配置创建数据库表
        * EntityManagerFactory的创建过程比较浪费资源
        特点:线程安全的对象
            多个线程访问同一个EntityManagerFactory不会有线程安全问题
        * 如何解决EntityManagerFactory的创建过程浪费资源(耗时)的问题?
        思路:创建一个公共的EntityManagerFactory的对象
        * 静态代码块的形式创建EntityManagerFactory
        
    3.创建事务对象,开启事务
        EntityManager对象:实体类管理器
            beginTransaction : 创建事务对象
            presist : 保存
            merge  : 更新
            remove : 删除
            find/getRefrence : 根据id查询
            
        Transaction 对象 : 事务
            begin:开启事务
            commit:提交事务
            rollback:回滚
    4.增删改查操作
    5.提交事务
    6.释放资源

i.搭建环境的过程
    1.创建maven工程导入坐标
    2.需要配置jpa的核心配置文件
        *位置:配置到类路径下的一个叫做 META-INF 的文件夹下
        *命名:persistence.xml
    3.编写客户的实体类
    4.配置实体类和表,类中属性和表中字段的映射关系
    5.保存客户到数据库中
ii.完成基本CRUD案例
    persist : 保存
    merge : 更新
    remove : 删除
    find/getRefrence : 根据id查询
    
iii.jpql查询
    sql:查询的是表和表中的字段
    jpql:查询的是实体类和类中的属性
    * jpql和sql语句的语法相似
    
    1.查询全部
    2.分页查询
    3.统计查询
    4.条件查询
    5.排序
    
    

以上是课件的内容:

总结:
使用jpa的步骤,但是不适用springboot注解的形式,那么

第一步就需要创建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 name="javax.persistence.jdbc.password" value="root"/>
        <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql:///springdatajpa"/>
        <!--可选的配置:为了配置jpa实现方的配置信息
            hibernate:
                显示sqlhibernate.show_sql
                自动创建数据库表hibernate.hbm2ddl.auto
                        create:程序运行时创建数据库表(如果有表,先删除表再创建)
                        update:c程序运行时创建表(如果有表不会创建表)
                        none:不会创建表
        -->
        <property name="hibernate.show_sql" value="true"/>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
    </properties>
</persistence-unit>
</persistence>

以上的代码进行了详细的注解,就不需要解释了。
第二步:需要创建实体类,根据实体类进行创建数据库表结构:

    package cn.itcast.domain;
    
    /**
     * @Created by Intellij IDEA.
     * @author: 陈亚萌
     * @Date: 2020/1/18
     */
    
    import javax.persistence.*;
    
    /**
     * 客户实体类:
     *  配置映射关系:
     *      1. 实体类和表的映射关系
     *      2. 实体类中属性和表中字段的映射关系
     *      @Entity声明实体列
     *      @Table:声明实体类和表的映射关系  name 属性是配置数据库的名称
     *      @Id:声明主键
     *      strategy
     *           @GeneratedValue(strategy = GenerationType.IDENTITY)  表示主键生成策略是自增 mysql
     *              * 底层数据库必须支持自动增长,底层数据库支持的自动增长方式,对id递增
     *           GenerationType.SEQUENCE: 序列  Oracle
     *                  底层数据库必须支持序列
     *           GenerationType.TABLE :
     *              jpa提供的一种机制,通过数据库表的形式帮我们完成主键自增
     *           GenerationType.AUTO:
     *              由程序自动帮我们选择主键生成策略
     *      @Column(name = 'cust_id')配置属性和字端的映射关系  name代表数据库表中的字段名
     */
    @Entity
    @Table(name = "cst_customer")
    public class Customer {
        @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_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;
    
        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 getCustIndustry() {
            return custIndustry;
        }
    
        public void setCustIndustry(String custIndustry) {
            this.custIndustry = custIndustry;
        }
    
        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 + '\'' +
                    ", custIndustry='" + custIndustry + '\'' +
                    ", custPhone='" + custPhone + '\'' +
                    ", custAddress='" + custAddress + '\'' +
                    '}';
        }
    }

以上也有对每段代码的详细注解,也可以不用手写setget方法,直接使用lombok进行@Data注解即可。

第三步,进行测试:

    package cn.itcast;

import cn.itcast.domain.Customer;
import cn.itcast.utils.JpaUtils;
import org.junit.Test;

import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

/**
 * @Created by Intellij IDEA.
 * @author: 陈亚萌
 * @Date: 2020/1/18
 */
public class test {
    /*
    * 测试jpa的保存
    *   案例 保存一个客户到数据库
    * jpa操作步骤:
    *   1. 加载配置文件创建工厂(实体管理工厂)对象
    *   2. 通过实体管理类获取实体管理器
    *   3. 获取事务对象,开启事务
    *   4. 完成增删改查操作
    *   5. 提交事务(回滚事务)
    *   6. 释放资源
    * */
    @Test
    public void testSave(){
    /*    //1. 加载配置文件创建工厂(实体管理工厂)对象
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");
        //2. 通过实体管理类获取实体管理器
        EntityManager em = factory.createEntityManager();*/
        EntityManager em= JpaUtils.getEntityManager();
        // 3 . 获取事务对象,开启事务
        EntityTransaction tx = em.getTransaction();
        //开启事务
        tx.begin();
        //4。完成增删改查操作
        Customer customer=new Customer();
        customer.setCustName("chenyameng");
        customer.setCustIndustry("IT");
        //保存
        em.persist(customer);
        // 5. 提交事务(回滚事务)
        tx.commit();
        // 6. 释放资源
        em.close();
        //factory.close();

    }

    /**
     * 根据id查询用户
     */
    @Test
    public void testFind(){
        //1, 通过工具类获取entityManger
        EntityManager em = JpaUtils.getEntityManager();
        //2,开启事务
        EntityTransaction tx=em.getTransaction();
        tx.begin();
        //3, 增删改查
        /**
         * find:根据id查询数据
         *      class:字节码,查询数据的结果需要包装的实体类类型的字节码
         *      id:查询的主键的取值
         *
         *      使用find方法查询
         *          1. 查询的对象就是当前客户对象本身
         *          2. 调用find方法的时候,就会发送sql请求
         */
        Customer customer = em.find(Customer.class, 1l);
        System.out.println(customer.toString());
        //4,提交事务,
        tx.commit();
        // 释放资源
        em.close();
    }

    /**
     * 根据id查询用户
     */
    @Test
    public void testReference(){
        //1, 通过工具类获取entityManger
        EntityManager em = JpaUtils.getEntityManager();
        //2,开启事务
        EntityTransaction tx=em.getTransaction();
        tx.begin();
        //3, 增删改查
        /**
         * getReference:根据id查询数据
         *      class:字节码,查询数据的结果需要包装的实体类类型的字节码
         *      id:查询的主键的取值
         *
         *      特点:
         *          获取的对象是动态代理的对象
         *          调用reference方法不会立即发送sql语句查询数据库
         *              * 当调用查询结果的时候,才会发送sql语句,什么时候用,什么时候发送sql语句
         *              延迟加载,特点:
         *                  得到的是动态代理对象
         *                  什么时候用什么时候查
         *
         */
        Customer customer = em.getReference(Customer.class, 1l);
        System.out.println(customer.toString());
        //4,提交事务,
        tx.commit();
        // 释放资源
        em.close();
    }
    /**
     * s删除客户
     */
    @Test
    public void testRemove(){
        //1, 通过工具类获取entityManger
        EntityManager em = JpaUtils.getEntityManager();
        //2,开启事务
        EntityTransaction tx=em.getTransaction();
        tx.begin();
        //3, 增删改查
        //3.1 根据id查询客户
        final Customer customer = em.find(Customer.class, 1L);
        // 3.2 调用remove  方法删除操作
       em.remove(customer);
        //4,提交事务,
        tx.commit();
        // 释放资源
        em.close();
    }
    /**
     * 更新客户
     */
    @Test
    public void testUpdate(){
        //1, 通过工具类获取entityManger
        EntityManager em = JpaUtils.getEntityManager();
        //2,开启事务
        EntityTransaction tx=em.getTransaction();
        tx.begin();
        //3, 增删改查
        //3.1 客户的更新
        final Customer customer = em.find(Customer.class, 2L);
        customer.setCustIndustry("it教育");
        // 3.2 调用update
        em.merge(customer);
        //4,提交事务,
        tx.commit();
        // 释放资源
        em.close();
    }
}

以上代码也有详细的解释。

jqpl语言的简单讲解:

    package cn.itcast;
    
    import cn.itcast.utils.JpaUtils;
    import org.junit.Test;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityTransaction;
    import javax.persistence.Query;
    import java.util.List;
    
    /**
     * @Created by Intellij IDEA.
     * @author: 陈亚萌
     * @Date: 2020/1/18
     * jpql测试
     */
    public class JpqlTest {
        /**
         * 查询全部:
         *      jqpl:from cn.itcast.domain.Customer
         *      sql:select * from cst_customer
         */
        @Test
        public void testFindAll(){
            //1, 获取Entitymanager对象
            EntityManager em=JpaUtils.getEntityManager();
            //2 开启事务
            final EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            //3 查询全部
            String jpql="from Customer";
            //创建Query对象,query对象才是执行spql对象
            Query query = em.createQuery(jpql);
            //发送查询,并封装结果集
            List list = query.getResultList();
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i));
            }
            // 4.提交事务
            transaction.commit();
    
            // 释放资源
            em.close();
        }
        /**
         * 排序查询:
         *      jqpl:from cn.itcast.domain.Customer order by custId
         *      sql:select * from cst_customer order by cust_id DESC
         *  进行jpql查询:
         *      1. 创建query对象
         *      2. 对参数进行复制
         *      3. 查询并返回结果
         */
        @Test
        public void testOrder(){
            //1, 获取Entitymanager对象
            EntityManager em=JpaUtils.getEntityManager();
            //2 开启事务
            final EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            //3 查询全部
            String jpql="from cn.itcast.domain.Customer order by custId DESC";
            //创建Query对象,query对象才是执行spql对象
            Query query = em.createQuery(jpql);
            //发送查询,并封装结果集
            List list = query.getResultList();
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i));
            }
            // 4.提交事务
            transaction.commit();
    
            // 释放资源
            em.close();
        }
        /**
         * 计数查询:
         *
         *     使用jpql查询,统计客户的总数:
         *      sql:select count(cus_id) from customer
         *      jpql:select count(custId) from Customer
         */
        @Test
        public void testCount(){
            //1, 获取Entitymanager对象
            EntityManager em=JpaUtils.getEntityManager();
            //2 开启事务
            final EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            //3 查询全部
    
            //1 根据jpql语句创建query对象
            String jpql="select count(custId) from Customer";
            //2 参数赋值
            // 3 发送查询,并封装结果
            Query query = em.createQuery(jpql);
            //发送查询,并封装结果集
            /**
             * getResultList:直接将查询结果封装成为list集合
             * getSingleResult:得到唯一的结果集
             */
            final Object singleResult = query.getSingleResult();
            System.out.println(singleResult);
    
            // 4.提交事务
            transaction.commit();
    
            // 释放资源
            em.close();
        }
        /**
         * 分页查询:
         * sql:select * from cst_customer limit ?,?
         * jpql:from Customer
         */
        @Test
        public void testPage(){
            //1, 获取Entitymanager对象
            EntityManager em=JpaUtils.getEntityManager();
            //2 开启事务
            final EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            //3 查询全部
    
            //1 根据jpql语句创建query对象
            String jpql="from Customer";
    
            // 3 发送查询,并封装结果
            Query query = em.createQuery(jpql);
            //发送查询,并封装结果集
            /**
             * getResultList:直接将查询结果封装成为list集合
             * getSingleResult:得到唯一的结果集
             */
            final List resultList = query.getResultList();
            for (Object o : resultList) {
                System.out.println(o);
            }
            //2 参数赋值
            //起始索引,
            query.setFirstResult(0);
            //每页查询的条数
            query.setMaxResults(2);
            // 4.提交事务
            transaction.commit();
    
            // 释放资源
            em.close();
        }
        /**
         * 条件查询:
         *  查询客户名称以“传值”开头的
         *      sql: select * from cst_customer where cust_name like '搜索%'
         *      jpql: from Customer where custName like ?
         */
        @Test
        public void testCondition(){
            //1, 获取Entitymanager对象
            EntityManager em=JpaUtils.getEntityManager();
            //2 开启事务
            final EntityTransaction transaction = em.getTransaction();
            transaction.begin();
            //3 查询全部
    
            //1 根据jpql语句创建query对象
            String jpql="from Customer where custName like ?";
    
            // 3 发送查询,并封装结果
            Query query = em.createQuery(jpql);
            //发送查询,并封装结果集
            /**
             * getResultList:直接将查询结果封装成为list集合
             * getSingleResult:得到唯一的结果集
             */
    
            //2 参数赋值  占位符参数
            // 第一个参数: 占位符的索引位置:(从1开始) 第二个参数:取值
            final Query query1 = query.setParameter(1, "chenya%");
            final List resultList = query.getResultList();
            for (Object o : resultList) {
                System.out.println(o);
            }
            // 4.提交事务
            transaction.commit();
    
            // 释放资源
            em.close();
        }
    }

这种方法一般不常用,常用的是已经封装好的,但是底层源码应该就是这样的,初步理解,如果错误,指出更正。
代码上传到git:
"springdatajpa"

上一篇:java-在jpql select中指定列会导致转换错误


下一篇:java-与JPQL不相关的两个表中的左联接