首页 > 其他 > 详细

JPA一篇从入门到实战

时间:2021-01-12 09:54:10      阅读:51      评论:0      收藏:0      [点我收藏+]

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 数据关系映射

JPA一篇从入门到实战

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

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!