这不是通常情况,但我希望有人可以解释一下。这曾经在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对象以便能够保存它。
非常感谢任何帮助。如果我需要提供更多信息,请将其放在评论中!谢谢!
答案 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);