2012-07-27 12 views
8

Digamos que tengo los siguientes persistence.xml con la url de conexión, todo codificado por el usuario & contraseña.Configuración de las propiedades de persistencia JPA dinámicamente

La siguiente es para Hibernate 3.2. Para Hibernate 3.5 ++, tenemos que cambiar "hibernate.connection" por "javax.persistence". Pero permítanme hacer esta pregunta independientemente de los literales "hibernate.connection" o "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> 

Sin embargo, tenemos que establecer la dirección URL, el usuario & contraseña de forma dinámica. Hay un servidor de autenticación propuesto, que sirve a la URL, el usuario & contraseña. De manera que no es necesario configurar individualmente las miríadas de aplicaciones web que utilizan algún tipo de JDBC, hibernación o APP. Además del problema de seguridad de no querer almacenar/administrar contraseñas en archivos de texto visibles.

En lo que se refiere a la APP, ¿cómo puedo establecer estas propiedades de la APP de forma dinámica? Estoy buscando a dos conjuntos de respuestas:

  1. Para una solución que es JPA proveedor independiente (vínculo superior, EclipseLink, hibernación, etc.) - ¿Hay alguna funcionalidad APP que me permitiera establecer estas tres propiedades de forma dinámica?

  2. Si se me permite depender totalmente de Hibernate, además de la posible única ruta JPA, ¿hay alguna manera de lograr esto sin incluir el marco Spring (que parece una enorme monstruosidad con tentáculos por todas partes)?

estaría eufórico si también desea lanzar en dos centavos/Quids/rupias en JNDI y cómo podría utilizarlo para reemplazar la funcionalidad de las propiedades persistence.xml. Sin embargo, esa no es la prioridad de la pregunta.

+1

La mayoría de las cosas que desea lograr se pueden hacer fácilmente con Spring. Estoy usando Spring por unas semanas y no me arrepiento del cambio. La primavera parece una gran carga de trabajo, pero en realidad es bastante fácil. – siebz0r

Respuesta

7

Depende de cómo arranque su EntityManagerFactory. Los 2 métodos definidos por cada especificación le permiten pasar un java.util.Mapa de valores. Se supone que estos valores tienen prioridad sobre los valores definidos en la unidad de persistencia.

En el "enfoque de ES" no hay problema ya que el proceso de arranque se controla típicamente por su aplicación: javax.persistence.Persistence#createEntityManagerFactory(String puName, Map config. Ahora puede tener problemas aquí si algo más (ejem, Spring) está "administrando" el EMF para usted ...

En el "enfoque EE", no estoy al tanto de un buen enfoque global. Este Mapa de valores todavía existe en el arranque, pero el problema es que el contenedor EE es el que llama a este método.

enfoque

Uno de hibernación específica que funcionaría en cualquier caso sería utilizar config sustitución variable. Por lo tanto, en su unidad de persistencia debe definir el nombre de usuario o la contraseña utilizando ${some.key} e Hibernate los reemplazará por usted. Si esto funcionará realmente depende de cómo quiera establecer estos valores en última instancia; Hibernate aún necesita acceso a un valor de configuración llamado some.key para que esto funcione ...

Otro "enfoque global" ... El "enfoque EE" para arrancar el EMF es para que el contenedor cree una instancia de javax.persistence. spi.PersistenceProvider y llame a su javax.persistence.spi.PersistenceProvider # createContainerEntityManagerFactory. createContainerEntityManagerFactory tiene una firma interesante aquí. Esencialmente se pasa un javax.persistence.spi.PersistenceUnitInfo que es una representación de objeto de la unidad de persistencia analizada más algunas otras cosas. Una opción sería usar este enfoque para arrancar y pasar una instancia de javax.persistence.spi.PersistenceUnitInfo que construyas tú mismo. javax.persistence.spi.PersistenceProvider es una interfaz. Para instanciarlo, necesitaría conocer el proveedor que desea usar y el FQN a su impl. Pero eso no suele ser un problema ya que estos son bastante conocidos.

Usted está preguntando específicamente sobre la creación/agrupación de conexiones JDBC. Tienes opciones adicionales allí específicamente. Podría hacer que su "servicio de credenciales" cree DataSources y su proveedor de JPA simplemente use ese DataSource. Todos los proveedores de JPA admiten la localización de DataSources a través de la búsqueda JNDI. En "EE bootstrapping", los proveedores también pueden pasar un DataSource para usar a través de PersistenceUnitInfo # getJtaDataSource y/o PersistenceUnitInfo # getNonJtaDataSource. Hibernate acepta alternativamente una instancia de DataSource en lugar de la configuración de nombre JNDI de DataSource típica. Si no desea utilizar DataSource (por alguna extraña razón), una alternativa específica de Hibernate es implementar usted mismo el contrato ConnectionProvider de Hibernate, este es el contrato (interfaz) que Hibernate utiliza para obtener y liberar conexiones JDBC cuando lo necesita. Al implementar ConnectionProvider, puede configurar las conexiones subyacentes de la forma que desee.

Muchas opciones :)

+0

Otro "enfoque global" ... El "enfoque de EE" para arrancar el EMF es crear una instancia del javax.persistence.spi.PersistenceProvider y llamar a su javax.persistence.spi.PersistenceProvider # createContainerEntityManagerFactory. createContainerEntityManagerFactory tiene una firma interesante aquí. Esencialmente se pasa una javax.persistence.spi.PersistenceUnitInfo que es una representación de objeto de la unidad de persistencia analizada más algunas otras cosas. La opción sería usar este enfoque para arrancar y pasar el javax.persistence.spi.PersistenceUnitInfo que construyas tú mismo –

+0

Se quedó sin espacio en el último comentario :) javax.persistence.spi.PersistenceProvider es una interfaz. Para instanciarlo, necesitaría conocer el proveedor que desea usar y el FQN a su impl. Pero eso no suele ser un problema ya que estos son bastante conocidos. –

+0

Steve, gracias por tu esfuerzo. ¿Hubiera alguna posibilidad de que pudieras transferir tus comentarios al área de respuesta? El método de sustitución $ {some.key} es exactamente lo que estoy buscando. ¿Podría darme un ejemplo de cómo hacerlo en persistence.xml de hibernate? Debido a que nuestra caja de producción es jboss 4.x, tenemos que usar hibernate 3.2 en lugar de hibernate 3.6, por lo que no son aplicables características de hibernación mucho más nuevas. –

3

Para su segunda pregunta que pueda proporcionar una Hibernate-única solución.

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(); 
    } 
} 
Cuestiones relacionadas