Hibernate,自动持久化依赖对象

时间:2013-08-26 22:27:01

标签: java hibernate orm cascade

我对Hibernate很陌生并且一直试图确定它将为您做什么以及它需要您做什么。

一个大问题是处理一个对象,该对象具有数据库中尚不存在的依赖项。例如,我有一个Project对象,其中包含一个Manufacturer字段,该字段接受Manufacturer对象作为其值。在数据库中,我有一个带有mfr_id列的产品表,该列是对manufacturer表的引用(一种相当典型的单向一对多关系)。

如果分配给产品对象的制造商与已经存在于数据库中的制造商有关,那么就没有问题。但是,当我尝试保存或更新引用尚未持久化的制造商的对象时,操作将失败并出现异常。

  

线程“Application”中的异常org.hibernate.TransientObjectException:object引用未保存的瞬态实例 - 在刷新之前保存瞬态实例

我当然可以手动检查产品制造商的状态,看看它的ID字段是否为空并保存,如果是,但这似乎是一个麻烦的解决方案。如果尚未保留相关的依赖项,Hibernate是否支持自动持久的依赖项?如果是这样,我该如何启用该行为?我正在使用与Netbeans捆绑的Hibernate版本(我相信3.5)和用于指定映射行为的内联注释。以下是我的产品和制造商类,减少了处理依赖关系的部分。 (产品扩展为Sellable,映射到可销售的表,使用JOINED作为继承策略。该表包含标识产品的主键)

@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;
    }
}

依赖制造商

@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;
    }
}

更新:我从this question尝试了以下内容,但我仍然得到了瞬态对象异常。

@ManyToOne (fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})

我还检查了Netbeans捆绑了哪个版本的Hibernate,它是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版本中不可用。

1 个答案:

答案 0 :(得分:7)

你必须看看级联操作;这种类型的操作允许您管理内部对象相对于其父对象的生命周期。

@ManyToOne(cascade)如果你使用Session.persist()操作,或org.hibernate.annotations.@Cascade如果你不使用JPA函数Session.saveOrUpdate()

这只是一个完整文档点here

的示例

对于您的代码,如果您想在保存Manufacturer时自动保存Project

@ManyToOne (fetch = FetchType.EAGER, cascade = {javax.persistence.CascadeType.PERSIST})
@JoinColumn (name = "mfr_id")
public Manufacturer getManufacturer () {
  return this.manufacturer;
}

@Cascade(CascadeType.PERSIST)