gpt4 book ai didi

java - 根据数据库中的数据检查对象的内存版本

转载 作者:行者123 更新时间:2023-11-30 04:57:30 25 4
gpt4 key购买 nike

我有一个 Hibernate 项目,其中调用 update()需要将内存中修改后的对象与已经保存到数据库中的数据进行比较。例如,我的业务逻辑规定,如果记录“有效”(生效日期是今天或更早),则更新无法更改生效日期。为了实现这一点,我有以下代码(有点长且复杂):

经理

public class LogicManager {

@Autowired
SessionFactory sessionFactory

private Session getSession() {
return sessionFactory.getCurrentSession();
}

public MemberRecord findRecord(Integer id) {
// << Code to check authorization >>
return memberRecordDAO.findById(id);
}

public void updateRecord(MemberRecord record) {
getSession().evict(record);
MemberRecord oldRecord = memberRecordDAO.findById(record.getId());

Date oldEffectiveDate = oldRecord.getEffectiveDate();
if ( isEffective(oldEffectiveDate) &&
!oldEffectiveDate.equals(record.getEffectiveDate)) {
throw new IllegalArgumentException("Cannot change date");
}

// << Other data checks >>
memberRecordDAO.update(record);
}
}

DAO

public class MemberRecordDAO {
@Autowired
private SessionFactory sessionFactory;

private Session getSession() {
return sessionFactory.getCurrentSession();
}

public MemberRecord findById(Integer id) {
return (MemberRecord)getSession()
.getNamedQuery("findMemberById")
.setInteger("id", id)
.uniqueResult();
}
}

客户端代码

// ...
public void changeEffectiveDate(Integer recordId, Date newDate) {
LogicManager manager = getBean("logicManager");

MemberRecord record = manager.findById(recordId);
record.setEffectiveDate(newDate);
manager.updateRecord(record);
}

在我添加 evict() 之前调用经理,我注意到经理的行为方式出乎意料。为了更新记录,我首先必须通过调用 findById() 来获取该记录。 ,这会将记录放入 session 缓存中。我会对该对象进行更改,然后调用 updateRecord()这会调用 findById()获取(据称)持久化的数据。我意识到第二次调用findById()不会查看数据库数据,而只是从缓存中提取对象。这将导致我的 oldEffectiveDate 总是与我新更改的日期相同,从record开始和oldRecord将是完全相同的对象。

为了解决这个问题,我添加了对 evict() 的调用,我理解这意味着该对象将从缓存中删除,迫使 Hibernate 去数据库获取 MemberRecord 。进行更改后,我的 MemberRecordDAO调用uniqueResult()时抛出异常,上面写着 AssertionFailed: possible nonthreadsafe access to session 。当我运行调试器时,我看到 LogicManagerMemberRecordDAO正在使用相同的 Session ,我认为这是正确的。

所以,我的问题:

  1. 我的想法/算法正确吗?是evict()正确的做法是什么?有没有更好的办法?我对 session 、缓存或evict()不太了解。我想在处理线程问题之前确保这个逻辑是正确的。
  2. 为什么访问 Session DAO 不是线程安全的吗?

最佳答案

evict() 方法可以工作,但我相信“首选的 hibernate 方式做事”是使用 Session.merge(),如下所示:

public MemberRecord updateRecord(MemberRecord newRecord) {

MemberRecord oldRecord = memberRecordDAO.findById(record.getId());

Date oldEffectiveDate = oldRecord.getEffectiveDate();
if ( isEffective(oldEffectiveDate) &&
!oldEffectiveDate.equals(newRecord.getEffectiveDate)) {
throw new IllegalArgumentException("Cannot change date");
} else {
MemberRecord merged = (MemberRecord) session.merge(newRecord);
return merged;
}
}

请记住,Session.merge() 将使用 newRecord 中的值更新 oldRecord 的所有字段。

关于java - 根据数据库中的数据检查对象的内存版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8070661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com