JPA:我可以按照对象发送到persist()的顺序强制将对象持久化到数据库吗?

时间:2010-09-25 01:20:25

标签: java jpa html-lists

I am creating a billing system管理每个客户的分类帐。每个Ledger都有一个LedgerEntry列表,用于记录每个客户交易。

当我测试这个时,我注意到如果我在同一个事务中创建了一堆LedgerEntry,那么@Id值不是为了将对象赋予em.persist(),除非我做了em。创建每个条目后刷新()。

因为我依赖于id的顺序来确定Ledger的正确行为(具体来说,当前的余额是列表中的最后一个LedgerEntry - 由@OrderBy强制执行“id ASC”),这意味着我有冲洗()很多次。

创建每一行后是否有办法避免刷新?也就是说,如何在不使用@OrderColumn的情况下对对象的持久性进行某种排序?

4 个答案:

答案 0 :(得分:1)

我不确定这是通用的JPA还是Hibernate,但请注意Hibernate的persist()save()之间的区别。来自the docs(强调我的):

  
      
  • persist()使瞬态实例持久化。但是,它不保证标识符值将立即分配给持久性实例,分配可能在刷新时发生。
  •   
  • save()确保返回标识符。如果必须执行INSERT以获取标识符(例如“身份”生成器,而不是“序列”),则无论您是在事务内部还是外部,都会立即执行此INSERT。
  •   

因此,如果您使用save(),则应按照您调用save()的顺序生成ID。如果只是为了获取ID而执行插入是有问题的(对于性能等),您可以选择使用另一个不需要命中数据库的ID生成器。

答案 1 :(得分:0)

据我所知,没有关于语句的顺序和规范中EntityManager方法调用的顺序。即使您的提供商允许通过某种专有设置进行配置,或者默认情况下提供此行为,我也不会依赖它。

但实际上,如果你需要处理有序列表,IMO会很有意义地使用列来维护持久性顺序并使用OrderColumn来定义它。你应该IMO不要依赖PK来做生意。

答案 2 :(得分:0)

我不完全确定我理解你的结构。

您应该能够通过transaction_timestamp对单个业务事务(多个LedgerEntry行?)进行排序,以获得正确的顺序。

但为什么表中的当前余额行呢?它可以计算,是吗?

如果当前余额行,我将创建一个line_item_number列,并为每个业务事务按顺序分配值。当与Ledger id结合使用时,这可能会成为一个很好的唯一键。并且我将当前余额行分配为999999的魔术值,因此它总是最后排序。

一个很好的副作用是从表中选择欠款真的很容易 - 对line_item_number = 999999的所有行求和。


然而,我的偏好是删除current_balance行,看看问题就消失了。


另一个选择是将计算机current_balance放在Ledger中,而不是将其作为LedgerEntry行。

答案 3 :(得分:0)

使用什么方法生成id?序列 ?桌子?用户指定的? 如其他回复所述,无法保证分配顺序如果生成方法不依赖于数据存储区,那么大多数实现都会将调用时的值设置为“persist” ”。如果生成方法OTOH使用数据存储区,则您必须刷新以强制此数据存储区联系。