(已解决,见下文)
Hibernate 4.1 / Spring / JPA项目。我正在使用Spring& JPA注释用于事务支持,实体管理器注入等。
我在同一个事务中看到我的@OneToMany延迟加载的集合没有设置会话属性,当然也无法加载。如果我'left join fetch'强制加载,我会得到多条指向同一PersistentBag的记录 - 显然这会抛出'shared collection'异常。
这是我的设置:
交易实体('交易'的意思是在金融交易中)
代码:
@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个整数类型列链接到Location实体,这些cols在Transaction或Location实体上都不是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;
}
}
交易实体与地点之间存在一对多关系,大多数交易实体将指向相同的地点列表。
现在,如果我执行以下查询:
代码:
select distinct t from " + Transaction.class.getName() + " t left join fetch t.locations where " + filterSQL
我得到了结果,但几乎每个Transaction实体都指向相同的PersistentBag位置 - 不用说这会导致共享引用错误。
如果我省略左连接提取,则所有实体都会返回延迟加载的集合,但没有设置会话属性。
如果我急切加载,我只会急切地加载2个实体,其余的仍然是懒惰的(我知道这是一个内置的限制,任何方式来覆盖它?)
修改 我开始相信这是Hibernate中的一个错误。如果你的查询返回指向同一集合的多个记录(我可能会添加完全有效的场景!),那么Hibernate将在急切地获取时重用相同的集合,并在延迟加载时将session设置为null。它将始终导致对同一集合的共享引用或“无会话”错误。
我已经切换到EclipseLink 2.4,在修复我的JPSQL之后,它似乎在上述情况下工作正常。