java 升级到 Hibernate 4.1 和“臭名昭著的”HibernateTemplate
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12158294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Upgrading to Hibernate 4.1 and the "infamous" HibernateTemplate
提问by Ido.Co
I'm upgrading our project from Hibernate 3.0 to Hibernate 4.1.6. (And we are currently using spring 3.1)
我正在将我们的项目从 Hibernate 3.0 升级到 Hibernate 4.1.6。(我们目前使用的是 spring 3.1)
I read in many articles and in HibernateTemplate documentation, that since version 4.0 HibernateTemplate is not supported and that I should replace it's usage with calling sessionFactory.getCurrentSession()
to get a session.
我在很多文章和 HibernateTemplate 文档中都读到过,因为不支持 4.0 版的 HibernateTemplate,所以我应该用调用sessionFactory.getCurrentSession()
来获取会话来替换它的用法。
Since this project was started with older version of Hibernate, where the use of HibernateTemplate
was encouraged, we currently have 124 usages of HibernateTemplate
across our project. I'm afraid that replacing all these occurrences with sessionFactory.getCurrentSession()
might insert regression bugs in our project. In addition, there are some places where HibernateTemplate
was used in a non-transactional context, where there is no 'current' session. What should I do in those cases? Open a new session and handle (close) it myself? That wasn't the case when I used HibernateTemplate
.
由于这个项目是从旧版本的 Hibernate 开始的,HibernateTemplate
鼓励使用,我们目前在HibernateTemplate
整个项目中有 124 次使用。恐怕将所有这些事件替换为sessionFactory.getCurrentSession()
可能会在我们的项目中插入回归错误。此外,有些地方在HibernateTemplate
非事务性上下文中使用,没有“当前”会话。在这些情况下我该怎么办?打开一个新会话并自己处理(关闭)它?当我使用HibernateTemplate
.
Do you have some good strategy addressing these issues?
您有解决这些问题的好策略吗?
Thanks.
谢谢。
Relevant reading:
相关阅读:
采纳答案by Ido.Co
Okay, So this is what I actually did, I don't know if this is the best solution for this problem, but under our circumstances, and since I was looking for the most localized solution, it seemed best to me.
好的,这就是我实际做的,我不知道这是否是这个问题的最佳解决方案,但在我们的情况下,由于我正在寻找最本地化的解决方案,对我来说似乎是最好的。
I have extended the springframework.orm.hibernate3.HibernateTemplate and created a new MyHibernateTemplate. The new template's main role is to override the doExecute method that most of the hibernate3.HibernateTemplate eventually lead to, and also supply some of the functionality that was provided by the old SessionFactoryUtils (like isSessionTransactional and applyTransactionTimeout).
我扩展了 springframework.orm.hibernate3.HibernateTemplate 并创建了一个新的 MyHibernateTemplate。新模板的主要作用是覆盖大多数 hibernate3.HibernateTemplate 最终导致的 doExecute 方法,并且还提供了旧 SessionFactoryUtils 提供的一些功能(如 isSessionTransactional 和 applyTransactionTimeout)。
The new doExecute replicates the logic of the old one, but instead of SessionFactoryUtils.getNewSession to get a session it first try to look for an open session getSessionFactory().getCurrentSession() :
新的 doExecute 复制了旧的逻辑,但不是 SessionFactoryUtils.getNewSession 来获取会话,它首先尝试查找打开的会话 getSessionFactory().getCurrentSession() :
boolean newSessionOpened = false;
Session session;
if (enforceNewSession){
session = SessionFactoryUtils.openSession(getSessionFactory());
newSessionOpened = true;
} else {
try {
// look for an open session
session = getSessionFactory().getCurrentSession();
}
catch (HibernateException ex) {
try {
// if there isn't an open session, open one yourself
session = getSessionFactory().openSession();
newSessionOpened = true;
} catch (HibernateException e) {
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
}
}
}
// is the open session, is a session in a current transaction?
boolean existingTransaction = (!enforceNewSession &&
(!isAllowCreate() || isSessionTransactional(session, getSessionFactory())));
You just need to close this session manually:
您只需要手动关闭此会话:
finally {
// if session was used in an existing transaction restore old settings
if (existingTransaction) {
//logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}
}
// if not and a new session was opened close it
else {
// Never use deferred close for an explicitly new Session.
if (newSessionOpened) {
SessionFactoryUtils.closeSession(session);
//_log.info("Closing opened Hibernate session");
}
}
I'm Trying keep this answer short, but if there are any questions I can elaborate further about this problem.
我试图保持这个答案简短,但如果有任何问题,我可以进一步详细说明这个问题。
回答by theon
Check out this sectionin the docs. It says that SessionFactory.getCurrentSession()
is pluggable and there is a ThreadLocalSessionContext
implementation that keeps the 'current session' in the ThreadLocal
rather than a JTA transaction. ThreadLocalSessionContext will also close the Session at the end of the hibernate Transaction created from that Session, so you don't have to worry about closing the Session
yourself.
在文档中查看此部分。它说这SessionFactory.getCurrentSession()
是可插入的,并且有一个ThreadLocalSessionContext
实现可以将“当前会话”保持在ThreadLocal
而不是 JTA 事务中。ThreadLocalSessionContext 还将在从该会话创建的休眠事务结束时关闭会话,因此您不必担心Session
自己关闭会话。
With regards to introducing regression bugs, upgrading a library will always have it's risks, especially so when it is something as core to your application as hibernate. The only advice I can give is to ensure your test suite has decent coverage before the upgrade. After all, that's the job of your test suite - to catch regression bugs.
关于引入回归错误,升级库总是有风险的,尤其是当它像休眠一样是应用程序的核心时。我能给出的唯一建议是确保您的测试套件在升级前具有良好的覆盖范围。毕竟,这是您的测试套件的工作 - 捕获回归错误。
回答by Shivani
You can also continue to use HibernateTemplate
with getCurrentSession()
, as in many cases openSession()
might not be the best choice as you will need to close sessions on your own.
To use currentSession you can add the following to manage transactions:
您还可以继续使用HibernateTemplate
with getCurrentSession()
,因为在许多情况下openSession()
可能不是最佳选择,因为您需要自行关闭会话。要使用 currentSession,您可以添加以下内容来管理事务:
<prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform</prop>
<prop key="hibernate.transaction.jta.platform">org.hibernate.engine.transaction.jta.platform.internal.JBossAppServerJtaPlatform</prop>
where the key's value will depend on your AS.
密钥的值将取决于您的 AS。