8

アプリケーションで複数のスレッドを実行すると、Spring と Hibernate で奇妙な問題が発生します。春の 3.2.0.RELEASE と休止状態の 4.1.12.Final を使用しています。問題は、一部のオブジェクトについて、それらがデータベースから取得されると、取得は成功しますが、すべてのマップされたコレクションが設定されていないことです。これが私のレポの例です:

@Repository("fooRepository")
public class FooRepository {

    private static final Logger log = Logger.getLogger(FooRepository.class);

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    @Transactional
    public Foo retrieve(final Long id) {
        Foo instance = (Foo) sessionFactory.getCurrentSession().get(Foo.class, id);
        for (CollectionMember member : instance.getCollectionMembers()) {
            log.debug(member.getId());      
        }
        return instance;
    }

一部のオブジェクトでは、CollectionMember リストにアクセスしようとすると、このメソッドは常に次のエラーをスローします。

Caused by: java.lang.NullPointerException
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:501)

問題は、session.get() 呼び出しが、遅延ロードされたすべてのコレクションに対して PersistentBag オブジェクトを作成するが、コンテンツを設定しないことです。これは、マルチスレッドが有効になっている場合にのみ発生します。なぜこれが起こっているのか誰か説明できますか?

編集: foo クラスの関連するビットは次のとおりです。

@Entity
@Table(name = "FOO")
@XmlRootElement(name = "foo")
public class Foo {

    @EmbeddedId
    private FooPK id;

    @OneToMany
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumns({
            @JoinColumn(name = "COLLECTION_ID", referencedColumnName = "COLLECTION_ID"),
            @JoinColumn(name = "FOO_ID", referencedColumnName = "FOO_ID")})
    private List<CollectionMember> collectionMembers = new ArrayList<CollectionMember>();

CollectionMember クラス:

@Entity
@Table(name = "COLLECTION_MEMBER")
@XmlRootElement(name = "collectionMember")
public class CollectionMember {

    @EmbeddedId
    private CollectionMemberPK primaryKey;

    @ManyToOne
    @JoinColumn(name = "COLL_CODE")
    private CollectionCode collectionCode;
4

6 に答える 6

2

3番目の結合テーブルのように使用し、コレクションのロードに基準を使用する必要があると思います。

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "table", joinColumns = {@JoinColumn(name = "COLLECTION_ID", nullable = false)}, inverseJoinColumns = { @JoinColumn(name = "FOO_ID", nullable = true) })
    private List<CollectionMember> collectionMembers = new ArrayList<CollectionMember>();


@ManyToOne(mappedBy="collectionMembers")
private CollectionCode collectionCode;
于 2014-05-01T09:49:20.337 に答える
0

特に明記しない限り、Hibernate はすべての *ToMany コレクション マッピングをデフォルトで遅延としてマークします。1 つのスレッドがオブジェクトをロードすることは不可能であり、1 つの @Transactional メソッド内で関連する遅延コレクションを読み取ることはできません。

あなたの場合、マルチスレッドとは何ですか? スレッドを手動で生成しますか、それとも Web アプリケーションですか? セッション境界をどのように設定しますか?

ところで、本当に問題を解決したい場合は、スタックトレースを投稿することをお勧めします.懸念がある場合に備えて、商用パッケージ名を置き換えるのに数秒かかる場合があります.

于 2013-10-13T19:11:45.613 に答える
0

マルチスレッドはどこで機能しますか? 単一のスレッドが常に同じ休止状態セッションを使用することをどのように保証していますか?

コレクションをトラバースすると、Hibernate は CurrentSession を参照します。マルチスレッド環境では、そのセッションが別のスレッドによってすでに使用されている可能性があります。同じ Hibernate セッションを保持するのに @Transactional で十分かどうかはわかりません。

このための Hibernate 構成がある場合があります。

于 2013-06-27T20:18:21.190 に答える