2015-09-21 57 views
7

这个问题是特别编程创建JPA EntityManagerFactory由Hibernate支持5,这意味着没有配置XML文件不使用Spring。此外,这个问题是特别是关于创建与Hibernate拦截器EntityManagerFactoryJPA与Hibernate 5:编程创建的EntityManagerFactory

我知道如何创建Hibernate SessionFactory我想要的方式,但我不想休眠SessionFactory,我想要一个JPA EntityManagerFactory备份Hibernate 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(); 
} 

使用Hibernate 4.3.0 Ejb3Configuration被删除,所以我不得不使用这个技巧的:(这是一个黑客,因为我实例EntityManagerFactoryImpl这是包org.hibernate.jpa.internal

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); 
} 

现在,随着Hibernate 5他们改变了构造函数EntityManagerFactoryImpl,所以上面的代码不起作用。我可以浪费几个小时试图弄清楚如何设置,以便我可以调用该构造函数,但是我确信在几个Hibernate版本之后,这些将不再工作。

所以,这是我的问题:

有谁知道实现这个功能的一个非常干净的方式

EntityManagerFactory buildEntityManagerFactory( 
     UnmodifiableMap<String,String> properties, 
     UnmodifiableCollection<Class<?>> annotatedClasses, 
     Interceptor interceptor) 

,从而创建一个Hibernate EntityManagerFactory编程,这意味着没有配置xml文件没有使用弹簧带Hibernate拦截器

有这个老问题:Hibernate create JPA EntityManagerFactory with out persistence.xml但它有一个老问题的Hibernate的答案,这个问题已经在这个问题中被预料到了。这是行不通的,因为我希望它能够与Hibernate 5一起工作,并且理想情况下,它不会使用任何废弃的或内部的方法,以便有很长时间的工作机会。

+0

你真的需要拦截器(他们使它很难有原因的登记)。什么是非常特殊的,不能用JPA EventListener替代,并且不会被黑客攻击,解决方法等。 –

+0

@ M.Deinum JPA希望自己实例化我的实体侦听器,要求它们具有无参数的构造函数。这是不可接受的,说得温和。 Hibernate允许我提供拦截器的实际实例,所以我可以以任何我想要的方式构造它。此外,JPA实体监听器不允许我实例化自己的实体。同样,Hibernate拦截器让我可以自由实例化我自己的实体。这是至关重要的。有关更多信息,请参阅http://stackoverflow.com/a/29433238/773113 –

+0

@MikeNakis您是否尝试联系开发组?你有没有解决这种情况?我和你们的问题非常相似。 – message

回答

0

最简单的方法是传递org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor引用,该引用是对“持久性单元”信息的抽象。在普通的JPA引导中,Hibernate会通过persistence.xml(用于JPA调用“SE bootstrapping”)或javax.persistence.spi.PersistenceUnitInfo(用于JPA称为“EE引导”的内容)构建PersistenceUnitDescriptor

但它是一个抽象的原因:)你可以创建你自己的并传递你想要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; 
    } 

    ... 
} 
+0

谢谢!在我有机会检查这件事情并看看它是否适用于我的情况下,我会等一段时间。 –

+0

@MikeNakis我有类似于http://stackoverflow.com/a/42372648/48136中的答案的代码解决了类似的问题(没有拦截器)。请注意,通过重新使用'javax.persistence.Persistence'中的一些代码来查找提供程序,可以避免直接使用'HibernatePersistenceProvider'。 – Brice

相关问题