没有persistence.xml初始化一个EntityManagerFactory

上一节我们介绍了通过persistence.xml初始化一个EntityManagerFactory;但是在很多种情况下是不需要使用xml配置文件来配置持久化单元的,因此,我们今天来学习如何通过编程来自动初始化一个EntityManagerFactory

Hibernate早就为我们考虑到了这一点,它允许您完全以编程方式构建一个 EntityManagerFactory,只需几行代码:

protected EntityManagerFactory newEntityManagerFactory() {
    PersistenceUnitInfo persistenceUnitInfo =
        persistenceUnitInfo(getClass().getSimpleName());
    Map<String, Object> configuration = new HashMap<>();
    configuration.put(AvailableSettings.INTERCEPTOR,
        interceptor()
    );
 
    return new EntityManagerFactoryBuilderImpl(
            new PersistenceUnitInfoDescriptor(
                persistenceUnitInfo), configuration
    ).build();
}
 
protected PersistenceUnitInfoImpl persistenceUnitInfo(
    String name) {
    return new PersistenceUnitInfoImpl(
        name, entityClassNames(), properties()
    );
}

每个测试都以一些合理的默认属性开始,并且必须在每个测试的基础上提供实体。

protected Properties properties() {
    Properties properties = new Properties();
    properties.put("hibernate.dialect",
        dataSourceProvider().hibernateDialect()
    );
    properties.put("hibernate.hbm2ddl.auto",
        "create-drop");
    DataSource dataSource = newDataSource();
    if (dataSource != null) {
        properties.put("hibernate.connection.datasource",
        dataSource);
    }
    return properties;
}
 
protected List entityClassNames() {
    return Arrays.asList(entities())
        .stream()
        .map(Class::getName)
        .collect(Collectors.toList());
}

每个测试可以定义自己的设置和实体,这样我们就可以封装整个环境。

@Override
protected Class<?>[] entities() {
    return new Class<?>[] {
        Patch.class
    };
}
 
@Entity(name = "Patch")
public class Patch {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @ElementCollection
    @CollectionTable(
            name="patch_change",
            joinColumns=@JoinColumn(name="patch_id")
    )
    @OrderColumn(name = "index_id")
    private List<Change> changes = new ArrayList<>();
 
    public List<Change> getChanges() {
        return changes;
    }
}
 
@Embeddable
public class Change {
 
    @Column(name = "path", nullable = false)
    private String path;
 
    @Column(name = "diff", nullable = false)
    private String diff;
 
    public Change() {
    }
 
    public Change(String path, String diff) {
        this.path = path;
        this.diff = diff;
    }
 
    public String getPath() {
        return path;
    }
 
    public String getDiff() {
        return diff;
    }
}

以上代码简单吧,主要就是使用了两个关键的类EntityManagerFactoryBuilderImplPersistenceUnitInfoImpl进行了封装,第一个类负责创建EntityManagerFactory,第二个类负责封装persistence.xml的相关配置信息,因此,主要还是用这个类来实现持久化单元的可编程配置。

大家如果对此感兴趣,可以留言一起讨论。嘿嘿

版权声明:著作权归作者所有。

大牛的文章呀,我的代码都是直接在persistence.xml中配置的,您的代码让我对EntityManagerFactory有了更加深入的理解。哈哈,也对持久化单元有了一些认识。
您的这些代码只是一些松散的代码,具体的还是跑步起来,再说了,您这样初始化EntityManagerFactory有啥作用呢?还是你打算做一些封装。
如果能分析一下这几个类就好了,比如EntityManagerFactoryBuilderImpl,还有PersistenceUnitInfoImpl这个类为啥这样实现
EntityManagerFactoryBuilderImpl这个类的实现比较复杂,简单理解就是创建EntityManagerFactory
thumb_up 2 | star_outline 0 | textsms 3