创建 Hibernate SessionFactory 时如何设置数据源?
Posted
技术标签:
【中文标题】创建 Hibernate SessionFactory 时如何设置数据源?【英文标题】:How can I set Datasource when I'm creating Hibernate SessionFactory? 【发布时间】:2011-05-23 08:36:16 【问题描述】:我正在创建 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();
【问题讨论】:
【参考方案1】:要为 Session 提供 JDBC 连接,您需要实现 ConnectionProvider。
默认情况下,Hibernate 使用 DatasourceConnectionProvider
,它从 JNDI 获取 DataSource
实例。
要使用自定义DataSource
实例,请使用InjectedDataSourceConnectionProvider
并将DataSource
实例注入其中。
InjectedDataSourceConnectionProvider有TODO注释
注意: setDataSource(javax.sql.DataSource) 必须在之前调用 配置(java.util.Properties)。
TODO : 找不到在哪里 setDataSource 实际上是被调用的。 这不能只是传递给 配置???
按照说明,从configure()
方法调用setDataSource()
方法。
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);
【讨论】:
【参考方案2】:我使用 LocalContainerEntityManagerFactoryBean 在配置类创建 EntityManagerFactory 实例。
如果需要设置另一个数据源,则可以在运行时使用实体管理器工厂实例对其进行更新:
@Service("myService")
public class MyService
....
@Autowired
private LocalContainerEntityManagerFactoryBean emf;
....
public void replaceDataSource(DataSource dataSource)
emf.setDataSource(dataSource);
emf.afterPropertiesSet();
....
它适用于 Hibernate 5.2.9 Final。
【讨论】:
【参考方案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>
【讨论】:
【参考方案4】:如果你用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();
...
【讨论】:
【参考方案5】:如果您碰巧将您的DataSource
存储在 JNDI 中,那么只需使用:
configuration.setProperty(
"hibernate.connection.datasource",
"java:comp/env/jdbc/yourDataSource");
但是,如果您使用像 Apache DBCP 或 BoneCP 这样的自定义数据源提供程序,并且您不想使用像 Spring 这样的依赖注入框架,那么您可以在 StandardServiceRegistryBuilder
之前将其注入创建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());
请注意,如果您使用这种方法,则无需再将连接参数放在您的 hibernate.cfg.xml 中。这是使用上述方法时兼容的 hibernate.cfg.xml 文件的示例:
<?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>
以上代码在 Hibernate 4.3 上测试。
【讨论】:
@PeterRader 这就是我正在使用的:.applySetting(Environment.DATASOURCE, dataSource)
【参考方案6】:
如果您使用的是 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>
【讨论】:
【参考方案7】:如果您的数据源以 JNDI 树为界:
configuration.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test");
否则,如果您在代码中有要使用的 DataSource 对象:
java.sql.Connection conn = datasource.getConnection();
Session session = sessionFactory.openSession(conn);
我会推荐第一个,让 Hibernate 根据需要处理连接生命周期。在第二种方法中,请确保在不再需要连接时关闭它。
【讨论】:
如何以编程方式将数据源添加到 JNDI? 您在 JEE 环境中工作吗?如果是的话,最好在JEE容器上设置,让它在启动时处理数据源的创建和绑定。 但是我每个客户有 1 个数据源,并且数据源是在应用程序启动时加载的,所以我必须在代码中执行此操作。每个客户都有自己的 sessionfactory,因为每个客户都有自己的数据库。 JEE 容器可以处理具有不同 JNDI 名称的多个数据源。当它们都可用时,您只需使用独特的 JNDI 名称来选择所需的名称。无论如何,正如我在回答中所说,如果你真的需要以编程方式设置连接,你可以做到。 显然我无法在 tomcat 上将数据源添加到 JNDI,因为它是只读的。除了 JNDI 还有其他方法可以设置数据源吗?【参考方案8】:我不认为你可以。 Hibernate API 将允许您配置 JDBC 属性以便它可以自己管理连接,或者您可以给它一个 JNDI 数据源位置以便它可以去获取它,但我认为您不能提供 em> 它是一个数据源。
如果您使用 Spring,它会更容易 - 使用 LocalSessionFactoryBean
配置 Hibernate,并将您的 DataSource 注入其中。 Spring 在后台执行必要的魔法。
【讨论】:
你有示例配置的链接吗? @newbie:你的意思是喜欢文档? docs.jboss.org/hibernate/core/3.6/reference/en-US/html/… 我的意思是如何使用 LocalSessionFactoryBean @newbie: static.springsource.org/spring/docs/3.0.x/…以上是关于创建 Hibernate SessionFactory 时如何设置数据源?的主要内容,如果未能解决你的问题,请参考以下文章