Java 休眠,自动持久化依赖对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18454058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:44:43  来源:igfitidea点击:

Hibernate, automatically persist dependant objects

javahibernateormcascade

提问by GordonM

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.

我是 Hibernate 的新手,一直在尝试确定它会为您做什么以及它需要您做什么。

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).

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

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

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

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)

我当然可以通过查看它的 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;
    }
}

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

我还检查了与 Netbeans 捆绑的 Hibernate 版本,它是 3.2.5

UPDATE 2: I found that the following appears to apparently work as I wanted.

更新 2:我发现以下内容似乎可以按我的意愿工作。

@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.

我在几个地方看到过 CascadeType.SAVE_UPDATE ,但是这种模式在 Netbeans 附带的 Hibernate 版本中似乎不可用。

采纳答案by Luca Basso Ricci

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.@Cascadeif you use not JPA function Session.saveOrUpdate().

@ManyToOne(cascade)如果您使用Session.persist()操作或org.hibernate.annotations.@Cascade不使用 JPA 功能Session.saveOrUpdate()

This is just an example, for full doc point here

这只是一个例子,这里有完整的文档点

For your code, if you want to automatically save Manufacturerwhen saving Projectuse:

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

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

or

或者

@Cascade(CascadeType.PERSIST)