Gibt es eine Möglichkeit, ein Jar mit JPA-kommentierten Entitäten in mehr als einer SE-Anwendung wiederzuverwenden (als Abhängigkeit)? <jar-file> in persistence.xml wird in SE-Umgebungen nicht unterstützt, gibt es also eine andere Möglichkeit?
Antworten
Zu viele Anzeigen?Offiziell (laut Spezifikation), müssen Sie alle Klassen mit der Option class
Element . Ich zitiere das Kapitel 6.2.1.6 mapping-file, jar-file, class, exclude-unlisted-classes der JSR-220 :
Anstelle oder zusätzlich zu den JAR-Dateien und Mapping-Dateien kann auch eine Liste von benannten verwalteten Persistenzklassen angegeben werden. Alle Mapping-Metadaten-Annotationen, die zu diesen Klassen gefunden werden, werden verarbeitet, oder sie werden unter Verwendung der Mapping-Annotations-Standardwerte abgebildet. Die
class
Element wird verwendet, um eine verwaltete Persistenzklasse aufzulisten. Eine Liste aller benannten verwalteten Persistenzklassen muss in Java SE-Umgebungen angegeben werden, um die Portabilität zu gewährleisten . Portable Java SE-Anwendungen sollten sich nicht auf die anderen hier beschriebenen Mechanismen verlassen, um die verwalteten Persistenzklassen einer Persistenzeinheit zu spezifizieren. Persistenzanbieter können auch verlangen, dass die Menge der zu verwaltenden Entitätsklassen und Klassen vollständig in jeder derpersistence.xml
Dateien in Java SE-Umgebungen.
Wenn es Ihnen nichts ausmacht, nicht portabel zu sein, können Sie Hibernate unterstützt unter Verwendung der jar-file
Element in Java SE (in diesem Fall wird eine absolute Url benötigt, nicht eine praktische). Hibernate unterstützt die automatische Erkennung sogar in JSE. Viel besser:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="foo">
<!-- This is required to be spec compliant, Hibernate however supports auto-detection even in JSE. -->
<class>foo.Bar<class>
<properties>
<!-- Scan for annotated classes and Hibernate mapping XML files -->
<property name="hibernate.archive.autodetection" value="class, hbm"/>
...
</properties>
</persistence-unit>
</persistence>
Soweit ich weiß, gibt es keine Möglichkeit, die Klassensuche nach Anmerkungen in dieser Konfiguration zum Laufen zu bringen. Sie können jedoch explizit Ihre persistence.xml-Datei auf jede Entitätsklasse verweisen.
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="punit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:/myDS</jta-data-source>
<!-- Must be explicit as classes are in separate jar -->
<class>com.foo.Bar</class>
<class>com.foo.Baz</class>
<properties/>
</persistence-unit>
</persistence>
Nach meiner Erfahrung funktioniert es jetzt.
Wir verwenden: Hibernate3.jar 3.6.0.Final hibernate-jpa-2.0-api-1.0.0.Final.jar
El < jar-datei >Datei:...< /jar-datei > weiß, wie man nach relativen Pfaden sucht - und es funktioniert sowohl für jar-Dateien als auch für Verzeichnisse.
Ich benutze diese Fähigkeit zweimal:
- mit einem Jar, das meine Entitäten enthält - die in mehreren Anwendungen verwendet werden. Jede Anwendung hat ihre eigene persistence.xml - hauptsächlich, um verschiedene ehcache-Einstellungen bereitzustellen.
- Mit Junits möchte ich, dass alle meine Tests in allen anderen abhängigen Projekten eine einzige persistence.xml-Datei haben, die auf alle Entitäten im Entitäten-Projekt verweist. Dann wird die persistence.xml im Entities-Projekt unter test/resources/META-INF gespeichert und verweist auf das Bin-Verzeichnis dieses Projekts: < jar-file >Datei:../entities/bin< /jar-file >
Das war ein Problem, auf das ich gestoßen bin. Es ist etwas schwieriger, da ich mehrere Jars sowohl einzeln als auch als Teil eines Kriegseinsatzes ausführen muss.
Es gibt ein paar Hacks da draußen, die sich entweder um mehrere persistence.xml-Dateien und/oder um einen seltsam anmutenden Versuch zu drehen scheinen, die Jar-Datei mit Hilfe von Spring Resource Loaders zu referenzieren (was bei mir nicht funktionierte).
Mein persönlicher Hack ist die Verwendung von Spring Resource Loaders, um eine Ressource aufzulösen, die in allen Entity-Jars ist, analysieren Sie die URL-Jar-Referenz und verwenden Sie einen Spring Persistence Unit Manager, um diese in das Jar-File-Tag in der virtuellen Persistence.xml zu injizieren
Das ist zwar ein Umweg, vermeidet aber, dass es mehrere persistence.xml gibt - was technisch ungültig ist.
public class SpringPersistenceUnitManager extends DefaultPersistenceUnitManager implements ApplicationContextAware {
private final Logger log = LoggerFactory.getLogger(getClass());
private ApplicationContext ctx = null;
private String jarLocationPattern;
@Override
protected void postProcessPersistenceUnitInfo(MutablePersistenceUnitInfo pui) {
super.postProcessPersistenceUnitInfo(pui);
try {
Resource[] resources = ctx.getResources("classpath*:applicationContext.xml");
for (Resource res : resources) {
String resJar = resolveJar(res.getURL());
if (!resJar.equals(pui.getPersistenceUnitRootUrl().toString())) {
log.info("Adding " + resJar + " to persistence context");
pui.addJarFileUrl(new URL(resJar));
}
}
}
catch (IOException e) {
log.error("error", e);
}
}
private String resolveJar(URL fileInJar) {
String path = fileInJar.getPath();
return path.substring(0, path.indexOf('!'));
}
und den Frühlingskontext:
<util:properties id="hibernate.properties" location="classpath:hibernate.properties" />
<bean id="persistenceUnitManager" class="com.rokksoft.blackice.util.SpringPersistenceUnitManager"
p:defaultDataSource-ref="jdbcDataSourcePool"
/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true"
p:persistenceUnitManager-ref="persistenceUnitManager"
p:persistenceUnitName="blackicePU"
p:dataSource-ref="jdbcDataSourcePool"
p:jpaProperties-ref="hibernate.properties">
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
</bean>
Idealerweise sollten Sie die Jar-Namen filtern - ein 3rd-Party-Jar kann alles Mögliche enthalten.