6

(二)JPA 连接工厂、主键生成策略、DDL自动更新 - look-word

 1 year ago
source link: https://www.cnblogs.com/look-word/p/16724725.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

(一)JPA的快速入门

2、JPA连接工厂

通过之前的 代码 实现已经清楚的发现了整个的JPA实现步骤,但是这个步骤似乎有一些繁琐了,毕竟最终所关心的一定是EntityManager对象实例,而要想获取到此对象的实例,那么要经过许多的步骤,这样如果每一次都重复的进行处理,会非常的繁琐了,那么就需要进行代码的抽象规定。

        // 创建JPA Entity工厂
        EntityManagerFactory factory =
                Persistence.createEntityManagerFactory("YootkJPA");
        // JPA操作对象
        EntityManager entityManager = factory.createEntityManager();

对等概念: DataSource -> EntityMannagerFactory

​ Connection -> EntityMannager,每一个对象的实例都表示一个Session的操作

所以此时可以考虑将部分的代码移交给JPA的专属连接管理类,用这个类可以基于ThreadLocal实现EntityManager存储,这样每一次通过该类的方法获取EntityManager的时候如果不关闭,则获取到的是同一个实例

对于上叙测试类的优化。

  • 一个工具类,简化EntityManagerFactory的创建与关闭
public class JPAEntityFactory {
    /**
     * JPA持久单元
     */
    private static final String PERSISTENCE_UNIT = "YootkJPA";
    /**
     * 等同于 数据源
     */
    private static EntityManagerFactory entityManagerFactory;
    /**
     * EntityManager 等同于 连接
     */
    private static ThreadLocal<EntityManager> entityManagerThreadLocal =
            new ThreadLocal<>();

    static {
        // 初始化创建数据源 静态代码块只会创建一次
        rebuildEntityManagerFactory();
    }
    
    /**
     * 获取连接
     */
    public static EntityManager getEntityManager() {
        // 本机线程获取连接
        EntityManager entityManager = entityManagerThreadLocal.get();
        if (entityManager == null) {
            // 从数据源获取新的连接
            entityManager = getEntityManagerFactory().createEntityManager();
            // 存入本地线程
            entityManagerThreadLocal.set(entityManager);
        }
        return entityManager;
    }
    
    private static EntityManagerFactory getEntityManagerFactory() {
        if (entityManagerFactory == null) {
            // 创建数据源
            rebuildEntityManagerFactory();
        }
        return entityManagerFactory;
    }
    
    private static void rebuildEntityManagerFactory() {
        // 持久单元 创建 数据源
        entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
    }
    
    /**
     * 关闭EntityManager
     */
    public static void close() {
        // 获取实例
        EntityManager entityManager = entityManagerThreadLocal.get();
        if (entityManager != null) {
            // 关闭连接  entityManager类似于Connection
            entityManager.close();
            // 删除本地线程中的连接
            entityManagerThreadLocal.remove();
        }
    }
}

修改测试类:

    @Test
    public void testAdd2() {
        // 获取连接
        EntityManager entityManager = JPAEntityFactory.getEntityManager();
        // 开启事务
        entityManager.getTransaction().begin();
        Course course = new Course();
        course.setCname("Spring编程实战");
        // 字符串 日期对象
        course.setStart(DateUtil.stringToDate("2022-09-19"));
        course.setEnd(DateUtil.stringToDate("2022-12-30"));
        course.setCredit(2);
        course.setNum(88);
        // 执行插入
        entityManager.persist(course);
        // 提交事务
        entityManager.getTransaction().commit();
        // 关闭连接
        JPAEntityFactory.close();
    }

3、主键生成

在JPA开发之中,主键数据的生成主要是基于@Id注解定义的,而在实际的项目开发之中,数据表的设计结构是有所不同的,所以JPA为了适应这些不同的数据表的定义,也提供有不同的主键生成策略。

image-20220923235348927

3、DDL自动更新

在实际的开发之中你是否会出现这样的一种比较 尴尬 的问题,在进行开发的时候有人修改数据表,而后当前的实体类结构和数据表的结构不统一,但是在JPA设计的时候,充分的考虑到了这种数据表修改的问题(表可能存在,也可能不存在,或者表的结构可能修改了),所以在这样的环境下就需要让代码可以自动的进行数据表的纠正。

在传统的项目开发之中,常规的做法是先进行数据表的创建,而后在围绕数据表进行业务功能的实现。在每次业务发生改变时,也是先进行表结构的修改,而后再进行程序的变更,这样的数据库维护是非常繁琐的,考虑到数据库更新以及 数据库移植 方面的设计,在 Hibernate 之中提供了 DDL 自动创建以及表更新策略

image-20220921111235152

JPA现在主要是基于 Hibernate 实现,那么 Hibernate 开发框架最早的一个特点就在于 可移植性,也就是说一个项目是在MySQL数据库下开发的,那么通过简单的配置修改,可以让代码直接在Oracle数据库中运行。

对于当前市面上可以见到的ORM开发框架来讲,只有JPA标准规定了数据库移植性的话题,而Hibernate 实现了JPA标准,所以只有Hibernate 开发框架具有移植性的功能,而像大家所熟悉的MyBatis是没有这样的功能

DDL更新策略

image-20220921111527086

3.1、使用

去到JPA配置文件中,修改DDL更新策略、

3.1.1、create

每次加载时,根据实体类生成表,如果表存在于数据库,会先删除

            <!-- JPA更新策略 -->
            <property name="hibernate.hbm2ddl.auto" value="create"/>
image-20220921123218377

查看执行日志信:可以看到 drop table if exists course (删除表,然后会依据实体类,重新创建表)

3.1.2、update

如果表不存在,重建表。

存在:如:实体类某个字段,在数据表中不存在,这个时候会添加。但是,删除实体类的某个字段,数据库对应的字段并不会删除。

修改实体类: 添加教师

image-20220921125003973

修改配置文件-更新策略为update

image-20220921125110845

查看执行日志:

表不存在,创建表

create table course (
cid bigint not null auto_increment,
cname varchar(255),
credit integer,
end date,
num integer,
start date,
teacher varchar(255),
primary key (cid)
) engine=InnoDB

排除属性

假如,我们相使实体类中的某个字段,在执行时,不创建数据库中的对应字段。使用@Transient即可

image-20220921130257497

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK