对象引用Hibernate 4.3中未保存的瞬态实例

时间:2015-01-29 16:19:25

标签: java oracle hibernate

这不是通常情况,但我希望有人可以解释一下。这曾经在Hibernate 3中运行,但我最近升级了哪些东西。

我正在使用Hibernate 4.3.5和Oracle 11g数据库。

假设一组看起来像这样的实体类(为简洁起见省略了一些代码):

@Entity
@Table("MY_FILES")
public class MyFileInfo {

  private String fileId;
  private String name;
  private MyFileData myFileData;

  @Id
  @GeneratedValue(strategy = GenerationType.SEQUENCE,
                  generator = "fidSeq")
  @SequenceGenerator(name = "fidSeq",
                     sequenceName = "SQ_FILE_ID",
                     allocationSize = 10,
                     initialValue = 1)
  @Column(name="FILE_ID")
  public String getFileId() {
    return fileId;
  }

  @Column(name = "NAME")
  public String getName() {
    return name;
  }

  @OneToOne(mappedBy = "myFileInfo",
            fetch = FetchType.LAZY,
            optional = false,
            cascade = CascadeType.REFRESH)
  public MyFileData getMyFileData() {
    if (myFileData == null) {
      myFileData = new MyFileData(this);
    }
    return myFileData;
  }

  // ... setters ... //
}

-

@Entity
@Table("MY_FILES")
public class MyFileData {

  private String fileId;
  private MyFileInfo myFileInfo;
  private byte[] content;

  public MyFileData() {}
  public MyFileData(MyFileInfo myFileInfo) {
    setMyFileInfo(myFileInfo);
  }

  @Id
  @Column(name = "FILE_ID",
          insertable = false,
          updatable = false)
  public String getFileId() {
    return fileId;
  }

  @OneToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "FILE_ID",
              referencedColumnName = "FILE_ID",
              insertable = false,
              updatable = false)
  public MyFileInfo getMyFileInfo()
  {
    return myFileInfo;
  }

  @Column(name = "FILE_CONTENTS",
          insertable = false)
  public byte[] getContent()
  {
    return content;
  }

  public setMyFileInfo(MyFileInfo myFileInfo) {
    this.myFileInfo = myFileInfo;
    fileId(myFileInfo.getId());
  }

  // ... other setters ... //
}

请注意,此处的代码是在IDE外部编写的,未经过测试或编译。请注意缺陷,请告诉我。

好吧,现在我知道这很奇怪,因为我将两个实体映射到同一个表。这里的全部目的是能够在不获取MyFileInfo列的情况下加载FILE_CONTENTS个对象,允许文件列表而无需从数据库中下载潜在的大文件。 "为什么不使用原生查询或类似的东西,"你问?好吧,在这个应用程序中使用Hibernate非常广泛且紧密耦合,并且捕获所有不必要地加载文件内容的地方几乎是不可能的。

说到这些,我曾经能够使用一系列看起来像这样的调用在Hibernate 3.6.10中写入数据库:

final MyFileInfo info = new MyFileInfo();
Session session = sessionFactory.getCurrentSession();
info.setMyFileData(new MyFileData(info));
session.saveOrUpdate(info);
session.flush();
session.refresh(info);
info.getMyFileData().setFileId(info.getId());
session.saveOrUpdate(info.getMyFileData());

这一切都非常复杂和充满感觉,但它确实奏效了。现在我得到了臭名昭着的object references an unsaved transient instance - save the transient instance before flushing错误,但我无法先保存MyFileInfo对象 - 刷新/刷新会获得我需要在MyFileData上设置的生成ID对象以便能够保存它。

非常感谢任何帮助。如果我需要提供更多信息,请将其放在评论中!谢谢!

1 个答案:

答案 0 :(得分:0)

答案比我想象的要简单得多。我能够通过移动持久性逻辑而不是触及@Entity类来修复它:

final MyFileInfo info = new MyFileInfo();
Session session = sessionFactory.getCurrentSession();

// saveOrUpdate actually gets the id from Hibernate's sequence cache,
// which doesn't need a flush
session.saveOrUpdate(info);

// then I can set the ID where appropriate and save (update) the "new" entity
info.setMyFileData(new MyFileData(info));
info.getMyFileData().setFileId(info.getId());
session.saveOrUpdate(info.getMyFileData());

// the flush will save the MyFileInfo object and perform a no-
// consequence update on the MyFileData object.
session.flush();
session.refresh(info);