2

私は複式簿記システムを開発しており、シーケンシャルIDにギャップなしで転記レコードを挿入する必要があります。すべてのデータベースアクセスはWebアプリケーションを介して行われるため、同期された静的変数を使用してIDの生成を処理しています。

import org.hibernate.*;

public class JournalService {    
    private static Object journalLock = new Object();    
    private Session session;

    public JournalService(Session session) {
        this.session = session;
    }

    public void insertJournalEntry(JournalEntry journalEntry) {
        Set<PostEntry> entries = journalEntry.getEntries();

        double total = 0;

        for (PostEntry entry : entries) {
            total += entry.getAmount();
        }

        if(total != 0)
            throw new InvalidParameterException("Journal entry is invalid. The sum of all entries must be zero.");

        Criteria criteria = session.createCriteria(PostEntry.class);
        criteria.setMaxResults(1);
        criteria.addOrder(Order.desc("id"));
        //here I add some other criteria
        synchronized(journalLock) {            
            PostEntry lastEntry = criteria.uniqueResult();
            long currentId = lastEntry.getId();

            for (PostEntry entry : entries) {
                entry.setId(currentId++)
                session.save(entry);
            }            
            session.save(journalEntry);
        }
    }
}

簡単に言うと、このサービスの有効期間は現在のhttprequestに関連付けられており、Springコンテナーによって管理されます。さらに、リクエストの最後にトランザクション全体がコミットされていることを確認します。同期化されたブロックが同時実行を処理するため、IDのシーケンスにギャップが発生することはありません。ここでの大きな問題は、特定の基準に一致する最後に挿入されたレコードを選択するためのデータベースアクセスの追加オーバーヘッドです。私はそれが起こらないようにしたいので、ここでの解決策は、最後に挿入されたレコードを最初に選択したときに保持するキャッシュを使用することであると推測しています。したがって、IDを生成するためにデータベースアクセスは必要ありません。私の質問:これを解決するためのすぐに使える休止状態の方法はありますか?休止状態に慣れておらず、クエリキャッシュについて聞いたことがありますが、その使用方法がわかりません。私はしません このサービスを使用して保存するすべての値をキャッシュに保持したい場合は、特定の基準に一致する最後に挿入されたエントリを保存するために必要です。たとえば、2つが等しい基準「X」に一致し、他の3つが基準「Y」に一致する5つの挿入を実行した場合、キャッシュには2つのオブジェクト(各基準に一致する最後に挿入されたオブジェクト)のみが格納されます。これは自分で簡単に実装できますが、HibernateAPIと統合するソリューションを使用したいと思います。キャッシュには2つのオブジェクトのみが保存されます(各基準に一致する最後に挿入されたオブジェクト)。これは自分で簡単に実装できますが、HibernateAPIと統合するソリューションを使用したいと思います。キャッシュには2つのオブジェクトのみが保存されます(各基準に一致する最後に挿入されたオブジェクト)。これは自分で簡単に実装できますが、HibernateAPIと統合するソリューションを使用したいと思います。

4

1 に答える 1

1

キャッシングは、頻繁にアクセスされるがほとんど変更されないオブジェクトを格納するのに適しています。それはあなたがやろうとしていることではありません。シリアライズ可能なトランザクションを使用して、更新の損失や読み取りの不整合を防ぐことができます。これは、回避しようとしていることです。ただし、そのオーバーヘッドを覚えておく必要があります。

// Hibernate Transaction isolation level settings
// Serializable isolation level
hibernate.connection.isolation=8

これがSessionFactoryAPIの内容です

SessionFactoryの動作は、構成時に提供されるプロパティによって制御されます。これらのプロパティは環境で定義されています。

回避策として、上記のように1つをシリアル化できる2つの異なるSessionFactoryを設定できます。

挿入された最新のPostEntryエンティティを取得しているため、データベースが取得したPostEntryをロックするだけなので、ペシミストロックは適切に適用されないと思います。

于 2010-08-10T04:27:57.627 に答える