2010-06-08 10 views
5

Possiedo un'applicazione web Java che sfrutta JPA. L'istanza del database è specificata nel file persistence.xml utilizzando il tag jta-data-source.Come "parametrizzare" l'istanza del database JPA in persistence.xml?

Vorrei distribuire una seconda copia dell'applicazione Web sullo stesso server (glassfish), ma puntato su un'istanza di database diversa.

Qual è il modo migliore per raggiungere questo obiettivo? Penso che idealmente, mi piacerebbe inserire un file override persistence.xml al di fuori della guerra (da qualche parte sul classpath?). Non sono esattamente sicuro su dove metterlo o su come definirlo in un modo che non possa confondere con la mia altra istanza. Posso vederci ospitare una manciata di istanze in questo modo (SaaS) e vorrei che la configurazione fosse al di fuori della guerra dispiegata in modo che non diventasse un problema di manutenzione. La condivisione di un'istanza di database tra client non è un'opzione per motivi di sicurezza.

Sono sicuro che questo non è un problema unico per il nostro gruppo. Quali sono le migliori pratiche o soluzioni che altri stanno usando per risolvere questo problema?

+0

Se sono presenti più istanze uniche dell'app in esecuzione, perché non modificare semplicemente persistence.xml per la seconda istanza? – kgrad

+0

Sembra che un problema di manutenzione debba essere eseguito manualmente per ogni istanza su ogni build, mi piacerebbe una soluzione automatizzata. – Vinnie

risposta

1

i Immagino che stai già alterando la copia anche in altre cose? (ad esempio nome del file ear)

Se si utilizza un software di build come ant o maven, è possibile utilizzare un segnaposto all'interno di persistence.xml e creare una "copia" differente utilizzando solo parametri di configurazione diversi.

ad es. con Maven

mvn clean install -DmyDatabaseName = db/somedb

+0

OK, sembra fantastico. Cosa devo inserire nel mio persistence.xml come segnaposto per la sostituzione del testo? – Vinnie

+1

vedere il commento da Pascal qui sotto :-) –

+0

Devo trovare una soluzione su come fare ciò che la domanda originale ha chiesto, in quanto devo gestire circa 500 server in luoghi diversi con connessioni diverse. Altre idee, come fare 500 guerre non è una buona idea: S – Vedran

1

sarei confezionare due versioni del webapp e dichiarare un'origine dati specifica nell'elemento jta-data-source dei rispettivi persistence.xml (non credo che si può esternalizzare questo file, ci si aspetta di essere in WEB-INF/classes/META-INF/persistence.xml)

+0

Ah, lo temevo. Costruire più volte per fare un semplice cambiamento di configurazione sembra un problema dal punto di vista della manutenzione man mano che l'applicazione matura, vengono aggiunti più client e vengono rilasciate nuove versioni (10 client significa 10 cicli di generazione e distribuzione separati con modifiche al file di persistenza tra). Io uso Maven per costruire e pacchettizzare. Sai se esiste un plugin Maven che sarebbe in grado di generare più guerre, prendendo l'xml di persistenza appropriato per ogni configurazione? – Vinnie

+1

@Vinnie: io userei [filtering and profiles] (http://www.sonatype.com/books/mvnref-book/reference/resource-filtering-sect-description.html) (e lasciare che il mio motore CI compilasse tutto varianti usando una Build Matrix). Dichiara qualcosa come ' $ {pippo}' nel tuo 'persistence.xml' e usa Maven per filtrare il valore. –

2

aggiornamento:

http://docs.jboss.org/hibernate/stable/entitymanager/reference/en/html/configuration.html

non so se questo può essere impostato in un appserver, ma ho deciso di dargli un partire. l'unica cosa che mi preoccupa è la gestione dello scope. il contenitore gestisce la portata lungo i confini di transazione

//inject entity manager 
@Inject("mySpecialEntityManager") 
EntityManager em; 

//then mark the actual factory method in the factory bean with  
@Produces("mySpecialEntityManager") 

ma poi come gestire la portata è il problema


2.2.2. Bootstrapping

La specifica JPA definisce una procedura di bootstrap per accedere a EntityManagerFactory e EntityManager. La classe bootstrap è javax.persistence.Persistence, ad es.

Mappa configOverrides = new HashMap();

configOverrides.put ("hibernate.hbm2ddl.auto", "create-drop");

EntityManagerFactory programmaticEmf =

Persistence.createEntityManagerFactory("manager1", configOverrides); 

La prima versione è equivalente al secondo con una mappa vuota.La versione della mappa è un insieme di sostituzioni che avrà la precedenza su qualsiasi proprietà definita nei file persistence.xml. Tutte le proprietà definite nella sezione 2.2.1, “imballaggio” possono essere passati al metodo createEntityManagerFactory e ci sono un paio di quelle aggiuntive:

* 

    javax.persistence.provider to define the provider class used 
* 

    javax.persistence.transactionType to define the transaction type used (either JTA or RESOURCE_LOCAL) 
* 

    javax.persistence.jtaDataSource to define the JTA datasource name in JNDI 
* 

    javax.persistence.nonJtaDataSource to define the non JTA datasource name in JNDI 
* 

    javax.persistence.lock.timeout pessimistic lock timeout in milliseconds (Integer or String) 
* 

    javax.persistence.query.timeout query timeout in milliseconds (Integer or String) 
* 

    javax.persistence.sharedCache.mode corresponds to the share-cache-mode element defined in Section 2.2.1, “Packaging”. 
1

Che dire di memorizzare una persistence.xml nella cartella META-INF di un Directory classes e quindi specificando prima quella cartella nel classpath?

0

Ecco quello che ero in grado di fare in un ambiente Java SE:

Creare un file .jar senza il file persistence.xml . Ho creato un file manifest.mf manualmente e nel file Class-Path: ho inserito "." oltre alle altre voci di cui avevo bisogno.

Nella directory in cui si installa il software, creare una directory META-INF e inserire persistence.xml lì. Dovrebbe essere prelevato automaticamente.

ad es.

/my/install/dir/ 
       META-INF/persistence.xml 
       foo.jar 
Problemi correlati