JPA一篇从入门到实战

技术文章 7个月前 完美者
1,195 0

标签:inter   实体类   北京   保存数据   llb   完成   com   persist   int   

Hibernate5 JPA 快速入门

1、Hibernate5 JPA简介

2、搭建开发环境(IDEA)

3、JPA 核心API对象

Persistence / EntityManagerFactory / EntityManager / EntityTransaction

Hibernate JPA 的操作步骤:

1. 加载配置文件创建实体管理器工厂
2. 根据实体管理器工厂,创建实体管理器
3. 创建事务对象,开启事务
4. 完成增删改查操作
5. 提交事务(回滚事务)
6. 释放资源

Persistence对象(创建实体管理器工厂)

/**
 * Persisitence.createEntityMnagerFactory(持久化单元名称)
 * 静态方法(根据持久化单元名称创建实体管理器工厂)
 **/
// 1.加载配置文件创建工厂(实体管理器工厂)对象
EntityManagerFactory factory = Persistence.createEntityManagerFactory("myJpa");

Persistence对象主要作用是用于获取EntityManagerFactory对象的 。通过调用该类的createEntityManagerFactory静态方法,根据配置文件中持久化单元名称创建EntityManagerFactory

EntityManagerFactoryEntityManagerFactory接口主要用来创建 EntityManager 实例)

/**
 * entityManagerFactory.createEntityManager():获取EntityManager对象
 *     内部维护的很多的内容:
 *         1.内部维护了数据库信息
 *         2.维护了缓存信息
 *         3.维护了所有的实体管理器对象
 *         4.在创建EntityManagerFactory的过程中会根据配置创建数据库表
 *     EntityManagerFactory的创建过程比较浪费资源
 *         特点:线程安全的对象,多个线程访问同一个EntityManagerFactory不会有线程安全问题
 *     如何解决EntityManagerFactory的创建过程浪费资源(耗时)的问题?
 *         思路:创建一个公共的EntityManagerFactory的对象
 *         静态代码块的形式创建EntityManagerFactory
 **/
// 2.通过实体管理器工厂获取实体管理器
EntityManager em = factory.createEntityManager();

EntityManager

/**
 * EntityManager:实体类管理器
 *     获取事务对象: getTransaction()
 *     保存数据: presist()
 *     更新数据: merge()
 *     删除数据: remove()
 *     根据id查询: find()/getRefrence(): 
 *     ......(还有挺多方法可以自己慢慢琢磨)
 **/
// 3.获取事务对象,然后可以开启事务、提交事务、回滚事务
EntityTransaction tx = em.getTransaction(); 

在 JPA 规范中, EntityManager是完成持久化操作的核心对象。实体类作为普通 java对象,只有在调用 EntityManager将其持久化后才会变成持久化对象。EntityManager对象在一组实体类与底层数据源之间进行 O/R 映射的管理。它可以用来管理和更新 Entity Bean, 根椐主键查找 Entity Bean, 还可以通过JPQL语句查询实体。我们可以通过调用EntityManager的方法完成获取事务,以及持久化数据库的操作

EntityTransaction

/**
 * EntityTransaction: 事务对象
 *     开启事务: begin()
 *     提交事务: commit()
 *     回滚事务: rollback()
 **/
// 开启事务
tx.begin();

在 JPA 规范中, EntityTransaction是完成事务操作的核心对象,对于EntityTransaction在我们的 java 代码中承接的功能比较简单

4、JPA 实现CRUD操作

保存操作

    /**
     * 运行之前,修改hibernate.hbm2ddl.auto=create
     * 保存操作
     */
    @Test
    public void testSave() {
        // 获取实体管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        // 获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 获取事务
        EntityTransaction transaction = entityManager.getTransaction();
        // 开启事务
        transaction.begin();
        // 创建实体对象并保存
        Customer customer1 = new Customer();
        customer1.setName("张三");
        customer1.setAge(20);
        customer1.setSex(true);
        customer1.setPhone("13018882888");
        customer1.setAddress("北京");
        entityManager.persist(customer1);

        Customer customer2 = new Customer();
        customer2.setName("李四");
        customer2.setAge(18);
        customer2.setSex(false);
        customer2.setPhone("13533333555");
        customer2.setAddress("广州");
        entityManager.persist(customer2);

        Customer customer3 = new Customer();
        customer3.setName("王五");
        customer3.setAge(28);
        customer3.setSex(true);
        customer3.setPhone("13012345678");
        customer3.setAddress("深圳");
        entityManager.persist(customer3);
        // 提交事务
        transaction.commit();
        // 释放资源
        entityManager.close();
        entityManagerFactory.close();
    }

查看日志:

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: insert into c_customer (c_address, c_age, c_name, c_phone, c_sex) values (?, ?, ?, ?, ?)
Hibernate: insert into c_customer (c_address, c_age, c_name, c_phone, c_sex) values (?, ?, ?, ?, ?)
Hibernate: insert into c_customer (c_address, c_age, c_name, c_phone, c_sex) values (?, ?, ?, ?, ?)

根据 id 查询操作

  • find 方法实现(立即查询)
    /**
     * 运行之前,修改hibernate.hbm2ddl.auto=update
     * 立即查询操作
     */
    @Test
    public void testQuery1() {
        // 获取实体管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        // 获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 获取事务
        EntityTransaction transaction = entityManager.getTransaction();
        // 开启事务
        transaction.begin();
        // 查询实体并输出
        Customer customer = entityManager.find(Customer.class, 2L);
        System.out.println(customer);
        // 提交事务
        transaction.commit();
        // 释放资源
        entityManager.close();
        entityManagerFactory.close();
    }

实际发送的SQL语句就是:select * from customer where id = 2

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select customer0_.id as id1_0_0_, customer0_.c_address as c_addres2_0_0_, customer0_.c_age as c_age3_0_0_, customer0_.c_name as c_name4_0_0_, customer0_.c_phone as c_phone5_0_0_, customer0_.c_sex as c_sex6_0_0_ from c_customer customer0_ where customer0_.id=?
Customer(Id=2, name=李四, age=20, sex=false, phone=13533333555, address=广州)
  • getReference 方法实现(懒加载查询)(推荐)
    /**
     * 运行之前,修改hibernate.hbm2ddl.auto=update
     * 延迟查询操作(查询结果对象的时候,才会发送查询的sql语句)
     */
    @Test
    public void testQuery2() {
        // 获取实体管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        // 获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 获取事务
        EntityTransaction transaction = entityManager.getTransaction();
        // 开启事务
        transaction.begin();
        // 查询实体并输出
        Customer customer = entityManager.getReference(Customer.class, 2L);
        System.out.println(customer);
        // 提交事务
        transaction.commit();
        // 释放资源
        entityManager.close();
        entityManagerFactory.close();
    }

日志发现与 find 查询没有区别:

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select customer0_.id as id1_0_0_, customer0_.c_address as c_addres2_0_0_, customer0_.c_age as c_age3_0_0_, customer0_.c_name as c_name4_0_0_, customer0_.c_phone as c_phone5_0_0_, customer0_.c_sex as c_sex6_0_0_ from c_customer customer0_ where customer0_.id=?
Customer(Id=2, name=李四, age=20, sex=false, phone=13533333555, address=广州)

可以注释打印对象在对比试试://System.out.println(customer);

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]

可以发现,如果没有使用对象的话,是没有调用查询SQL语句的

findgetReference 查询对比:

  • find 实现的查询时,是会在调用 find 方法时,立即发送SQL语句查询数据库的操作
  • getReference 是一种延迟加载策略的操作,调用getReference方法不会立即发送sql语句查询数据库,当调用查询结果对象的时候,才会发送查询的sql语句(实际就是动态代理)

更新操作

    /**
     * 运行之前,修改hibernate.hbm2ddl.auto=update
     * 更新操作
     */
    @Test
    public void testUpdate() {
        // 获取实体管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        // 获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 获取事务
        EntityTransaction transaction = entityManager.getTransaction();
        // 开启事务
        transaction.begin();
        // 查询实体并更新
        Customer customer = entityManager.find(Customer.class, 2L);
        customer.setAddress("上海");
        entityManager.merge(customer);
        // 提交事务
        transaction.commit();
        // 释放资源
        entityManager.close();
        entityManagerFactory.close();
    }

查看日志:

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select customer0_.id as id1_0_0_, customer0_.c_address as c_addres2_0_0_, customer0_.c_age as c_age3_0_0_, customer0_.c_name as c_name4_0_0_, customer0_.c_phone as c_phone5_0_0_, customer0_.c_sex as c_sex6_0_0_ from c_customer customer0_ where customer0_.id=?
Hibernate: update c_customer set c_address=?, c_age=?, c_name=?, c_phone=?, c_sex=? where id=?

删除操作

    /**
     * 运行之前,修改hibernate.hbm2ddl.auto=update
     * 删除操作
     */
    @Test
    public void testDelete() {
        // 获取实体管理器工厂
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myJpa");
        // 获取实体管理器
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        // 获取事务
        EntityTransaction transaction = entityManager.getTransaction();
        // 开启事务
        transaction.begin();
        // 查询实体并删除
        Customer customer = entityManager.find(Customer.class, 1L);
        entityManager.remove(customer);
        // 提交事务
        transaction.commit();
        // 释放资源
        entityManager.close();
        entityManagerFactory.close();
    }

查看日志:

INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
Hibernate: select customer0_.id as id1_0_0_, customer0_.c_address as c_addres2_0_0_, customer0_.c_age as c_age3_0_0_, customer0_.c_name as c_name4_0_0_, customer0_.c_phone as c_phone5_0_0_, customer0_.c_sex as c_sex6_0_0_ from c_customer customer0_ where customer0_.id=?
Hibernate: delete from c_customer where id=?

5、JPA 连接工厂工具类

为什么要抽取 JpaUtil 工具类?

由于EntityManagerFactory 是一个线程安全的对象(即多个线程访问同一个EntityManagerFactory 对象不会有线程安全问题),并且EntityManagerFactory 的创建极其浪费资源,所以在使用JPA编程时,我们可以对EntityManagerFactory 的创建进行优化,只需要做到一个工程只存在一个EntityManagerFactory 即可。

解决思路是通过静态代码的形式创建 EntityManagerFactory

  • JpaUtil.java 工具类
/**
 * 解决实体管理器工厂的浪费资源和耗时问题
 *      通过静态代码块的形式,当程序第一次访问此工具类时,创建一个公共的实体管理器工厂对象
 *
 * 第一次访问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();
    }
}
  • 测试工具类
public class JpaTest {
    @Test
    public void testSave() {
        // 1.通过工具类获取实体类管理器
        EntityManager em = JpaUtils.getEntityManager();
        // 2.获取事务对象
        EntityTransaction tx = em.getTransaction();
        // 开启事务
        tx.begin();
        //3.完成增删改查操作:保存一个客户到数据库中
        Customer customer = new Customer();
        customer.setName("Yolo");
        customer.setAddress("BeiJing");
        //保存操作
        em.persist(customer);
        //4.提交事务
        tx.commit();
        //5.释放资源
        em.close();
        //因为工厂是公共的,不能关闭,不然其他线程将无法获取
        //factory.close();
    }
}

Hibernate5 JPA 复杂查询

1、JPQL 语句

2、原生SQL查询

3、Criteria 查询

Hibernate5 JPA 注解分析

1、常用注解

Hibernate5 JPA 缓存配置

Hibernate5 JPA 锁机制

Hibernate5 JPA 数据关系映射

SpringData JPA 快速入门

SpringData JPA 查询方式

1、SpringData 定义的方法

2、使用JPQL的方式查询

3、使用 SQL 语句查询

4、Specifications 动态查询

SpringData JPA 数据表映射

1、一对一表设计

2、一对多表设计

3、多对多表设计

JPA一篇从入门到实战

标签:inter   实体类   北京   保存数据   llb   完成   com   persist   int   

原文地址:https://www.cnblogs.com/liusuixing/p/14265087.html

版权声明:完美者 发表于 2021-01-13 11:16:32。
转载请注明:JPA一篇从入门到实战 | 完美导航

暂无评论

暂无评论...