2015-09-21 13 views
7

Questa domanda è specificamente circa programmazione la creazione di un JPA EntityManagerFactory sostenuta da Hibernate 5, che significa senza file di configurazione XML e senza l'utilizzo di primavera. Inoltre, questa domanda è nello specifico sulla creazione di uno EntityManagerFactorycon un Hibernate Interceptor.JPA con Hibernate 5: a livello di codice creare EntityManagerFactory

so come creare un Hibernate SessionFactory come voglio, ma non voglio un Hibernate SessionFactory, voglio un JPA EntityManagerFactory sostenuta da un Hibernate SessionFactory. Dato un EntityManagerFactory c'è un modo per ottenere il sottostante SessionFactory, ma se quello che hai è un SessionFactory e tutto quello che vuoi è un wrapper EntityManagerFactory attorno ad esso, sembra che sei sfortunato.

con Hibernate versione 4.2.2 Ejb3Configuration era già deprecato, ma non sembrava esserci altro modo per creare a livello di codice un EntityManagerFactory, quindi stavo facendo qualcosa di simile:

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

con Hibernate 4.3.0 Ejb3Configuration è stato rimosso, così ho dovuto fare uso di questo hack: (. si tratta di un hack perché sto istanziare EntityManagerFactoryImpl che si trova nel pacchetto 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); 
} 

Ora, con Hibernate 5 hanno cambiato il costruttore di EntityManagerFactoryImpl, quindi il codice sopra riportato non funziona. Posso sprecare qualche ora cercando di capire come impostare le cose in modo da poter invocare quel costruttore, ma sono sicuro che dopo un paio di versioni di Hibernate, non funzionerà più neanche così.

Quindi, questa è la mia domanda:

Qualcuno sa di un modo bello e pulito di implementare questa funzione

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

in modo da creare un Hibernate EntityManagerFactoryprogrammazione, che significa senza file xml di configurazione e senza utilizzare la primavera ma con un Hibernate Interceptor?

C'è questa vecchia domanda: Hibernate create JPA EntityManagerFactory with out persistence.xml ma ha una risposta per una versione precedente di Hibernate, che è già stata anticipata in questa domanda. Non lo farò, perché voglio che funzioni con Hibernate 5, e idealmente, in un modo che non usi nulla di deprecato o di interno, in modo da avere alcune possibilità di lavorare per molto tempo a venire.

+0

Avete veramente bisogno l'intercettore (che rendono difficile per registrare per un motivo). Cosa c'è di così speciale che non può essere sostituito con un EventListener JPA e funziona senza hack, soluzioni alternative, ecc. –

+0

@ M.Deinum JPA vuole istanziare i miei ascoltatori di entità da solo, richiedendo loro di avere costruttori senza parametri. Questo è inaccettabile, per usare un eufemismo. Hibernate mi consente di fornire l'istanza effettiva del mio intercettore, così posso costruirla nel modo che voglio. Inoltre, gli ascoltatori dell'entità JPA non mi permettono di istanziare le mie stesse entità. Di nuovo, Hibernate Interceptor mi dà la libertà di istanziare le mie stesse entità. Questo è di fondamentale importanza. Per ulteriori informazioni, consultare http://stackoverflow.com/a/29433238/773113 –

+0

@MikeNakis Hai provato a contattare il gruppo dev? Hai risolto quella situazione? Ho un problema molto simile al tuo. – message

risposta

0

Il modo più semplice è passare un riferimento org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor, che è un'astrazione sulle informazioni di "unità di persistenza". Nel normale bootstrap JPA Hibernate crea un valore PersistenceUnitDescriptor sul persistence.xml (per ciò che JPA chiama "SE bootstrapping") o su javax.persistence.spi.PersistenceUnitInfo (per ciò che JPA chiama "EE bootstrapping").

Ma è un'astrazione per un motivo :) È possibile creare il proprio e passare ciò che si desidera utilizzare a Hibernate. Il modo in cui funziona è destinato questo a partire dal org.hibernate.jpa.boot.spi.Bootstrap, ad es .:

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

Grazie! Passerà un po 'di tempo prima che riesca a controllarlo e vedere se funziona per me, quindi resta lì. –

+0

@MikeNakis Ho avuto lo stesso tipo di problemi (senza intercettore) che ho risolto tramite codice simile alla risposta in http://stackoverflow.com/a/42372648/48136. Nota che è possibile evitare di usare 'HibernatePersistenceProvider' direttamente riutilizzando del codice nel' javax.persistence.Persistence' per trovare il provider. – Brice

Problemi correlati