Gibt es eine Möglichkeit, die EntityManager
ohne definierte Persistenzeinheit zu initialisieren ?
Sie sollten mindestens eine Persistenzeinheit im persistence.xml
Bereitstellungsdeskriptor definieren.
Können Sie alle erforderlichen Eigenschaften angeben, um eine zu erstellen Entitymanager
?
- Das Namensattribut ist erforderlich. Die anderen Attribute und Elemente sind optional. (JPA-Spezifikation). Das sollte also mehr oder weniger Ihre minimale
persistence.xml
Datei sein:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
SOME_PROPERTIES
</persistence-unit>
</persistence>
In Java EE-Umgebungen werden die Elemente jta-data-source
und non-jta-data-source
verwendet, um den globalen JNDI-Namen der JTA- und / oder Nicht-JTA-Datenquelle anzugeben, die vom Persistenzanbieter verwendet werden soll.
Wenn Ihr Zielanwendungsserver JTA (JBoss, Websphere, GlassFish) unterstützt, persistence.xml
sieht es folgendermaßen aus:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<jta-data-source>jdbc/myDS</jta-data-source>
</persistence-unit>
</persistence>
Wenn Ihr Zielanwendungsserver JTA (Tomcat) nicht unterstützt, persistence.xml
sieht es folgendermaßen aus:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
<non-jta-data-source>jdbc/myDS</non-jta-data-source>
</persistence-unit>
</persistence>
Wenn Ihre Datenquelle nicht an eine globale JNDI gebunden ist (z. B. außerhalb eines Java EE-Containers), definieren Sie normalerweise die Eigenschaften von JPA-Anbieter, Treiber, URL, Benutzer und Kennwort. Der Name der Eigenschaft hängt jedoch vom JPA-Anbieter ab. Für Hibernate als JPA-Anbieter persistence.xml
sieht Ihre Datei also folgendermaßen aus:
<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>
Transaktionstypattribut
In Java EE-Umgebungen wird bei einem Transaktionstyp im Allgemeinen RESOURCE_LOCAL
davon ausgegangen, dass eine Nicht-JTA-Datenquelle bereitgestellt wird. Wenn in einer Java EE-Umgebung dieses Element nicht angegeben ist, ist der Standardwert JTA. Wenn in einer Java SE-Umgebung dieses Element nicht angegeben ist, kann ein Standardwert von RESOURCE_LOCAL
angenommen werden.
- Um die Portabilität einer Java SE-Anwendung sicherzustellen, müssen die verwalteten Persistenzklassen, die in der Persistenzeinheit enthalten sind (JPA-Spezifikation) , explizit aufgelistet werden.
Ich muss die zur EntityManager
Laufzeit aus den vom Benutzer angegebenen Werten erstellen
Verwenden Sie also Folgendes:
Map addedOrOverridenProperties = new HashMap();
addedOrOverridenProperties.put("hibernate.show_sql", true);
Persistence.createEntityManagerFactory(<PERSISTENCE_UNIT_NAME_GOES_HERE>, addedOrOverridenProperties);
Ja, Sie können ohne Verwendung einer XML-Datei mit spring wie diesem in einer @ Configuration-Klasse (oder der entsprechenden Spring-Konfigurations-XML) Folgendes tun:
@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; }
quelle
properties
?Hier ist eine Lösung ohne Frühling. Konstanten werden entnommen aus
org.hibernate.cfg.AvailableSettings
: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 das berüchtigte
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; } }; }
quelle
Ich konnte
EntityManager
mit Hibernate und PostgreSQL ausschließlich mit Java-Code (mit einer Spring-Konfiguration) Folgendes 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 Anruf bei
LocalContainerEntityManagerFactoryBean.afterPropertiesSet()
ist wichtig, da sonst die Fabrik nie gebaut wird und danngetObject()
zurückkehrtnull
und Sie denNullPointerException
ganzen Tag hinterher jagen . > :-(Es funktionierte dann mit folgendem Code:
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 Entität war 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 }
quelle
Mit einfachem JPA können Sie unter der Annahme, dass Sie eine
PersistenceProvider
Implementierung haben (z. B. Hibernate), die PersistenceProvider # createContainerEntityManagerFactory-Methode (PersistenceUnitInfo info, Map map) verwenden, um eineEntityManagerFactory
zu booten, ohne eine zu benötigenpersistence.xml
.Es ist jedoch ärgerlich, dass Sie die
PersistenceUnitInfo
Schnittstelle implementieren müssen , sodass Sie besser Spring oder Hibernate verwenden sollten, die beide das Bootstrapping von JPA ohnepersistence.xml
Datei unterstützen:this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory( this.persistenceUnitInfo, getJpaPropertyMap() );
Wobei die PersistenceUnitInfo von der Spring-spezifischen MutablePersistenceUnitInfo- Klasse implementiert wird .
In diesem Artikel erfahren Sie, wie Sie dieses Ziel mit Hibernate erreichen können.
quelle
MutablePersistenceUnitInfo
funktioniert nicht, da einige Methoden UnsupportedOperationException auslösen . Auch der erwähnte Artikel ist etwas veraltet:getPersistenceUnitRootUrl
Kann nicht null zurückgeben, sonst scannt Hibernate den Klassenpfad nicht (Hibernate 5.2.8).getPersistenceUnitRootUrl
oder implementiert werdengetJarFileUrls
. LetzteresDataNucleus JPA, das ich verwende, hat auch eine Möglichkeit, dies in seinen Dokumenten zu tun . Keine Notwendigkeit für Frühling oder hässliche Implementierung von
PersistenceUnitInfo
.Gehen Sie einfach wie folgt vor
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);
quelle
Sie können einen EntityManager auch mithilfe von PersistenceContext oder Autowired Annotation abrufen. Beachten Sie jedoch, dass er nicht threadsicher ist.
@PersistenceContext private EntityManager entityManager;
quelle