如何在 Apache Cayenne 中搜索可能已修改的对象?

问题描述 投票:0回答:1

与其他 ORM 框架一样,Cayenne 中的查询会读取数据库。但与其他 ORM 框架不同,Cayenne 仅在提交时将更改写入数据库。这意味着查询将看不到同一事务中所做的更改:

ObjectContext ctx = runtime.newContext();
// Searches for an item with id 1.
Item item = Cayenne.objectForPK(ctx, Item.class, 1);
System.out.println("" + item.getValue()); // output is 42.
// Changes the value but doesn't commit.
item.setValue(84);

// Searches (in the database) with new attribute value. Item is not found.
Item copy1 = ObjectSelect.query(Item.class).where(Item.VALUE.eq(84)).selectOne(ctx);
if (copy1 == null) System.out.println("not found"); // output: "not found".

// Searches (in the database) with old attribute value. Item is found.
Item copy2 = ObjectSelect.query(Item.class).where(Item.VALUE.eq(42)).selectOne(ctx);
// But item has the new attribute values cached in the ObjectContext.
System.out.println("" + copy2.getValue()); // output is 84.

一个可能但麻烦的解决方案是始终查询数据库和 ObjectContext:

Item copy = ObjectSelect.query(Item.class).where(Item.VALUE.eq(84)).selectOne(ctx);
if (copy == null) copy = (Item) Item.VALUE.eq(84).first(new ArrayList<>(ctx.uncommittedObjects()));
System.out.println("" + copy.getValue()); // output: "84".

在同一事务中查找可能已修改或新创建的对象的最佳实践是什么?

apache-cayenne
1个回答
0
投票

Cayenne 仅在提交时将更改写入数据库。

正确,但请记住,Cayenne 默认情况下将刷新和提交步骤作为单个操作进行,以使事情变得更容易,并在 99% 的情况下避免显式事务管理。但如果需要的话,它允许您将两者分开。

这意味着查询不会看到同一事务中所做的更改

问题是默认情况下您的查询不会在同一事务中。以下是您如何在一个事务中组合多个提交和查询

runtime.performInTransaction(() -> {
    ...
    ctx.commitChanges();
    ...
    ObjectSelect.query(Item.class).selectOne(ctx);
    ...
    ctx.commitChanges();
    ...
});
© www.soinside.com 2019 - 2024. All rights reserved.