我支持使用相对简单的数据模型的CRUD遗留应用程序。为了通过启用延迟加载来提高性能,我从每个数据库查询的Hibernate会话(围绕每个查询的openSession / closeSession)切换到Tomcat过滤器完成的每个HTTP请求的Hibernate事务:
public class HibernateSessionRequestFilter implements Filter {
public void doFilter ... {
HibernateSession.getSessionFactory().getCurrentSession().beginTransaction();
chain.doFilter(request, response);
HibernateSession.getSessionFactory().getCurrentSession().getTransaction().commit();
就数据阅读而言,一切正常。
但是当复合对象被持久化然后在同一请求(事务)中呈现时会出现问题。对象映射就像
<class name="xxx.data.ReportDescription" table="report_descriptions">
...
<many-to-one name="job" class="xxx.data.Job" column="jobId"/>
持久代码是:
Session session = HibernateSession.currrentSession();
session.persist(reportDescription);
LOGGER.info("report PERSISTED: " + reportDescription.getJob());
“job PERSISTED”LOGGER输出显示Job对象只有有效的id,而其所有其他字段都是空的,这是不正确的 - 新的reportDescription对象指向的现有Job对象在所有对象中都没有空值它的领域。
如果我继续使用以下方法在同一事务中新加载reportDescription:
ReportDescription fetchedReportDescription =
ReportDescriptionHelper.getReportDescription(reportDescription.getId());
LOGGER.info("report FETCHED: " + fetchedReportDescription);
我再次使用其他字段中的有效id和null值复合Job对象。
如果我关闭交易并开始新交易,一切正常:
HibernateSession.getSessionFactory().getCurrentSession().getTransaction().commit();
HibernateSession.getSessionFactory().getCurrentSession().beginTransaction();
fetchedReportDescription =
ReportDescriptionHelper.getReportDescription(reportDescription.getId());
LOGGER.info("report FETCHED: " + fetchedReportDescription);
逻辑上,在下一个HTTP请求中,所有数据都是一致的。
我有两个解决方案,我不喜欢它们,因为它们只是解决方法:
在persist()
在每个persist()
为什么我会有这样的行为?有什么好的解决方案吗?
提前谢谢!