【问题标题】:JPA persistence using multiple threads使用多线程的 JPA 持久性
【发布时间】:2011-09-24 17:46:45
【问题描述】:

当我尝试使用多线程持久化对象时遇到问题。

详情:

假设我有一个对象PaymentOrder,其中包含PaymentGroup(一对多关系)列表,PaymentGroup 包含CreditTransfer(又是一对多关系)列表。

由于CreditTransfer 的数量很大(以十万为单位),我根据PaymentGroup 对其进行了分组(基于一些业务逻辑) 并创建 WORKER 线程(每个 PaymentGroup 一个线程)以形成 PaymentOrder 对象并提交到数据库中。

问题是,每个工作线程都在创建一个PaymentOrder(其中包含一组唯一的PaymentGroups)。

所有实体的主键都是自动生成的。

所以一共有三个表,1. PAYMENT_ORDER_MASTER, 2. PAYMENT_GROUPS, 3. CREDIT_TRANSFERS,都是一对多关系映射的。

因为当第二个线程尝试将其组持久化到数据库中时,框架尝试持久化相同的PaymentOrder,前一个线程已提交,事务由于一些其他唯一字段约束而失败(@987654331 的校验和@)。

理想情况下它必须是 1..n..m (PaymentOrder ->PaymentGroup-->CreditTransfer`)

我需要实现的是,如果数据库中没有PaymentOrder 的条目,则创建一个条目,如果存在,则不要在PAYMENT_ORDER_MASTER 中输入,而只能在PAYMENT_GROUPSCREDIT_TRANSFERS 中输入。

我怎样才能克服这个问题,维护 split-master-payment-order-using-groups 逻辑和多个线程?

【问题讨论】:

    标签: java multithreading hibernate orm jpa-2.0


    【解决方案1】:

    您有多种选择。
    1)原始但简单,在最后捕获密钥冲突错误并在没有父母的情况下重试插入。假设您的父母确实是独一无二的,您知道父母刚刚做了另一个线程......继续与孩子一起。与其他选项相比,这可能表现不佳,但也许你会得到你需要的流行音乐。如果你有一个孩子的父母比例很高,那会很好用。

    2) 更改您的读取一致性级别。它是特定于供应商的,但您有时可以读取未提交的事务。这将帮助您在提交之前查看其他线程的工作。这不是万无一失的,你仍然必须做#1,因为另一个线程可以在读取后潜入。但它可能会提高您的吞吐量,但代价是更加复杂。基于 RDBMS 可能是不可能的(或者它可能会发生,但仅在数据库级别,会弄乱其他应用程序!)

    3) 使用单线程消费者实现工作队列。如果程序的主要昂贵工作是在持久性级别之前,您可以让您的线程将其数据“插入”到工作队列中,其中不强制执行密钥。然后从工作队列中拉出一个线程并持久化。工作队列可以在内存中、另一个表中或供应商特定的位置(Weblogic 队列、Oracle AQ 等)。如果程序的主要工作是在持久化之前,则将其并行化并返回到插入的单个线程。您甚至可以让您的消费者在“批量插入”模式下工作。亲爱的。

    4) 放松你的约束。谁真正关心同一个孩子的两个父母是否拥有相同的信息?我只是问问。如果您以后不需要对父信息进行超快速更新,并且您可以更改阅读程序以理解它,它可以很好地工作。它不会让你在 DB 设计课上获得“A”,但如果它有效的话.....

    5) 实现一个愚蠢的锁表。我讨厌这个解决方案,但它确实有效——让你的线程写下它正在父“x”上工作,而其他人都不能,因为它是第一个事务(和提交)。通常会导致相同的问题(以及其他问题 - 稍后清理记录等),但当子插入速度慢且单行插入速度快时可以工作。您仍然会遇到碰撞,但会更少。

    【讨论】:

      【解决方案2】:

      Hibernate 会话不是线程安全的。作为 Hibernate 基础的 JDBC 连接不是线程安全的。考虑多线程化您的业务逻辑,以便每个线程都使用它自己的 Hibernate 会话和 JDBC 连接。通过使用线程池,您可以通过添加限制同时线程数量的能力来进一步改进您的代码。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-02-15
        • 1970-01-01
        • 2018-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-17
        • 2013-09-30
        相关资源
        最近更新 更多