Créer JPA EntityManager sans persistance.fichier de configuration xml
Est-il un moyen d'initialiser le EntityManager
sans une unité de persistance? Pouvez-vous donner toutes les propriétés requises pour créer un gestionnaire d'entité? Je dois créer le EntityManager
à partir des valeurs spécifiées par l'utilisateur à l'exécution. Mettre à jour le persistence.xml
et recompiler n'est pas une option.
toute idée sur la façon de faire ceci est plus que bienvenu!
5 réponses
Est-il un moyen d'initialiser le
EntityManager
sans une unité de persistance?
vous devez définir au moins une unité de persistance dans le descripteur de déploiement persistence.xml
.
pouvez-vous donner toutes les propriétés nécessaires pour créer un
Entitymanager
?
- l'attribut name est requis. Les autres les attributs et les éléments sont optionnels. (Spécification JPA). Donc ceci devrait être plus ou moins votre fichier minimal
persistence.xml
:
<persistence>
<persistence-unit name="[REQUIRED_PERSISTENCE_UNIT_NAME_GOES_HERE]">
SOME_PROPERTIES
</persistence-unit>
</persistence>
dans les environnements Java EE, les éléments
jta-data-source
etnon-jta-data-source
sont utilisés pour spécifier le nom JNDI global de la source de données JTA et/ou non-JTA qui doit être utilisé par le fournisseur de la persistance.
donc si votre serveur d'Application cible prend en charge JTA( JBoss, Websphere, GlassFish), votre persistence.xml
ressemble à:
<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>
si votre serveur d'Application cible ne supporte pas JTA (Tomcat), votre persistence.xml
ressemble à:
<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>
si votre source de données n'est pas liée à un JNDI global (par exemple, en dehors d'un conteneur Java EE), vous définiriez généralement JPA provider, driver, url, user et password properties. mais le nom de la propriété dépend de fournisseur JPA. Donc, pour L'hibernation en tant que fournisseur de JPA, votre fichier persistence.xml
ressemblera à:
<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>
Attribut Du Type De Transaction
en général, dans les environnements Java EE, un type de transaction
RESOURCE_LOCAL
suppose qu'une source de données non JTA sera fournie. Dans un environnement Java EE, si cet élément n'est pas spécifié, la valeur par défaut est JTA. Dans un environnement Java SE, si cet élément n'est pas spécifié, une valeur par défaut deRESOURCE_LOCAL
peut être supposé.
- pour assurer la portabilité d'une application Java SE, il est nécessaire d'énumérer explicitement les classes gérées de persistance qui sont incluses dans l'Unité de persistance (spécification JPA)
je dois créer le
EntityManager
à partir des valeurs spécifiées par l'utilisateur à l'exécution
alors utilisez ceci:
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);
Oui vous pouvez sans utiliser n'importe quel fichier xml en utilisant le ressort comme ceci dans une classe @Configuration (ou son équivalent XML de config de ressort):
@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;
}
j'ai pu créer un EntityManager
avec hibernation et PostgreSQL en utilisant uniquement le code Java (avec une configuration à ressort) comme suit:
@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();
}
l'appel à LocalContainerEntityManagerFactoryBean.afterPropertiesSet()
est essentiel car autrement l'usine ne se construit jamais, puis getObject()
retourne null
et vous chassez après NullPointerException
s toute la journée. > :- (
il a ensuite travaillé avec le code suivant:
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();
où mon entité était:
@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
}
Voici une solution sans ressort.
Les constantes sont tirées de 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();
et l'infâme 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;
}
};
}
avec simple JPA, en supposant que vous avez une implémentation PersistenceProvider
(par ex. Hibernate), vous pouvez utiliser la méthode PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) pour bootstrap un EntityManagerFactory
sans avoir besoin d'un persistence.xml
.
cependant, il est ennuyeux que vous ayez à mettre en œuvre l'interface PersistenceUnitInfo
, donc vous êtes mieux d'utiliser le ressort ou L'hibernation qui les deux soutiennent bootstrapping JPA sans un persistence.xml
fichier:
this.nativeEntityManagerFactory = provider.createContainerEntityManagerFactory(
this.persistenceUnitInfo,
getJpaPropertyMap()
);
où le Persistenence Unitinfo est mis en œuvre par le ressort spécifique Mutablepersistence Unitinfo classe.
Check out cet article pour une belle démonstration de la façon dont vous pouvez atteindre cet objectif avec mise en veille prolongée.