Erstellen JPA EntityManager ohne persistence.xml Konfigurationsdatei
-
22-09-2019 - |
Frage
Gibt es eine Möglichkeit, die EntityManager
ohne Persistenzeinheit definiert zu initialisieren? Können Sie alle die erforderlichen Eigenschaften geben einen Entity Manager zu schaffen? Ich brauche die EntityManager
aus Anwender angegebenen Werte zur Laufzeit erstellen. die persistence.xml
und Neukompilieren Aktualisierung ist keine Option.
Jede Idee, wie dies zu tun ist mehr als willkommen!
Lösung
Gibt es eine Möglichkeit, die
EntityManager
ohne Persistenzeinheit definiert zu initialisieren?
Sie sollten definieren mindestens ein Persistenzeinheit im persistence.xml
Deployment Descriptor.
Können Sie alle erforderlichen Eigenschaften geben einen
Entitymanager
zu erstellen?
- Das Attribut name ist erforderlich. Die anderen Attribute und Elemente sind optional. (JPA-Spezifikation). So sollte dies mehr oder weniger Ihre minimale
persistence.xml
-Datei:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
SOME_PROPERTIES
</persistence-unit>
</persistence>
In Java EE-Umgebungen, die
jta-data-source
undnon-jta-data-source
Elemente angeben, werden verwendet, um die globalen JNDI Namen des JTA und / oder nicht-JTA Datenquelle durch die Persistenz-Provider verwendet werden.
Also, wenn Ihr Ziel Application Server unterstützt JTA (JBoss, Websphere, Glassfish), Ihre persistence.xml
sieht aus wie:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<!--GLOBAL_JNDI_GOES_HERE-->
<jta-data-source>jdbc/myDS</jta-data-source>
</persistence-unit>
</persistence>
Wenn Ihr Ziel Application Server unterstützt keine JTA (Tomcat), Ihr persistence.xml
sieht aus wie:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<!--GLOBAL_JNDI_GOES_HERE-->
<non-jta-data-source>jdbc/myDS</non-jta-data-source>
</persistence-unit>
</persistence>
Wenn Ihre Datenquelle ist nicht auf einen globalen JNDI gebunden (zB außerhalb eines Java EE-Container), so würden Sie in der Regel JPA-Provider definieren, Treiber, URL, Benutzer und Passwort Eigenschaften. Aber Eigenschaftsname ist abhängig von den JPA-Provider. Also, für Hibernate als JPA-Provider, Ihre persistence.xml
Datei wird aussieht wie:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>br.com.persistence.SomeClass</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="hibernate.connection.url" value="jdbc:derby://localhost:1527/EmpServDB;create=true"/>
<property name="hibernate.connection.username" value="APP"/>
<property name="hibernate.connection.password" value="APP"/>
</properties>
</persistence-unit>
</persistence>
Transaktionsart Attribut
In der Regel in Java EE-Umgebungen, eine transaktions Art von
RESOURCE_LOCAL
geht davon aus, dass eine nicht-JTA-Datenquelle zur Verfügung gestellt wird. In einer Umgebung mit Java EE, wenn dieses Element nicht angegeben ist, ist die Standard-JTA. In einer Umgebung mit Java SE, wenn dieses Element nicht angegeben ist, kann ein Ausfall vonRESOURCE_LOCAL
übernommen werden.
- Um die Portabilität einer Java SE-Anwendung zu gewährleisten, ist es notwendig, explizit Liste die Persistenz Klassen verwaltet, die in der Persistenzeinheit (JPA-Spezifikation) enthalten sind
Ich brauche die
EntityManager
aus Anwender angegebenen Werte zur Laufzeit erstellen
diese So verwenden:
Map addedOrOverridenProperties = new HashMap();
// Let's suppose we are using Hibernate as JPA provider
addedOrOverridenProperties.put("hibernate.show_sql", true);
Persistence.createEntityManagerFactory(<PERSISTENCE_UNIT_NAME_GOES_HERE>, addedOrOverridenProperties);
Andere Tipps
Ja, Sie können ohne eine XML-Datei zu verwenden, wie dies in einer @Configuration Klasse mit Feder (oder dessen Äquivalent Feder Config xml):
@Bean
public LocalContainerEntityManagerFactoryBean emf(){
properties.put("javax.persistence.jdbc.driver", dbDriverClassName);
properties.put("javax.persistence.jdbc.url", dbConnectionURL);
properties.put("javax.persistence.jdbc.user", dbUser); //if needed
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceProviderClass(org.eclipse.persistence.jpa.PersistenceProvider.class); //If your using eclipse or change it to whatever you're using
emf.setPackagesToScan("com.yourpkg"); //The packages to search for Entities, line required to avoid looking into the persistence.xml
emf.setPersistenceUnitName(SysConstants.SysConfigPU);
emf.setJpaPropertyMap(properties);
emf.setLoadTimeWeaver(new ReflectiveLoadTimeWeaver()); //required unless you know what your doing
return emf;
}
Ich konnte einen EntityManager
mit Hibernate und PostgreSQL rein mit Hilfe von Java-Code (mit einer Spring-Konfiguration) den folgenden erstellen:
@Bean
public DataSource dataSource() {
final PGSimpleDataSource dataSource = new PGSimpleDataSource();
dataSource.setDatabaseName( "mytestdb" );
dataSource.setUser( "myuser" );
dataSource.setPassword("mypass");
return dataSource;
}
@Bean
public Properties hibernateProperties(){
final Properties properties = new Properties();
properties.put( "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect" );
properties.put( "hibernate.connection.driver_class", "org.postgresql.Driver" );
properties.put( "hibernate.hbm2ddl.auto", "create-drop" );
return properties;
}
@Bean
public EntityManagerFactory entityManagerFactory( DataSource dataSource, Properties hibernateProperties ){
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource( dataSource );
em.setPackagesToScan( "net.initech.domain" );
em.setJpaVendorAdapter( new HibernateJpaVendorAdapter() );
em.setJpaProperties( hibernateProperties );
em.setPersistenceUnitName( "mytestdomain" );
em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
em.afterPropertiesSet();
return em.getObject();
}
Der Aufruf von LocalContainerEntityManagerFactoryBean.afterPropertiesSet()
ist wesentlich , da sonst die Fabrik nie gebaut wird, und dann getObject()
kehrt null
und Sie jagen nach NullPointerException
s den ganzen Tag lang. >: - (
Es dann mit dem folgenden Code gearbeitet:
PageEntry pe = new PageEntry();
pe.setLinkName( "Google" );
pe.setLinkDestination( new URL( "http://www.google.com" ) );
EntityTransaction entTrans = entityManager.getTransaction();
entTrans.begin();
entityManager.persist( pe );
entTrans.commit();
Wo meine Einheit wurde diese:
@Entity
@Table(name = "page_entries")
public class PageEntry {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String linkName;
private URL linkDestination;
// gets & setters omitted
}
Hier ist eine Lösung ohne Frühling.
Konstanten werden von org.hibernate.cfg.AvailableSettings
genommen:
entityManagerFactory = new HibernatePersistenceProvider().createContainerEntityManagerFactory(
archiverPersistenceUnitInfo(),
ImmutableMap.<String, Object>builder()
.put(JPA_JDBC_DRIVER, JDBC_DRIVER)
.put(JPA_JDBC_URL, JDBC_URL)
.put(DIALECT, Oracle12cDialect.class)
.put(HBM2DDL_AUTO, CREATE)
.put(SHOW_SQL, false)
.put(QUERY_STARTUP_CHECKING, false)
.put(GENERATE_STATISTICS, false)
.put(USE_REFLECTION_OPTIMIZER, false)
.put(USE_SECOND_LEVEL_CACHE, false)
.put(USE_QUERY_CACHE, false)
.put(USE_STRUCTURED_CACHE, false)
.put(STATEMENT_BATCH_SIZE, 20)
.build());
entityManager = entityManagerFactory.createEntityManager();
Und die berüchtigten PersistenceUnitInfo
private static PersistenceUnitInfo archiverPersistenceUnitInfo() {
return new PersistenceUnitInfo() {
@Override
public String getPersistenceUnitName() {
return "ApplicationPersistenceUnit";
}
@Override
public String getPersistenceProviderClassName() {
return "org.hibernate.jpa.HibernatePersistenceProvider";
}
@Override
public PersistenceUnitTransactionType getTransactionType() {
return PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
@Override
public DataSource getJtaDataSource() {
return null;
}
@Override
public DataSource getNonJtaDataSource() {
return null;
}
@Override
public List<String> getMappingFileNames() {
return Collections.emptyList();
}
@Override
public List<URL> getJarFileUrls() {
try {
return Collections.list(this.getClass()
.getClassLoader()
.getResources(""));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
@Override
public URL getPersistenceUnitRootUrl() {
return null;
}
@Override
public List<String> getManagedClassNames() {
return Collections.emptyList();
}
@Override
public boolean excludeUnlistedClasses() {
return false;
}
@Override
public SharedCacheMode getSharedCacheMode() {
return null;
}
@Override
public ValidationMode getValidationMode() {
return null;
}
@Override
public Properties getProperties() {
return new Properties();
}
@Override
public String getPersistenceXMLSchemaVersion() {
return null;
}
@Override
public ClassLoader getClassLoader() {
return null;
}
@Override
public void addTransformer(ClassTransformer transformer) {
}
@Override
public ClassLoader getNewTempClassLoader() {
return null;
}
};
}
Mit Klar JPA, unter der Annahme, dass Sie eine PersistenceProvider
Implementierung (zB Hibernate), können Sie verwenden, um die PersistenceProvider # createContainerEntityManagerFactory (PersistenceUnitInfo Info, Karte map) Methode eine EntityManagerFactory
Bootstrap ohne zu benötigen persistence.xml
.
Allerdings ist es ärgerlich, dass Sie die PersistenceUnitInfo
Schnittstelle zu implementieren, so dass Sie besser dran mit Spring oder Hibernate, die sowohl Unterstützung Bootstrapping JPA ohne persistence.xml
-Datei:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
this.persistenceUnitInfo,
getJpaPropertyMap()
);
Wenn die PersistenceUnitInfo implementiert durch die Federspezifische Klasse.
Schauen Sie sich diesem Artikel für ein schönes Beispiel dafür, wie Sie dieses Ziel mit Hibernate erreichen können.
Datanucleus JPA, dass ich auch eine Art und Weise, dies zu tun? in seiner docs . Keine Notwendigkeit für Frühling, oder hässliche Umsetzung PersistenceUnitInfo
.
Einfach Sie folgt als
import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.api.jpa.JPAEntityManagerFactory;
PersistenceUnitMetaData pumd = new PersistenceUnitMetaData("dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("mydomain.test.A");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.persistence.jdbc.url", "jdbc:h2:mem:nucleus");
pumd.addProperty("javax.persistence.jdbc.user", "sa");
pumd.addProperty("javax.persistence.jdbc.password", "");
pumd.addProperty("datanucleus.schema.autoCreateAll", "true");
EntityManagerFactory emf = new JPAEntityManagerFactory(pumd, null);