如何在Apache Cayenne同一事务中查询修改或新建的对象?
Cayenne同一事务内查询已修改/新建对象的最佳实践
和其他ORM框架类似,Cayenne的查询会直接读取数据库,但不同的是Cayenne仅在提交操作时才会将对象更改写入数据库。这就导致一个问题:同一事务内的查询无法看到已经做出但未提交的更改,示例如下:
ObjectContext ctx = runtime.newContext(); // 查询ID为1的Item Item item = Cayenne.objectForPK(ctx, Item.class, 1); System.out.println("" + item.getValue()); // 输出:42 // 修改值但不提交 item.setValue(84); // 用新值查询数据库,找不到对象 Item copy1 = ObjectSelect.query(Item.class) .where(Item.VALUE.eq(84)).selectOne(ctx); if (copy1 == null) System.out.println("not found"); // 输出:not found // 用旧值查询数据库,可以找到对象 Item copy2 = ObjectSelect.query(Item.class) .where(Item.VALUE.eq(42)).selectOne(ctx); // 但ObjectContext中缓存了对象的新值 System.out.println("" + copy2.getValue()); // 输出: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()); // 输出:"84"
那么,在同一事务中查找可能已修改或新建的对象,最佳实践是什么?
编辑后的解决方案
根据提示,正确的解决方案如下:
try { runtime.performInTransaction(() -> { ObjectContext ctx = runtime.newContext(); Item item = Cayenne.objectForPK(ctx, Item.class, 31); item.setValue(84); ctx.commitChanges(); Item copy = ObjectSelect.query(Item.class) .where(Item.VALUE.eq(84)).selectOne(ctx); System.out.println("" + copy.getValue()); // 输出:84 ctx.rollbackChanges(); return 0; }); } catch (Exception e) { // 回滚会触发CayenneRuntimeException System.out.println(e.toString()); }
如果回滚引发的异常不符合预期,可以使用以下辅助函数:
public <T> T performInTransaction(TransactionalOperation<T> op) { Transaction t = runtime.getInjector() .getInstance(TransactionFactory.class) .createTransaction(); BaseTransaction.bindThreadTransaction(t); try { TransactionDescriptor td = TransactionDescriptor.builder() .propagation(TransactionPropagation.MANDATORY).build(); T result = runtime.performInTransaction(op, td); BaseTransaction.bindThreadTransaction(null); if (t.isRollbackOnly()) t.rollback(); else t.commit(); return result; } catch (Exception e) { t.rollback(); throw e; } }
内容的提问来源于stack exchange,提问作者PSt
相关产品推荐
相关产品推荐

