Hibernate会自动持久依赖对象 [英] Hibernate, automatically persist dependant objects

查看:101
本文介绍了Hibernate会自动持久依赖对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于Hibernate来说,我很新,并且一直试图确定它会为你做什么以及它需要你做什么。

一个重要的问题是处理一个对象,该对象具有数据库中尚不存在的依赖项。例如,我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆