2015-09-21 13 views
7

Diese Frage ist speziell über programmatisch eine JPA EntityManagerFactory Schaffung von Hibernate gesichert 5, was bedeutet, ohne Konfiguration XML-Dateien und ohne Verwendung von Spring. Auch diese Frage ist speziell über die Erstellung eines EntityManagerFactorymit einem Hibernate Interceptor.JPA mit Hibernate 5: erstellen programmatisch EntityManagerFactory

Ich weiß, wie eine Hibernate SessionFactory, wie ich will zu schaffen, aber ich will kein Hibernate SessionFactory, ich will ein JPA EntityManagerFactory von einem Hibernate SessionFactory gesichert. Angesichts einer EntityManagerFactory gibt es eine Möglichkeit, die zugrunde liegende SessionFactory zu erhalten, aber wenn Sie eine SessionFactory und alles, was Sie wollen, ist ein EntityManagerFactory Wrapper drumherum, es scheint, dass Sie kein Glück haben.

Mit Hibernate Version 4.2.2 Ejb3Configuration wurde bereits veraltet, aber es schien keine andere Möglichkeit, um programmatisch ein EntityManagerFactory zu erstellen, also war ich so etwas wie dies zu tun:

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

Mit Hibernate 4.3.0 Ejb3Configuration entfernt wurde, so hatte ich Verwendung dieses Hacks zu machen: (. Es ist ein Hack, weil ich EntityManagerFactoryImpl bin Instanziieren die org.hibernate.jpa.internal im Paket ist)

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

Nun, mit Hibernate 5 haben sie den Konstruktor EntityManagerFactoryImpl geändert, so funktioniert der obige Code nicht. Ich kann ein paar Stunden damit verbringen, herauszufinden, wie ich die Dinge einrichten soll, damit ich diesen Konstruktor aufrufen kann, aber ich bin sicher, dass nach ein paar Hibernate-Versionen auch das nicht mehr funktionieren wird.

Also, das ist meine Frage:

Weiß jemand von einem schönen und sauberen Weg, um diese Funktion zu implementieren

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

, um eine Hibernate EntityManagerFactoryprogrammatisch, erstellen Bedeutung ohne Konfiguration XML-Dateien und ohne Verwendung von Spring aber mit einem Hibernate Interceptor?

Es gibt diese alte Frage: Hibernate create JPA EntityManagerFactory with out persistence.xml, aber es hat eine Antwort auf eine ältere Version von Hibernate, die bereits in dieser Frage antizipiert wurde. Das geht nicht, weil ich möchte, dass es mit Hibernate 5 funktioniert, und zwar idealerweise in einer Weise, die nichts Veraltetes oder Internes verwendet, um einige Chancen zu haben, lange zu arbeiten.

+0

Haben Sie wirklich die Abfangjäger müssen (sie machen es schwer, einen Grund zu registrieren). Was ist das Besondere daran, das nicht durch einen JPA EventListener ersetzt werden könnte und ohne Hacks, Workarounds usw. funktionieren würde? –

+0

@M.Deinum JPA möchte meine Entity-Listener selbst instanziieren, indem sie parameterlose Konstruktoren benötigen. Das ist inakzeptabel, um es milde auszudrücken. Hibernate ermöglicht es mir, die tatsächliche Instanz meines Interceptors zu liefern, damit ich es beliebig konstruieren kann. JPA-Entity-Listener erlauben mir auch nicht, meine eigenen Entitäten zu instanziieren. Wiederum gibt mir der Hibernate Interceptor die Freiheit, meine eigenen Entitäten zu instantiieren. Das ist von größter Wichtigkeit. Weitere Informationen finden Sie unter http://stackoverflow.com/a/29433238/773113 –

+0

@MikeNakis Haben Sie versucht, die Dev-Gruppe zu kontaktieren? Hast du diese Situation gelöst? Ich habe ein sehr ähnliches Problem wie Ihres. – message

Antwort

0

Der einfachste Weg ist, eine org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor Referenz zu übergeben, die eine Abstraktion über "Persistenzeinheit" Information ist. Im normalen JPA-Bootstrapping würde Hibernate einen PersistenceUnitDescriptor über der persistence.xml (für was JPA "SE Bootstrapping" nennt) oder über die javax.persistence.spi.PersistenceUnitInfo (für was JPA "EE Bootstrapping" nennt) aufbauen.

Aber es ist eine Abstraktion aus einem Grund :) Sie könnten Ihre eigenen erstellen und übergeben, was Sie Hibernate verwenden möchten. Die vorgesehene Art und Weise dies funktioniert, ist aus org.hibernate.jpa.boot.spi.Bootstrap starten, z.B .:

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

Danke! Es wird noch einige Zeit dauern, bis ich die Gelegenheit habe, das zu überprüfen und zu sehen, ob es für mich funktioniert, also bleib dran. –

+0

@MikeNakis Ich hatte die gleichen Probleme (ohne Interceptor), die ich über Code ähnlich der Antwort in http://stackoverflow.com/a/42372648/48136 gelöst habe. Beachten Sie, dass es möglich ist, 'HibernatePersistenceProvider' direkt zu vermeiden, indem Sie Code in' javax.persistence.Persistence' wiederverwenden, um den Provider zu finden. – Brice

Verwandte Themen