【问题标题】:How to know an object has changed compared to database与数据库相比,如何知道对象已更改
【发布时间】:2015-06-15 10:25:43
【问题描述】:

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

我无法触摸模型类是否已生成。

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

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

【问题讨论】:

  • 对象是否实现了 hashCode 函数?
  • 我不知道。但是我需要确切知道哪个字段被修改了......

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


【解决方案1】:

要强制 Hibernate 在 playframework 中启动一个新事务,从而为您提供一个新的实体管理器,它将返回数据库中的对象而不是对它的引用,您需要专门要求 play framework 启动通过 JPAPlugin 的新事务。

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

查看startTxcloseTx的javadoc

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这是一个相当复杂的应用程序,其中生成了模型类,我无法触摸模型类
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      您似乎正在使用扩展会话/实体管理器。你什么时候开始会议? 你试过了吗:

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

      【讨论】:

      • 模型类显然没有在 Play 中提供clear() 方法。清除会话的问题在于,在清除之前尝试与检索到的实体进行交互时会使事情中断。我找到的最佳解决方案是创建一个新的 EntityManager 并使用它从数据库中检索实体并将其与更改的实体进行比较。
      猜你喜欢
      • 1970-01-01
      • 2015-03-28
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 2018-07-07
      • 1970-01-01
      • 2015-01-27
      相关资源
      最近更新 更多