使用多个线程的JPA持久性
当我尝试使用多个线程持久化对象时,我遇到了问题。
细节 :
假设我有一个对象PaymentOrder
,它有一个PaymentGroup
列表(一对多关系), PaymentGroup
包含一个CreditTransfer
列表(一对多关系)。
由于CreditTransfer
的数量巨大(以CreditTransfer
),我根据PaymentGroup
(基于某些业务逻辑)对其进行分组,并创建WORKER线程(每个PaymentGroup一个线程)以形成PaymentOrder
对象并在数据库中提交。
问题是,每个工作线程都创建一个PaymentOrder
(其中包含一组唯一的PaymentGroup
)。
所有权利的主键都是自动生成的。
所以有三个表,1。PAYMENT_ORDER_MASTER,2。PAYMENT_GROUPS,3。CREDIT_TRANSFERS,都是由One to Many关系映射的。
因此,当第二个线程试图将其组保留在数据库中时,框架会尝试持久保存相同的PaymentOrder
,前一个线程已提交,由于某些其他唯一字段约束( PaymentOrder
的校验和),事务将失败。
理想情况下,它必须是1..n..m( PaymentOrder
– > PaymentGroup -->
CreditTransfer`)
我需要实现的是,如果在数据库中没有PaymentOrder
的条目进行输入,如果它在那里,不要在PAYMENT_ORDER_MASTER
输入,而只在PAYMENT_GROUPS
和CREDIT_TRANSFERS
。
我怎样才能解决这个问题,维护split-master-payment-order-using-groups逻辑和多个线程?
你有选择。
1)原始但很简单,在最后捕获密钥违规错误并在没有父母的情况下重试插入。 假设你的父母是真正独特的,你知道另一个线索只是做了父母……继续孩子。 与其他选项相比,这可能表现不佳,但也许您可以获得所需的弹出窗口。 如果你有一个孩子的父母有很高的百分比,它会很好地工作。
2)更改读取一致性级别。 它是特定于供应商的,但您有时可以读取未提交的事务。 这可以帮助您在提交之前查看其他线程的工作。 这不是万无一失的,你仍然必须做#1,因为另一个线程可以在读取后潜入。 但它可能会以更复杂的代价提高您的吞吐量。 可能是不可能的,基于RDBMS(或者它可能发生但只在数据库级别,搞乱其他应用程序!)
3)使用单线程使用者实现工作队列。 如果程序的主要昂贵工作在持久性级别之前,则可以让您的线程将其数据“插入”到不强制执行密钥的工作队列中。 然后从工作队列中拉出一个线程并保持不变。 工作队列可以位于内存中,另一个表中,也可以位于特定于供应商的位置(Weblogic队列,Oracle AQ等)。 如果程序的主要工作在持久性之前,那么您可以并行化THAT并返回插入的单个线程。 您甚至可以让您的消费者以“批量插入”模式工作。 Sweeeeeeeet。
4)放松你的约束。 如果同一个孩子有两个父母持有相同信息,谁真正关心? 我只是问问。 如果您以后不需要父信息的超快速更新,并且您可以更改您的阅读程序以理解它,它可以很好地工作。 它不会让你在DB设计课上成为“A”,但如果它有效……
5)实现一个傻瓜锁表。 我讨厌这个解决方案,但它确实有效 – 让你的线程记下它正在处理父“x”而没有其他人可以作为它的第一个事务(和提交)。 通常会导致相同的问题(以及其他问题 – 稍后清理记录等),但是当子插入缓慢且单行插入速度很快时可以工作。 你仍然会发生碰撞,但会更少。
Hibernate会话不是线程安全的。 支持Hibernate的JDBC连接不是线程安全的。 考虑multithreading化您的业务逻辑,以便每个线程都使用它自己的Hibernate会话和JDBC连接。 通过使用线程池,您可以通过添加限制同时线程数量的function来进一步改进代码。
- 抢先并优雅地检查org.hibernate.Session是否仍然连接(通过c3p0)
- 使用JPA Criteria Api和hibernate spatial 4
- Hibernate更快地创建EntityManagerFactory
- 使用Apache Ivy无法获得Hibernate Core和Hibernate Annotations(但它也与Maven2相关。)
- 在Hibernate标准中区分大小写搜索
- 使用Oracle序列时,Hibernate不会生成标识符
- 使用hibernate和gilead for gwt添加到实体类中保存的列表时的LazyInitializationException
- 映射键值的Hibernate Criteria
- 如何使用generics关系实现多态JPA实体