(解決済みのソート、以下を参照)
Hibernate 4.1 / Spring/JPAプロジェクト。トランザクションサポート、エンティティマネージャーインジェクションなどにSpring&JPAアノテーションを使用しています。
同じトランザクション内で、@ OneToManyの遅延ロードされたコレクションにセッションプロパティが設定されておらず、もちろんロードできません。'left join fetch'を実行して強制的にロードすると、同じPersistentBagを指す複数のレコードが取得されます-明らかにこれは'sharedcollection'例外をスローします。
これが私の設定です:
トランザクションエンティティ(「トランザクション」は金融トランザクションの場合と同じ意味です)
コード:
@Entity
@Table(name = "transactionData")
@Access(AccessType.PROPERTY)
public class TransactionData extends AbstractTransaction implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
@OneToMany(cascade=CascadeType.ALL,targetEntity=Location.class,fetch=FetchType.LAZY)
@JoinColumns(
{
@JoinColumn(name="routecode",referencedColumnName="v_OPERSTAT"),
@JoinColumn(name="cogrp", referencedColumnName="v_COUNTRY")
})
@Transactional
public Collection<Location> getLocations() {
return super.getLocations();
}
public void setLocations(Collection<Location> l) {
super.setLocations(l);
}
}
トランザクションの基本クラス:
コード:
public abstract class AbstractTransaction {
private List<Location> _locations;
@Override
@Transactional
public List<Location> getLocations() {
return _locations;
}
@Override
public void setLocations(List<Location> value) {
_locations = value;
}
}
トランザクションエンティティは、2つの整数型列を使用してロケーションエンティティにリンクされています。これらの列は、トランザクションエンティティまたはロケーションエンティティのいずれでもPKではありません。
ロケーションエンティティ:
コード:
@Entity
@Table(name = "locations", uniqueConstraints = @UniqueConstraint(columnNames = {
"cogrp", "cugrp", "bogrp", "status", "id" }))
public class Location implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Column(name = "cogrp", nullable = false)
public int getCogrp() {
return this.cogrp;
}
public void setCogrp(int cogrp) {
this.cogrp = cogrp;
}
@Column(name = "routecode")
public Integer getRoutecode() {
return this.routecode;
}
public void setRoutecode(Integer routecode) {
this.routecode = routecode;
}
}
トランザクションエンティティは場所と1対多の関係にあり、ほとんどのトランザクションエンティティは同じ場所のリストを指します。
ここで、次のクエリを実行すると、次のようになります。
コード:
select distinct t from " + Transaction.class.getName() + " t left join fetch t.locations where " + filterSQL
結果は返されますが、ほとんどすべてのトランザクションエンティティが同じPersistentBagの場所を指しているため、共有参照エラーが発生することは言うまでもありません。
左結合フェッチを省略すると、すべてのエンティティが遅延ロードされたコレクションで返されますが、セッションプロパティが設定されているものはありません。
熱心にロードする場合、熱心にロードされるエンティティは2つだけですが、残りはまだ遅延です(これは組み込みの制限であり、それをオーバーライドする方法はありますか?)
編集: これはHibernateのバグであると私は信じるようになりました。クエリが同じコレクションを指す複数のレコードを返す場合(私が追加する可能性のある完全に有効なシナリオです!)、Hibernateは熱心にフェッチするときに同じコレクションを再利用し、遅延読み込み時にセッションをnullに設定します。常に同じコレクションへの共有参照、または「セッションなし」エラーが発生します。
EclipseLink 2.4に切り替えましたが、JPSQLを修正した後、上記の場合は正常に機能しているようです。