与数据库相比,如何知道对象已更改

时间:2015-06-15 10:25:43

标签: java hibernate jpa playframework playframework-1.x

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

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

我的问题是,每当我更改控制器中的对象并检查数据库是否存储该对象时,在保存修改后的对象之前,数据库中返回的对象与修改后的对象“相同”。 / p>

我正在玩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);

4 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

要强制Hibernate在playframework中启动一个新事务,从而为你提供一个新的实体管理器,它将返回数据库中的对象,而不是对它的引用,你需要特别要求play框架启动通过JPAPlugin进行的新交易。

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

请参阅startTxcloseTx

的javadoc

答案 3 :(得分:0)

看起来你正在使用扩展会话/ entityManager。你什么时候开会? 你试过了吗?

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);
    }
}