Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I set Datasource when I'm creating Hibernate SessionFactory?

Tags:

I'm creating SessionFactory and I have my datasource as object in code where I'm creating SessionFactory, but i cannot set datasource to Hibernate Configuration object. So how can I set my datasource to my 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();
like image 468
newbie Avatar asked Dec 10 '10 08:12

newbie


3 Answers

If you happen to have your DataSource stored in JNDI, then simply use:

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

But if you use a custom data source provider like Apache DBCP or BoneCP and you don't want to use a dependency injection framework like Spring, then you may inject it on the StandardServiceRegistryBuilder before creating the 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()); 

Note that if you use this approach, you don't need to put the connection parameters in your hibernate.cfg.xml anymore. Here's an example of a compatible hibernate.cfg.xml file when using approach from above:

<?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> 

Code above tested on Hibernate 4.3.

like image 198
Luiggi Mendoza Avatar answered Sep 21 '22 18:09

Luiggi Mendoza


To supply JDBC connections to Session, you need an implementation of ConnectionProvider.

By default, Hibernate uses DatasourceConnectionProvider which obtains a DataSource instance from JNDI.

To use a custom DataSource instance, use InjectedDataSourceConnectionProvider and inject the DataSource instance into it.

There is TODO note on InjectedDataSourceConnectionProvider

NOTE : setDataSource(javax.sql.DataSource) must be called prior to configure(java.util.Properties).

TODO : could not find where setDataSource is actually called. Can't this just be passed in to configure???

As per the note, call setDataSource() method from configure() method.

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);
    }
}

You can also extend UserSuppliedConnectionProvider.

According to the contract of ConnectionProvider

Implementors should provide a public default constructor.

Hibernate will invoke this constructor if custom ConnectionProvider is set through Configuration instance.

Configuration cfg = new Configuration();
Properties props = new Properties();
props.put( Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName() );
cfg.addProperties(props);
like image 33
dira Avatar answered Sep 19 '22 18:09

dira


Luiggi Mendoza's answer is why my search sent me here, but I figure I should give my version because I spent quite some time looking around for how to do this - it sets it up with the Spring in-memory database for testing, a SessionContext and the hbm.xml in case you're not using annotations:

/**
 * 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;
    }

}

and you'll need these:

<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>
like image 35
Adam Avatar answered Sep 19 '22 18:09

Adam