Spring データを使用した Postgres SQL の競合状態 JpaRepository

okwaves2024-01-25  7

Spring データ JpaRepository を使用して PostgresSQL DB にデータを永続化する実装で、奇妙な問題に直面しています。

私の Entity クラスには以下の列があります:

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private int id;
    
    @Column(name = "field1", nullable = false, length = 16)
    private String field1;

    @Column(name = "field2", nullable = false, length = 16)
    private String field2;

    @Column(name = "field3", nullable = false, length = 16)
    private String field3;

複合キーとして扱われるフィールドが多数あったため、私は当初、上記のフィールドを複合として宣言することを避けました。 Java コード チェックはあらゆるシナリオでうまくいくと思いました

基本的に、field1、field2、field3 に基づいて各行の一意性を維持する必要があります。これは、フィールド 1、フィールド 2、およびフィールド 3 の組み合わせに対するエントリが DB に存在する場合に Java 例外をスローするという Java コードでのチェックの基本的な要件でした。

これらの値を 2 つの行で繰り返すことはできません。アプリケーションをテストするまではすべて順調でした実稼働環境では決して起こらないが、誤って実行されたいくつかのエラーのあるビジネス シナリオ

現在起こっていることは、上記のまったく同じ 3 つのフィールドを持つまったく同じインスタンスで 2 つのリクエストが (スクリプトを通じて) トリガーされた場合、どちらもエントリ チェックが false になるため、両方ともデータベースに入ります。

それらすべてを 1 つの複合キーとして宣言すると、状況は解決しますか?

安全のために、まず postgres に一意の制約を追加します。

– シリル G.

2020 年 9 月 3 日 10:57



------------------------

JPA 制約に加えて、データベースに一意制約を定義する必要があります。

@Entity
@Table(uniqueConstraints={
    @UniqueConstraint(columnNames = {"field1", "field2", "field3"})
}) 
public class MyEntity {
  ...
}

2

もちろん。これを試して戻ってきます。ご協力ありがとうございます

– アモル・クシルサガル

2020 年 9 月 3 日 23:48

上記の提案を試したところ、統合テストの存続期間中にエンティティ定義を使用してテーブルを作成するメモリ DB に H2 を作成している統合テストの場合に機能しました。ただし、実行時のデプロイメント後、uniqueconstraint は実際のテーブルでは機能しません。実際のテーブルを作成するために使用している liquibase スクリプトも変更する必要があると思います。上記を Java @Entity クラスに追加するだけでは機能しません。間違っていたら修正してください

– アモル・クシルサガル

2020 年 9 月 6 日 13:32

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。