Set dynamic JPA properties dynamically

Say I have the following persistence.xml with the connection url, user and password, all hardcoded.

Below is the version of Hibernate 3.2. For Hibernate 3.5 ++, we must change "hibernate.connection" to "javax.persistence". But let me ask this question regardless of the literals "hibernate.connection" or "javax.persistence".

<persistence-unit name="obamacare" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="hibernate.archive.autodetection" value="class, hbm"/> <property name="hibernate.connection.driver_class" value="oracle.jdbc.driver.OracleDriver"/> <property name="hibernate.connection.url" value="blah blah blah"/> <property name="hibernate.connection.username" value="careuser"/> <property name="hibernate.connection.password" value="carepass"/> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence> 

However, we need to dynamically set the URL, user and password. There is a proposed authentication server that serves the URL, user, and password. So we don’t need to individually configure myriads of webapps that use some form of jdbc, hibernate or JPA. In addition, the security issue is that you do not want to store / manage passwords in visible text files.

As for JPA, how can I set these JPA properties dynamically? I am looking for two sets of answers:

  • For a JPA vendor independent solution (toplink, eclipselink, hibernate, etc.) - Are there any JPA features that will allow me to dynamically set these three properties?

  • If I am allowed to completely depend on Hibernate, besides the possible JPA prospectus, is there any way to achieve this without using the Spring framework (which seems like a huge monster with tentacles everywhere)

I would be delighted if you also want to throw two cents / dice / rupees in JNDI and how I can use it to replace the functionality of persistence.xml properties. However, this is not a matter of priority.

+8
java hibernate jpa
source share
2 answers

It depends on how you load your EntityManagerFactory. Each of the two specified methods allows you to pass the value of java.util.Map values. It is assumed that these values ​​take precedence over values ​​defined in a constant unit.

There is no problem with the SE approach, since the boot process is usually controlled by your application: javax.persistence.Persistence#createEntityManagerFactory(String puName, Map config . Now you may have problems if something else (ahh, Spring) " Manages EMF for you ...

In the "EE-approach" I do not know a good global approach. This value map still exists at boot time, but the problem is that the EE container is the one that calls this method.

One Hibernate-specific approach that would work anyway would be to replace configuration variables. Thus, on your persistence device, you must define a username or password using ${some.key} , and Hibernate will replace them for you. Whether this will work really depends on how you want to ultimately set these values; Hibernate still needs to access the configuration value named some.key for this to work ...

Another “global approach” ... The “EE Approach” for loading EMF is a container for instantiating javax.persistence.spi.PersistenceProvider and calling its javax.persistence.spi.PersistenceProvider # createContainerEntityManagerFactory. createContainerEntityManagerFactory has an interesting signature here. Essentially, it is passed to javax.persistence.spi.PersistenceUnitInfo, which is an object representation of the analyzed persistence unit plus some other things. An option would be to use this approach for bootstrapping and pass into the javax.persistence.spi.PersistenceUnitInfo instance that you are creating yourself. javax.persistence.spi.PersistenceProvider is an interface. To create an instance, you need to know the provider you want to use, and the FQN to implant them. But this is usually not a problem, as they are pretty well known.

You specifically ask about creating / joining JDBC connections. You have additional features. You may have your "accounting service" creating DataSources, and your JPA provider simply uses this DataSource. All JPA providers support data source lookups through JNDI lookups. In "EE download", DataSource can also be passed to providers for use through PersistenceUnitInfo # getJtaDataSource and / or PersistenceUnitInfo # getNonJtaDataSource. Hibernate takes an instance of the DataSource one at a time instead of the typical DataNource JNDI data name. If you do not want to use a DataSource (for some odd reason), the alternative to Hibernate is to implement the Hibernate ConnectionProvider contract yourself, this is a contract (interface). Hibernate uses to receive and release JDBC connections when necessary. By implementing ConnectionProvider, you can configure basic Connections in any way you like.

Lots of options :)

+7
source share

For your second question, I can only provide a Hibernate solution.

 package dev.stackoverflow; import java.util.Properties; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class DynamicHibernateSessionFactory { public Session setProperties(final String provider, final Boolean excludeUnlisted, final Properties properties) { properties.setProperty("provider", provider); properties.setProperty("exclude-unlisted-classes", excludeUnlisted.toString()); Configuration configuration = new Configuration(); configuration.setProperties(properties); SessionFactory sessionFactory = configuration.configure().buildSessionFactory(); return sessionFactory.openSession(); } } 
+3
source share

All Articles