java如何在Hibernate 4.3.4中配置和获取会话。最终的
我最近将Hibernate的版本升级到了4.3.4。决赛Based on Contextual Sessions configuration of Hibernate this new version is not based on ThreadLocal anymore.如果我到目前为止得到的是正确的,我需要做些什么来提高效率吗?如果不正确,我该怎么办?我不知道
请注意文档中提到:Hibernate提供了三种当前会话跟踪方法。基于“线程”的方法不适用于生产使用;它只对原型设计和类似于本教程的教程有用
冬眠。cfg。xml
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/myDB</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<property name="show_sql">true</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.timeout">300</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.idle_test_period">3000</property>
<!-- <property name="hbm2ddl.auto">update</property>-->
<mapping class="com.myProject.entities.users" />
...
当前配置和代码
基于以上结果和this part of documentationmu当前配置如下 以下内容:
public class HibernateUtil {
private static SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
Configuration configuration = new Configuration();
return configuration.configure()
.buildSessionFactory(
new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.build());
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
代码如下
final Session session = HibernateUtil.getSessionFactory().openSession();
try {
final Transaction tx = session.beginTransaction();
try {
...
以前的配置和代码
public class HibernateUtil {
private static ServiceRegistry serviceRegistry;
private static final ThreadLocal<Session> threadLocal = new ThreadLocal();
private static SessionFactory sessionFactory;
private static SessionFactory configureSessionFactory() {
try {
Configuration configuration = new Configuration();
configuration.configure();
serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.build();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
return sessionFactory;
} catch (HibernateException e) {
System.out.append("** Exception in SessionFactory **");
e.printStackTrace();
}
return sessionFactory;
}
static {
try {
sessionFactory = configureSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateUtil() {
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session getSession() throws HibernateException {
Session session = threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession() : null;
threadLocal.set(session);
}
return session;
}
public static void rebuildSessionFactory() {
try {
sessionFactory = configureSessionFactory();
} catch (Exception e) {
System.err.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
if (session.isOpen()) {
session.close();
}
}
}
}
访问事务和提交命令的代码
final Session session = HibernateUtil.getSession();
try {
final Transaction tx = session.beginTransaction();
try {
//Commands related to query go here
if (!tx.wasCommitted()) {
tx.commit();
}
if (session.isOpen()) {
session.close();
}
return true;
} catch (Exception e) {
tx.rollback();
return false;
}
} finally {
HibernateUtil.closeSession();
}
return false;
# 1 楼答案
我会放弃TreadUtil类,它让我想起了Spring 1.0 Hibernate集成风格。如果你打算转移到Hibernate 4
除了应该依赖Hibernate 4bootstrap机制之外,您的代码还存在以下问题:
会话工厂重建未同步
我不明白为什么需要重建它,因为您从未将其设置为null,会话工厂在静态块中初始化
如果你总是要在HibernateUtil中包装你的Hibernate代码。openSession()try/finally阻塞,在混合业务逻辑和事务逻辑时,会复制大量会话管理逻辑。这打破了单一责任原则
如果您仍然不想让HibernateUtil消失,那么至少可以使用类似于JDBCTemplate的机制,在模板方法中抽象会话/事务管理,同时在可调用文件中提供业务代码,这对您来说可能如下所示:
查看代码表明您希望JDBC资源本地事务使用每请求会话访问习惯用法,这意味着您需要ThreadLocalSessionContext:
额外的
您可以考虑切换到JPA,并将Hibernate属性移动到持久性。xml
# 2 楼答案
只需要在应用程序中访问SessionFactory的一个实例
以下信息来自Hibernate 4.3手册的所有章节2.2. Contextual sessions和 13. Transactions and Concurrency
“SessionFactory是一个创建线程安全对象的成本很高的对象,旨在由所有应用程序线程共享。它通常在应用程序启动时从配置实例创建一次。”
“会话是一种廉价的、非线程安全的对象,应该使用一次,然后丢弃:一个请求、一次对话或一个工作单元。”
如果没有“工作单元”,只有一堆(捆绑的)查询和更新,只需遵循non-managed environment的第一个习惯用法(来自前面提到的第13章)。除非你能证明这会带来性能问题(*),否则不要尝试优化,因为这是root of all evil
如果有“工作单元”或“每个请求的会话”,问题中的
HibernateUtil
可以用org.hibernate.context.internal.ThreadLocalSessionContext
作为CurrentSessionContext
(参见前面提到的第2.2章)替换,并遵循non-managed environment的第二个习惯用法如果使用JTA,用
org.hibernate.context.internal.JTASessionContext
替换ThreadLocalSessionContext
,并遵循Using JTA中描述的习惯用法请注意讨论“工作单元”的章节:软件的良好体系结构取决于对“业务事务”和“应用程序事务”对应用程序意味着什么的充分理解
(*)性能问题可能由配置问题引起,例如this question在Hibernate手册中有相关文档here