如何知道一个对象与数据库相比发生了变化

How to know an object has changed compared to database

我需要知道模型对象的某些字段在保存之前是否已更改,因为我需要将新值与旧值进行比较。

我无法触摸模型类它们是生成的吗。

我的问题是,每当我更改控制器中的对象并检查数据库以在保存修改后的对象之前存储对象时,从数据库返回的对象是 "same" 作为修改对象。

我正在使用 Play! 1.2.7 基本上我有这个:

class MyModel extends Model {
    public String label;
}

class MyModels extends Controller {

    public static void save(Long id) {
        MyModel m = MyModel.findById(id); // at this point m.label is "original"

        m.label = "changed !";

        MyModel m2 = MyModel.findById(id); // m2.label is "changed !" but should be "original", shouldn't it ?

    }
}

也许问题是:如何强制 JPA EntityManager 真正查看数据库而不是从上下文返回对象?因为这似乎是这里的真正问题。

解决方案

所以最终的解决方案是:

class MyModels extends Controller {

    public static void save(Long id) {
        MyModel m = MyModel.findById(id); // at this point m.label is "original"

        m.label = "changed !";
        MyModel m2;
        JPAPlugin.startTx(false);
        try {
            m2 = MyModel.findById(id); m2.label is "original"
        } finally {
            JPAPlugin.closeTx(false);
        }
    }
}

实现此目的的另一种方法是像这样创建一个新的 EntityManager :

EntityManager manager = JPA.entityManagerFactory.createEntityManager();
// set your new EntityManager as you like...
manager.setProperty("org.hibernate.readOnly", true);
Query q = manager.createQuery("select m from MyModel m where id = :id");
q.setMaxResults(1);
q.setParameter("id", m.getBaseId());

MyModel m2 = (MyModel) q.getResultList().get(0);

您可以向模型添加一个布尔字段(如 "hasBeenModified" - 用 false 初始化),而不将其绑定到数据库,并且每当您更新对象时,您将 hasBeenModified 的值更改为 true。

您可以在 Entity/Table 中添加一个版本字段,就像它在 jpa 中用于乐观锁定一样。

要强制 Hibernate 在 playframework 中启动一个新事务,从而为您提供一个新的实体管理器,它将 return 对象在数据库中的原样而不是对它的引用,您需要特别通过 JPAPlugin 要求 play 框架开始一个新的事务。

JPAPlugin.startTx(false);
try {
    // your code
} finally {
    JPAPlugin.closeTx(false);
}

查看 startTx and closeTx

的 javadoc

您似乎在使用扩展 session/entityManager。你什么时候打开session? 你试过了吗:

session.clear()/entityManager.clear()

在第二次调用 MyModel.findById(id) 之前; ?

class MyModels extends Controller {
    public static void save(Long id) {
        MyModel m = MyModel.findById(id); // at this point m.label is "original"
        m.label = "changed !"; 

        MyModel.clear() // I don't know if you have a MyModel.clear() but you should call session.clear()/entityManager.clear() here

        MyModel m2 = MyModel.findById(id);
    }
}