1

(已解决,见下文)

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 个整数类型列链接到位置实体,这些列在事务或位置实体上都不是 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 位置 - 不用说这会导致共享引用错误。

如果我省略 left join fetch 所有实体返回延迟加载的集合,但没有设置会话属性。

如果我进行急切加载,我只会急切加载 2 个实体,其余的仍然是惰性的(我知道这是一个内置限制,有什么方法可以覆盖它吗?)

编辑: 我开始相信这是 Hibernate 中的一个错误。如果您的查询返回指向同一个集合的多条记录(我可能会添加完全有效的场景!),那么 Hibernate 将在急切获取时重用相同的集合,并在延迟加载时将 session 设置为 null。它总是会导致对同一集合的共享引用或“无会话”错误。

我已经切换到 EclipseLink 2.4,并且在修复了我的 JPSQL 之后,它似乎在上述情况下工作正常。

4

0 回答 0