2010-12-10 16 views
18

Estoy creando SessionFactory y tengo mi origen de datos como objeto en el código donde estoy creando SessionFactory, pero no puedo establecer el origen de datos para hibernar el objeto de configuración. Entonces, ¿cómo puedo configurar mi fuente de datos en mi SessionFactory?¿Cómo puedo establecer el origen de datos cuando estoy creando Hibernate SessionFactory?

Configuration configuration = new Configuration(); 
Properties properties = new Properties(); 
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect"); 
configuration.setProperties(properties); 
configuration.setProperty("packagesToScan", "com.my.app"); 
SessionFactory sessionFactory = configuration.configure().buildSessionFactory(); 

Respuesta

13

Suministrar conexiones JDBC a la sesión, necesita una implementación de ConnectionProvider.

Bu predeterminado, Hibernate usa DatasourceConnectionProvider que obtiene una instancia DataSource de JNDI.

Para usar la instancia personalizada DataSource use InjectedDataSourceConnectionProvider, e inyecte la instancia DataSource en ella.

No es TODO nota en InjectedDataSourceConnectionProvider

NOTA: setDataSource (javax.sql.DataSource) debe ser llamado antes de la configure (java.util.Properties).

TODO: no se pudo encontrar dónde se llama realmente setDataSource. ¿No se puede pasar esto solo a configure ???

Según la nota, llame al método setDataSource() desde el método configure().

public class CustomConnectionProvider extends InjectedDataSourceConnectionProvider { 
    @Override 
    public void configure(Properties props) throws HibernateException { 
     org.apache.commons.dbcp.BasicDataSource dataSource = new BasicDataSource(); 
     org.apache.commons.beanutils.BeanUtils.populate(dataSource, props); 
     setDataSource(dataSource); 

     super.configure(props); 
    } 
} 

También puede extender UserSuppliedConnectionProvider.

De acuerdo con el contrato de ConnectionProvider

ejecutores deben proporcionar una constructor público predeterminado.

Hibernate invocará este constructor, si se establece ConnectionProvider personalizado a través de la instancia de configuración.

Configuration cfg = new Configuration(); 
Properties props = new Properties(); 
props.put(Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName()); 
cfg.addProperties(props); 
1

No creo que se pueda. La API de Hibernate le permitirá configurar las propiedades de JDBC para que pueda administrar las conexiones, o puede asignarle una ubicación de JNDI DataSource para que pueda ir a buscarla, pero no creo que pueda otorgarle un DataSource .

En el caso de que esté utilizando Spring, es más fácil: use LocalSessionFactoryBean para configurar Hibernate, e inyecte su DataSource en eso. Spring realiza la magia necesaria en el fondo.

+0

¿tiene algún vínculo a las configuraciones de ejemplo? – newbie

+0

@newbie: ¿Te refieres a la documentación? http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/session-configuration.html – skaffman

+0

Quería decir cómo puedo usar LocalSessionFactoryBean – newbie

2

Si su fuente de datos está limitada en el árbol JNDI:

configuration.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test"); 

De lo contrario, si usted tiene un objeto de origen de datos en el código, que desea utilizar:

java.sql.Connection conn = datasource.getConnection(); 
Session session = sessionFactory.openSession(conn); 

recomendaría la primera uno, para permitir que Hibernate maneje el ciclo de vida de la conexión según sea necesario. En el segundo enfoque, asegúrese de cerrar la conexión cuando ya no la necesite.

+0

¿cómo puedo agregar el origen de datos a JNDI mediante programación? – newbie

+0

¿Estás trabajando en un entorno JEE? En caso afirmativo, sería mejor configurarlo en el contenedor JEE y dejar que maneje la creación y el enlace de la fuente de datos al inicio. –

+0

Pero tengo 1 fuente de datos por cliente, y las fuentes de datos se cargan en el inicio de la aplicación, así que tengo que hacer esto dentro del código. Cada cliente tiene su propio sessionfactory, porque cada cliente tiene su propia base de datos. – newbie

1

Si está utilizando Spring Framework, utilice LocalSessionFactoryBean para inyectar su origen de datos a Hibernate SessionFactory.

<beans> 
    <bean id="YourClass" 
     class="com.YourClass. 
     <property name="sessionFactory"> 
      <ref bean="DbSessionFactory" /> 
     </property>  
    </bean> 


    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
     <property name="driverClassName"> 
      <value>org.postgresql.Driver</value> 
     </property> 
     <property name="url"> 
      <value>jdbc:postgresql://localhost/yourdb</value> 
     </property> 
     <property name="username"> 
      <value>postgres</value> 
     </property> 
     <property name="password"> 
      <value>postgres</value> 
     </property>  
    </bean> 

    <bean id="DbSessionFactory" 
     class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
     <property name="dataSource"> 
      <ref local="dataSource"/> 
     </property>  
     <property name="mappingResources"> 
      <list> 
       <value>conf/hibernate/UserMapping.hbm.xml</value>    
      </list> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect"> org.hibernate.dialect.PostgreSQLDialect </prop>  
       <prop key="hibernate.hbm2ddl.auto">update</prop> 
       <prop key="hibernate.cache.use_second_level_cache"> true </prop> 
       <prop key="hibernate.cache.use_query_cache">true</prop> 
      </props> 
     </property> 
    </bean> 
</beans> 
9

Si le sucede que tiene su DataSource almacenada en JNDI, a continuación, sólo tiene que utilizar:

configuration.setProperty(
    "hibernate.connection.datasource", 
    "java:comp/env/jdbc/yourDataSource"); 

Pero si utiliza un proveedor de fuente de datos personalizados como Apache o DBCP BoneCP y que no quieren utilizar un marco de inyección de dependencias como la primavera, entonces puede inyectarlo en el StandardServiceRegistryBuilder antes de crear el SessionFactory:

//retrieve your DataSource 
DataSource dataSource = ...; 
Configuration configuration = new Configuration() 
    .configure(); 
//create the SessionFactory from configuration 
SessionFactory sf = configuration 
    .buildSessionFactory(
     new StandardServiceRegistryBuilder() 
      .applySettings(configuration.getProperties()) 
      //here you apply the custom dataSource 
      .applySetting(Environment.DATASOURCE, dataSource) 
      .build()); 

Tenga en cuenta que si usa este enfoque, ya no necesita poner los parámetros de conexión en su hibernate.cfg.xml. He aquí un ejemplo de un archivo hibernate.cfg.xml compatibles cuando se utiliza el enfoque desde arriba:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC 
     "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 
<hibernate-configuration> 

    <session-factory> 
     <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> 
     <property name="show_sql">false</property> 
     <!-- your mappings to classes go here --> 
    </session-factory> 
</hibernate-configuration> 

Código anteriormente probado en Hibernate 4.3.

+1

@PeterRader eso es lo que estoy usando: '.applySetting (Environment.DATASOURCE, dataSource)' –

+0

Ah, didnt read full. –

1

Si ha implementado una clase con javax.sql.DataSource, se puede configurar el DataSource de Hibernate configurando las propiedades.

import javax.sql.DataSource; 
public class HibernateDataSource implements DataSource { 
    ... 
} 


import org.hibernate.cfg.Configuration; 
import org.hibernate.cfg.Environment; 
public class MyHibernateCfg { 
    public void initialize() { 
     HibernateDataSource myDataSource = new HibernateDataSource(); 
     Configuration cfg = new Configuration(); 
     // this is how to configure hibernate datasource 
     cfg.getProperties().put(Environment.DATASOURCE, myDataSource); 
     ... 
    } 
} 


import org.hibernate.cfg.Configuration; 
import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 
import org.hibernate.service.ServiceRegistry; 
import org.hibernate.SessionFactory; 
import org.hibernate.Session; 
public class TableClass { 
    public void initialize() { 
     MyHibernateCfg cfg = new MyHibernateCfg(); 
     Configuration conf = cfg.getCfg(); 
     ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build(); 
     SessionFactory sessionFactory = conf.buildSessionFactory(serviceRegistry); 
     Session sessionFactory.openSession(); 
     ... 
    } 
} 
2
respuesta de

Luiggi Mendoza es por qué mi búsqueda me envió aquí, pero me imagino que debo dar mi versión porque pasé mucho tiempo mirando a su alrededor para saber cómo hacer esto - es la configura con el muelle en memoria la base de datos para las pruebas, un SessionContext y la hbm.xml en caso de que no se están usando anotaciones:

/** 
* Instantiates a H2 embedded database and the Hibernate session. 
*/ 
public abstract class HibernateTestBase { 

    private static EmbeddedDatabase dataSource; 
    private static SessionFactory sessionFactory; 
    private Session session; 

    @BeforeClass 
    public static void setupClass() { 
     dataSource = new EmbeddedDatabaseBuilder(). 
       setType(EmbeddedDatabaseType.H2). 
       addScript("file:SQLResources/schema-1.1.sql"). 
       addScript("file:SQLResources/schema-1.2.sql"). 
       build(); 
     Configuration configuration = new Configuration(); 
     configuration.addResource("hibernate-mappings/Cat.hbm.xml"); 
     configuration.setProperty("hibernate.dialect", 
       "org.hibernate.dialect.Oracle10gDialect"); 
     configuration.setProperty("hibernate.show_sql", "true"); 
     configuration.setProperty("hibernate.current_session_context_class", 
       "org.hibernate.context.internal.ThreadLocalSessionContext"); 
     StandardServiceRegistryBuilder serviceRegistryBuilder = 
       new StandardServiceRegistryBuilder(); 
     serviceRegistryBuilder.applySetting(Environment.DATASOURCE, dataSource); 
     serviceRegistryBuilder.applySettings(configuration.getProperties()); 
     StandardServiceRegistry serviceRegistry = 
       serviceRegistryBuilder.build(); 
     sessionFactory = configuration.buildSessionFactory(serviceRegistry); 
     sessionFactory.openSession(); 
    } 

    @AfterClass 
    public static void tearDown() { 
     if (sessionFactory != null) { 
      sessionFactory.close(); 
     } 
     if (dataSource != null) { 
      dataSource.shutdown(); 
     } 
    } 

    @Before 
    public final void startTransaction() { 
     session = sessionFactory.getCurrentSession(); 
     session.beginTransaction(); 
    } 

    @After 
    public final void rollBack() { 
     session.flush(); 
     Transaction transaction = session.getTransaction(); 
     transaction.rollback(); 
    } 

    public Session getSession() { 
     return session; 
    } 

} 

y necesitará los siguientes:

<dependency> 
    <groupId>org.springframework</groupId> 
    <artifactId>spring-jdbc</artifactId> 
    <version>4.1.6.RELEASE</version> 
</dependency> 
<dependency> 
    <groupId>com.h2database</groupId> 
    <artifactId>h2</artifactId> 
    <version>1.4.184</version> 
    <scope>test</scope> 
</dependency> 
0

que utilizan LocalContainerEntityManagerFactoryBean ac Reate la instancia de EntityManagerFactory en la clase de configuración.

Si es necesario establecer otra fuente de datos, de lo que es posible actualizarlo con instancia fábrica gestor de la entidad en tiempo de ejecución:

@Service("myService") 
public class MyService 
{ 
.... 
    @Autowired 
    private LocalContainerEntityManagerFactoryBean emf; 
.... 
    public void replaceDataSource(DataSource dataSource) 
    { 
     emf.setDataSource(dataSource); 
     emf.afterPropertiesSet(); 
    } 
.... 
} 

Funciona con Hibernate 5.2.9 Final.

Cuestiones relacionadas