制約例外処理せずに、スレッドセーフな冪等アップサートを休止状態?

アレックスR:

私としても知らUPSERT、実行するいくつかのコード持ってマージ私は特に、私は例外処理から離れて移動し、このような簡単な操作のためのコードの全体的な冗長性と複雑性を軽減したい、クリーンアップこのコードにしたいです。要件は、それが既に存在しない限り、各項目を挿入することです。

public void batchInsert(IncomingItem[] items) {
    try(Session session = sessionFactory.openSession()) {
        batchInsert(session, items);
    }
    catch(PersistenceException e) {
        if(e.getCause() instanceof ConstraintViolationException) {
            logger.warn("attempting to recover from constraint violation");
            DateTimeFormatter dbFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
            items = Arrays.stream(items).filter(item -> {
                int n = db.queryForObject("select count(*) from rets where source = ? and systemid = ? and updtdate = ?::timestamp",
                        Integer.class,
                        item.getSource().name(), item.getSystemID(), 
                        dbFormat.format(item.getUpdtDateObj()));
                if(n != 0) {
                    logger.warn("REMOVED DUPLICATE: " +
                            item.getSource() + " " + item.getSystemID() + " " + item.getUpdtDate());
                    return false;
                }
                else {
                    return true; // keep
                }
            }).toArray(IncomingItem[]::new);
            try(Session session = sessionFactory.openSession()) {
                batchInsert(session, items);
            }
        }
    }
}

SOの最初の検索が不十分です:

質問ではどのように春データJPAでON DUPLICATE KEY UPDATEを行うには?これは重複としてマークされていた、私は、この魅力的なコメントに気づきました:ここでは、画像の説明を入力します。

私は本当にコメントを理解していないとして、それはそれは巧妙な解決策のように聞こえる、そして「実際に同じSQL文」の言及にもかかわらず、行き止まりでした。

もう一つの有望なアプローチはこれです:Hibernateと春がDBに送信する前にクエリを変更します

CONFLICT DO NOTHING ON / ON DUPLICATE KEY UPDATE

主要なオープンソースデータベースの両方がデータベースに冪等を押し下げするメカニズムをサポートしています。以下の例は、PostgreSQLの構文を使用しますが、簡単にMySQLのために適合させることができます。

でアイデアに従うことでHibernateと春のDBに送信する前にクエリを変更Hibernateのクエリー生成にフッキング、そしてどのように私は、HibernateでStatementInspectorを設定することができますか?、私が実装さ:

import org.hibernate.resource.jdbc.spi.StatementInspector;

@SuppressWarnings("serial")
public class IdempotentInspector implements StatementInspector {

    @Override
    public String inspect(String sql) {
        if(sql.startsWith("insert into rets")) {
            sql += " ON CONFLICT DO NOTHING";
        }
        return sql;
    }

}

プロパティを持ちます

        <prop key="hibernate.session_factory.statement_inspector">com.myapp.IdempotentInspector</prop>

重複が発生した次のようなエラーに残念なことに、このリード線:

org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException:によって引き起こさバッチ更新は、更新[0]から予期しない行数を返しました。実際の行数:0。予想:1; ネストされた例外はorg.hibernate.StaleStateExceptionある:バッチ更新は、更新[0]から予期しない行数を返しました。実際の行数:0。予想:1

あなたはどちらのカバーの下に何が起こっているのか考えてみれば、理にかなって:ON CONFLICT DO NOTHINGゼロ行が挿入されます、しかし、1つのインサートが期待されています。

スレッドセーフな例外なしの同時冪等の挿入が可能になり、Hibernateが実行される全体のSQL INSERT文を定義し、手動で必要としない解決策はありますか?

何それの価値のために、私は、データベースへのdupcheckのダウンを押しアプローチは適切な解決策へのパスであることを感じています。

明確化IncomingItemによって消費されるオブジェクトbatchInsertメソッドは、レコードが不変であるシステムに由来します。この特殊な条件下でON CONFLICT DO NOTHING可能にもかかわらず、UPSERTと同じように動作N番目の更新の損失

ドラガンBozanovic:

短い答え- Hibernateは箱のそれをサポートしていない(でHibernateの第一人者によって確認されるよう、このブログの記事)。おそらく、あなたはそれはあなたがすでに説明したメカニズムで、いくつかのシナリオである程度動作させることができますが、単にネイティブクエリを使用すると、直接、この目的のために私には最も簡単な方法を探します。

長い答えは例えば、休止状態Iの推測のすべての側面を考慮すると、それをサポートするのは難しいだろうと次のようになります。

  • それらが持続した後、管理しまうことになっているとして、重複が発見されるインスタンスで何をしますか?永続コンテキストにそれらをマージ?
  • 何すでにされている団体で行うには、(;またはそれはその決定を下すためにその時点で手遅れになるsomething_new /持続/マージ)の操作がそれらに適用するためにどのカスケード、持続しましたか?
  • データベースはすべてのユースケースをカバーするためにアップサート事業から十分な情報を返します(行をスキップ;など、モードのインサートバッチで、スキップされていないために生成されたキー)。
  • 何について@Audit-edエンティティ、彼らは作成または更新され、更新された場合に何が変わったのか?
  • またはバージョニングと楽観的ロック(定義により、あなたが実際にそのような場合には例外をしたいですか)?

Hibernateはいくつかの方法でそれをサポートしていても気を付けると考慮すべきあまりにも多くの注意点があった場合、私は確かに、私はその機能を使用すると思いませんよ。

だから、私は従う親指のルールは次のとおりです。

  • (ほとんどの時間です)シンプルなシナリオの場合:+再試行を持続。特定のエラー(例外タイプまたは類似の別)の場合の再試行は、グローバルプロジェクトで使用しているフレームワークに依存しAOPのようなアプローチ(注釈、カスタムインターセプタと同様に)で構成することができ、特に分散環境でとにかくお勧めします。
  • 特定のデータベース機能の利用率を最大化するために、ネイティブクエリ:複雑なシナリオとパフォーマンスの集中的な操作については(特にそれがバッチ処理、非常に複雑なクエリと同様に来るとき)。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=171567&siteId=1