在创建Hibernate SessionFactory时如何设置Datasource?

时间:2010-12-10 08:28:28

标签: java hibernate sessionfactory

我正在创建SessionFactory,我在我创建SessionFactory的代码中将数据源作为对象,但是我无法将数据源设置为Hibernate Configuration对象。那么如何将我的数据源设置为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();

8 个答案:

答案 0 :(得分:14)

要向Session提供JDBC连接,您需要实现ConnectionProvider

默认情况下,Hibernate使用DatasourceConnectionProvider从JNDI获取DataSource实例。

要使用自定义DataSource实例,请使用InjectedDataSourceConnectionProvider并将DataSource实例注入其中。

InjectedDataSourceConnectionProvider

上有TODO注释
  

注意:   的setDataSource(javax.sql.DataSource中)   必须先调用   配置(java.util.Properties)。

     

TODO:找不到哪里   实际上调用了setDataSource。   不能这只是传递给   配置???

根据说明,请从setDataSource()方法调用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);
    }
}

您还可以展开UserSuppliedConnectionProvider

根据ConnectionProvider的合约

  

执行者应该提供公众   默认构造函数。

如果通过Configuration实例设置自定义ConnectionProvider,Hibernate将调用此构造函数。

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

答案 1 :(得分:9)

如果您恰好将DataSource存储在JNDI中,那么只需使用:

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

但是如果您使用自定义数据源提供程序(如Apache DBCP或BoneCP)和您不想使用像Spring这样的依赖注入框架,那么您可以将其注入{{1}在创建StandardServiceRegistryBuilder

之前
SessionFactory

请注意,如果使用此方法,则无需再将连接参数放在hibernate.cfg.xml中。以下是使用上述方法时兼容的hibernate.cfg.xml文件的示例:

//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());

上面的代码在Hibernate 4.3上测试过。

答案 2 :(得分:3)

Luiggi Mendoza的回答是为什么我的搜索发送给我的原因,但我认为我应该提供我的版本,因为我花了很长时间四处寻找如何做到这一点 - 它用Spring内存设置它用于测试的数据库,SessionContext和hbm.xml,以防您不使用注释:

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

}

你需要这些:

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

答案 3 :(得分:2)

如果您的数据源在JNDI树中有界:

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

否则,如果您要在代码中使用DataSource对象:

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

我建议第一个,让Hibernate根据需要处理连接生命周期。在第二种方法中,确保在不再需要时关闭连接。

答案 4 :(得分:1)

我认为你不能。 Hibernate API将允许您配置JDBC属性,以便它可以自己管理连接,或者您可以为它提供一个JNDI DataSource位置,以便它可以去获取它,但我认为您不能给 em>它是一个DataSource。

如果你正在使用Spring,那就更容易 - 使用LocalSessionFactoryBean来配置Hibernate,并将你的DataSource注入其中。 Spring在后台执行必要的魔术。

答案 5 :(得分:1)

如果您使用的是Spring框架,那么请使用LocalSessionFactoryBean将数据源注入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>

答案 6 :(得分:1)

如果您使用javax.sql.DataSource实现了一个类,则可以通过配置属性来设置Hibernate的DataSource

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

答案 7 :(得分:0)

我使用LocalContainerEntityManagerFactoryBean在配置类中创建EntityManagerFactory实例。

如果需要设置另一个DataSource,那么可以在运行时使用实体管理器工厂实例更新它:

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

适用于Hibernate 5.2.9 Final。