2010-06-08 6 views
5

Ich habe eine Java-Webanwendung, die JPA nutzt. Die Datenbankinstanz wird in der Datei persistence.xml mit dem Tag angegeben.Wie "parameterize" JPA-Datenbankinstanz in persistence.xml?

Ich möchte eine zweite Kopie der Webanwendung auf demselben (Glassfish) Server bereitstellen, zeigte aber auf eine andere Datenbankinstanz.

Was ist der beste Weg, dies zu erreichen? Ich denke, idealerweise würde ich gerne eine persistence.xml Override-Datei außerhalb des Krieges (irgendwo auf dem Klassenpfad?) Platzieren. Ich weiß nicht genau, wo ich es hinstellen soll oder wie ich es so definieren soll, dass es nicht mit meiner anderen Instanz zusammenfallen würde. Ich kann sehen, dass wir eine Handvoll Instanzen auf diese Art und Weise hosten (SaaS) und ich möchte, dass die Konfiguration außerhalb des eingesetzten Krieges liegt, damit es kein Wartungsproblem wird. Das Teilen einer Datenbankinstanz zwischen Clients ist aus Sicherheitsgründen nicht möglich.

Ich bin sicher, das ist kein einzigartiges Problem für unsere Gruppe. Welche Best Practices oder Lösungen werden von anderen zur Lösung dieses Problems verwendet?

+0

Wenn Sie mehrere eindeutige Instanzen der App ausführen, warum ändern Sie nicht einfach die persistence.xml für die 2. Instanz? – kgrad

+0

Es scheint ein Wartungsproblem zu sein, dies manuell für jede Instanz bei jedem Build zu tun, ich hätte gerne eine automatisierte Lösung. – Vinnie

Antwort

1

Vermutlich ändern Sie die Kopie auch in anderen Dingen? (z. B. Name der EAR-Datei)

Wenn Sie eine Build-Software wie ant oder maven verwenden, können Sie einen Platzhalter in der Datei persistence.xml verwenden und eine andere "Kopie" erstellen, indem Sie einfach andere Build-Parameter verwenden.

z.B. mit Maven

mvn saubere Installation -DmyDatabaseName = db/somedb

+0

OK, das klingt cool. Was muss ich in meine persistence.xml als Platzhalter für die Textersetzung einfügen? – Vinnie

+1

siehe den Kommentar von Pascal unten :-) –

+0

Ich muss eine Lösung finden, wie zu tun, was die ursprüngliche Frage gestellt, wie ich etwa 500 Server an verschiedenen Standorten mit unterschiedlichen Verbindungen verwalten muss. Noch mehr Ideen, als 500 Kriege zu machen, ist nicht gut: S – Vedran

1

würde ich zwei Versionen der Webapp verpacken und eine spezifische Datenquelle im jta-data-source Element ihrer jeweiligen persistence.xml erklären (ich glaube nicht, dass Sie diese Datei externalisieren kann, es wird erwartet, dass in WEB-INF/classes/META-INF/persistence.xml sein) i

+0

Ah, ich habe das befürchtet. Der Aufbau einer einfachen Konfigurationsänderung scheint aus Wartungssicht schmerzhaft, wenn die Anwendung reifer wird, mehr Clients hinzugefügt und neue Versionen veröffentlicht werden (10 Clients bedeuten 10 separate Build- und Deploy-Zyklen mit Änderungen an der Persistenzdatei dazwischen). Ich benutze Maven zum Bauen und Verpacken. Weißt du, ob es ein Maven-Plugin gibt, das in der Lage ist, mehrere Kriege zu erzeugen, wobei das entsprechende Persistenz-XML für jede Konfiguration verwendet wird? – Vinnie

+1

@Vinnie: Ich würde [Filterung und Profile] (http://www.sonatype.com/books/mvnref-book/reference/resource-filtering-sect-description.html) (und lassen Sie meine CI-Engine alle bauen Varianten mit einer Build Matrix). Deklariere etwas wie $ {foo} 'in deiner' persistence.xml' und benutze Maven um den Wert zu filtern. –

2

Update:

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

nicht sicher, ob dies in einem appserver aufgebaut werden kann, aber ich werde es gehen. Das einzige, was mich beunruhigt, ist die Verwaltung des Umfangs. der Behälter verwaltet den Umfang entlang Transaktionsgrenzen

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

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

aber dann, wie Umfang zu verwalten, ist das Problem


2.2.2. Bootstrapping

Die JPA-Spezifikation definiert eine Bootstrap-Prozedur für den Zugriff auf die EntityManagerFactory und den EntityManager. Die Bootstrap-Klasse ist javax.persistence.Persistence, z.B.

Karte configOverrides = new HashMap();

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

EntityManagerFactory programmaticEmf =

Persistence.createEntityManagerFactory("manager1", configOverrides); 

Die erste Version ist mit einer leeren Karte mit dem zweiten Äquivalent.Die Kartenversion ist eine Gruppe von Außerkraftsetzungen, die Vorrang vor allen Eigenschaften haben, die in Ihren persistence.xml-Dateien definiert sind. Alle definierten Eigenschaften in Abschnitt 2.2.1, „Verpackung“ kann auf die createEntityManagerFactory Methode übergeben werden, und es gibt ein paar zusätzliche diejenigen:

* 

    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

Was ist eine persistence.xml im Ordner META-INF der einen Speicher classes Verzeichnis und dann diesen Ordner zuerst im Klassenpfad angeben?

0

Hier ist, was ich in der Lage war, in einer Java-SE-Umgebung zu tun:

Erstellen Sie eine .jar-Datei ohne die persistence.xml Datei . Ich erstellte eine manifest.mf Datei manuell und in der Class-Path: stelle ich "." zusätzlich zu den anderen Einträgen, die ich brauchte.

In dem Verzeichnis, in dem Sie die Software installieren, erstellen Sie ein META-INF Verzeichnis und geben Sie persistence.xml dort ein. Es sollte automatisch abgeholt werden.

z.B.

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