JPA with Hibernate 5:以编程方式创建EntityManagerFactory

Mik*_*kis 7 java hibernate jpa hibernate-entitymanager hibernate-5.x

这个问题是专门关于编程创建JPA EntityManagerFactory由Hibernate支持5,这意味着无需配置XML文件没有使用Spring.此外,这个问题具体是关于EntityManagerFactory 使用Hibernate Interceptor创建一个.

我知道如何以SessionFactory我想要的方式创建Hibernate ,但我不想要Hibernate SessionFactory,我想要一个EntityManagerFactory由Hibernate支持的JPA SessionFactory.鉴于EntityManagerFactory有一种方法可以获得底层证券SessionFactory,但如果你拥有的是一个SessionFactory并且所有你想要的东西都是EntityManagerFactory它的包装,看起来你运气不好.

Hibernate版本4.2.2 Ejb3Configuration已被弃用,但似乎没有其他方式以编程方式创建EntityManagerFactory,所以我做了这样的事情:

@SuppressWarnings( "deprecation" )
EntityManagerFactory buildEntityManagerFactory(
        UnmodifiableMap<String,String> properties,
        UnmodifiableCollection<Class<?>> annotatedClasses, 
        Interceptor interceptor )
{
    Ejb3Configuration cfg = new Ejb3Configuration();
    for( Binding<String,String> binding : properties )
        cfg.setProperty( binding.key, binding.value );
    for( Class<?> annotatedClass : annotatedClasses )
        cfg.addAnnotatedClass( annotatedClass );
    cfg.setInterceptor( interceptor );
    return cfg.buildEntityManagerFactory();
}
Run Code Online (Sandbox Code Playgroud)

随着Hibernate 4.3.0 Ejb3Configuration被删除,所以我不得不利用这个hack:

EntityManagerFactory buildEntityManagerFactory(
        UnmodifiableMap<String,String> properties,
        UnmodifiableCollection<Class<?>> annotatedClasses,
        Interceptor interceptor )
{
    Configuration cfg = new Configuration();
    for( Binding<String,String> binding : properties )
        cfg.setProperty( binding.key, binding.value );
    for( Class<?> annotatedClass : annotatedClasses )
        cfg.addAnnotatedClass( annotatedClass );
    cfg.setInterceptor( interceptor );
    StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder();
    ssrb.applySettings( cfg.getProperties() ); //??? why again?
    ServiceRegistry serviceRegistry = ssrb.build();
    return new EntityManagerFactoryImpl( PersistenceUnitTransactionType.RESOURCE_LOCAL, /**/
            /*discardOnClose=*/true, /*sessionInterceptorClass=*/null, /**/
            cfg, serviceRegistry, null );
}
Run Code Online (Sandbox Code Playgroud)

(这是一个黑客,因为我正在实例化EntityManagerFactoryImpl包中org.hibernate.jpa.internal.)

现在,使用Hibernate 5他们已经改变了构造函数EntityManagerFactoryImpl,因此上面的代码不起作用.我可以浪费几个小时试图弄清楚如何设置,以便我可以调用该构造函数,但我确信在经过几个Hibernate版本之后,这也将无法工作.

所以,这是我的问题:

有没有人知道实现这个功能的一种漂亮而干净的方式

EntityManagerFactory buildEntityManagerFactory( 
        UnmodifiableMap<String,String> properties,
        UnmodifiableCollection<Class<?>> annotatedClasses, 
        Interceptor interceptor )
Run Code Online (Sandbox Code Playgroud)

EntityManagerFactory 编程方式创建一个Hibernate ,这意味着没有配置xml文件,没有使用Spring而是使用Hibernate Interceptor

有一个老问题:Hibernate使用out pers.xml创建JPA EntityManagerFactory但它有一个旧版本的Hibernate的答案,这已经在这个问题中得到了预期.这是不行的,因为我希望它能够与Hibernate 5一起工作,理想情况下,它不会使用任何弃用或内部的东西,以便有一段时间可以工作的机会.

Ste*_*ole 0

最简单的方法是传递引用org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor,这是对“持久性单元”信息的抽象。PersistenceUnitDescriptor在正常的 JPA 引导中,Hibernate 将在 persistence.xml(JPA 称为“SE 引导”)或javax.persistence.spi.PersistenceUnitInfo(JPA 称为“EE 引导”) 上构建一个。

但它是一个抽象是有原因的:) 您可以创建自己的抽象并传递您希望 Hibernate 使用的内容。它的预期工作方式是从 开始org.hibernate.jpa.boot.spi.Bootstrap,例如:

EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder(
        new CustomPersistenceUnitDescriptor(),
        Collections.emptyMap()
).build();

...

class CustomPersistenceUnitDescriptor implements PersistenceUnitDescriptor {
    @Override
    public Properties getProperties() {
        final Properties properties = new Properties();
        properties.put( AvailableSettngs.INTERCEPTOR, new MyInterceptor( ... );
        return properties;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)