Hibernate会自动持久依赖对象 [英] Hibernate, automatically persist dependant objects
问题描述
一个重要的问题是处理一个对象,该对象具有数据库中尚不存在的依赖项。例如,我有一个Project对象,其中包含一个Manufacturer字段,该字段接受一个Manufacturer对象作为其值。在数据库中,我有一个带有mfr_id列的产品表,它是对制造商表格的引用(一种相当典型的单向一对多关系)。
如果分配给产品对象的制造商与已经在数据库中的制造商相关,那么这没有问题。但是,当我尝试保存或更新引用尚未保存的制造商的对象时,操作将失败,并显示异常。
$ b
线程中的异常Applicationorg.hibernate.TransientObjectException:对象引用未保存的瞬态实例 - 在刷新前保存瞬态实例
>
我当然可以手动检查产品制造商的状态,看看它的ID字段是否为空并保存,如果是的话像一个麻烦的解决方案。 Hibernate是否支持自动持久化依赖项,如果相关依赖项尚未保留?如果是这样,我该如何启用该行为?我使用的是与Netbeans(3.5,我相信)绑定的Hibernate版本和内联注释来指定映射行为。以下是我的产品和制造商类,缩减为处理依赖关系的部分。 (Product extends Sellable映射到可销售表,使用JOINED作为继承策略)这是包含标识产品的主键的表
@Entity
@Table(
name =products,
schema =sellable
)
public abstract class Product extends Sellable {
私人制造商制造商;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name =mfr_id)
public制造商getManufacturer(){
return this.manufacturer;
}
/ **
*
* @param制造商
* /
公共产品setManufacturer(制造商制造商){
this.manufacturer =制造商;
返回此;
$ / code $ / pre
依赖制造商
@Entity
@Table(
name =manufacturer,
schema =sellable,
uniqueConstraints = @UniqueConstraint(columnNames =mfr_name)
)
public class Manufacturer实现Serializable {
private Integer mfrId = null;
private String mfrName = null;
@Id
@SequenceGenerator(name =manufacturers_mfr_id_seq,sequenceName =sellable.manufacturers_mfr_id_seq,allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE,generator = manufacturer_mfr_id_seq)
@Column(name =mfr_id,unique = true,nullable = false)
public Integer getMfrId(){
return mfrId;
}
私人制造商setMfrId(Integer mfrId){
this.mfrId = mfrId;
返回此;
@Column(name =mfr_name,unique = true,nullable = false,length = 127)
public String getMfrName(){
return mfrName ;
}
公共制造商setMfrName(String mfrName){
this.mfrName = mfrName;
返回此;
$ / code $ / pre
$ b更新:我尝试了以下从这个问题,但我仍然得到暂时性的对象异常。
@ManyToOne(fetch = FetchType.EAGER,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
我也查了一下Hibernate与Netbeans捆绑在一起的版本,它是3.2.5
更新2:我发现以下看起来显然是按照我的意愿工作的。
@ManyToOne(fetch = FetchType.EAGER,cascade = CascadeType.ALL)
但是,我怀疑这不是我真正想要的级联类型。如果我删除了某个产品,我认为删除其关联的制造商并不是正确的行为,这是我相信现在会发生的事情。
我曾尝试创建一个包含所有可用类型的级联类型,但这也不起作用。当我试图保存一个与未保存的制造商关联的产品时,我得到了同样的例外情况。
@ManyToOne(fetch = FetchType.EAGER,cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH})
我在几处提到过CascadeType.SAVE_UPDATE,但这种模式似乎并不可用在Netbeans附带的Hibernate版本中。
解决方案您必须查看级联操作;
这种类型的操作允许你管理内部对象的生命周期,尊重他们的父母。
@ ManyToOne(cascade)如果使用 Session.persist()
操作或 org.hibernate.annotations。@ Cascade
如果您不使用JPA函数 Session.saveOrUpdate()
。
这只是一个例子,对于完整的文档点 here
对于您的代码,如果您想自动保存制造商保存项目
使用:
@ ManyToOne(fetch = FetchType.EAGER,cascade = {javax.persistence.CascadeType.PERSIST})
@JoinColumn(name =mfr_id)
public制造商getManufacturer(){
return this。制造商;
}
或
@Cascade(CascadeType.PERSIST)
I'm quite new to Hibernate and have been trying to determine what it will do for you and what it requires you to do.
A big one is dealing with an object that has dependants that don't yet exist in the database. For example, I have a Project object that includes a Manufacturer field that accepts a Manufacturer object as its value. In the database I have a products table with a mfr_id column that's a reference to the manufacturers table (a fairly typical unidirectional one-to-many relationship).
If the manufacturer assigned to the product object relates to one that's already in the database then there's no problem. However, when I try to save or update an object that references a manufacturer that hasn't been persisted yet, the operation fails with an exception.
Exception in thread "Application" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing
I can of course manually check the state of the product's manufacturer by seeing if it's ID field is null and saving it if it is, but this seems like a cumbersome solution. Does Hibernate support automatically persisting dependants if the dependant in question isn't yet persisted? If so, how do I enable that behaviour? I'm using the version of Hibernate bundled with Netbeans (3.5, I believe) and inline annotations for specifying the mapping behaviour. Below are my product and manufacturer classes, cut down to the parts that handle the dependency. (Product extends Sellable which maps to a sellable table, using JOINED as the inheritance strategy It's that table that contains the primary key that identifies the product)
@Entity
@Table (
name="products",
schema="sellable"
)
public abstract class Product extends Sellable {
private Manufacturer manufacturer;
@ManyToOne (fetch = FetchType.EAGER)
@JoinColumn (name = "mfr_id")
public Manufacturer getManufacturer () {
return this.manufacturer;
}
/**
*
* @param manufacturer
*/
public Product setManufacturer (Manufacturer manufacturer) {
this.manufacturer = manufacturer;
return this;
}
}
The dependant Manufacturer
@Entity
@Table (
name="manufacturers",
schema="sellable",
uniqueConstraints = @UniqueConstraint(columnNames="mfr_name")
)
public class Manufacturer implements Serializable {
private Integer mfrId = null;
private String mfrName = null;
@Id
@SequenceGenerator (name = "manufacturers_mfr_id_seq", sequenceName = "sellable.manufacturers_mfr_id_seq", allocationSize = 1)
@GeneratedValue (strategy = GenerationType.SEQUENCE, generator = "manufacturers_mfr_id_seq")
@Column (name="mfr_id", unique=true, nullable=false)
public Integer getMfrId () {
return mfrId;
}
private Manufacturer setMfrId (Integer mfrId) {
this.mfrId = mfrId;
return this;
}
@Column(name="mfr_name", unique=true, nullable=false, length=127)
public String getMfrName () {
return mfrName;
}
public Manufacturer setMfrName (String mfrName) {
this.mfrName = mfrName;
return this;
}
}
UPDATE: I tried the following from this question, but I still get the transient object exception.
@ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
I also checked what version of Hibernate is bundled with Netbeans, it's 3.2.5
UPDATE 2: I found that the following appears to apparently work as I wanted.
@ManyToOne (fetch = FetchType.EAGER, cascade = CascadeType.ALL)
However, I suspect that this is not the cascade type I really want. If I delete a product, I don't think deleting its associated manufacturer is the correct action, which is what I believe will happen now.
I did try creating a cascade type that consisted of all the types that were available, but that didn't work either. I got the same exception when I tried to save a product that had an unsaved manufacturer associated with it.
@ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
I've seen CascadeType.SAVE_UPDATE mentioned in several places, but that mode doesn't seem to be available in the version of Hibernate that comes with Netbeans.
解决方案 You have to look at cascading operations; this type of operation permits you to manage lifecycle of inner object respect their parent.
@ManyToOne(cascade) if you use Session.persist()
operation or org.hibernate.annotations.@Cascade
if you use not JPA function Session.saveOrUpdate()
.
This is just an example, for full doc point here
For your code, if you want to automatically save Manufacturer
when saving Project
use:
@ManyToOne (fetch = FetchType.EAGER, cascade = {javax.persistence.CascadeType.PERSIST})
@JoinColumn (name = "mfr_id")
public Manufacturer getManufacturer () {
return this.manufacturer;
}
or
@Cascade(CascadeType.PERSIST)
这篇关于Hibernate会自动持久依赖对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!