休眠实体循环引用产生StackOverflowError [英] Hibernate Entity Circular Reference Produces StackOverflowError

查看:61
本文介绍了休眠实体循环引用产生StackOverflowError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我尝试具有引用 Product Product Order 时,出现 StackOverflowError 引用 Order .我知道这是由于有一个循环参考,但是我不确定如何解决它.我是ORM的新手,但不是SQL/Schema Design的新手:通常,我会有一个 Ordered_Products 表,该表将 Order 映射到 Product ,但我认为Hibernate会自动为我解决这个问题.

I get a StackOverflowError when attempting to have an Order which references a Product, and a Product that references an Order. I know this is due to having a circular reference, but I am unsure as to how to fix it. I'm new to ORMs but not to SQL/Schema Design: typically, I would have a Ordered_Products table which maps an Order to a Product, but I thought Hibernate would automagically take care of that for me.

Product 都具有唯一的ID(这些ID在应用程序外部生成),因此没有两个 Product 是相同的. Order ID也会在应用程序外部生成(我将在此管道的较早过程中从CSV导入此数据).

Products all have unique IDs (these are generated outside the app), so no two Products are the same. Order IDs are also generated outside the app (I will be importing this data from a CSV in an earlier process in this pipeline).

有人可以协助我们前进吗?

Could someone assist with moving forward?

@Entity
@Table(name = "Orders")
class Order implements Serializable {

    private static final long serialVersionUID = 2916987431893884948L;

    @Id
    @Column(name="id")
    private Long id;

    @Column(name="contactName")
    private String contactName;

    @OneToMany(mappedBy = "order", fetch=FetchType.EAGER, cascade = CascadeType.ALL)
    private Set<Product> products;

    // ...plain old getters and setters omitted...

    public Set<Product> getProducts() {

        // Should this be done at the member variable declaration?
        if (null == products) {
            this.products = new HashSet<Product>();
        }

        return products;
    }

    public void addProduct(Product p) {
        p.setOrder(this);
        getProducts().add(p);
    }

    public String toString() { 
    /* plain old to String which prints all member vars */ 
    }
}

Product.java

@Entity
@Table(name = "Products")
public class Product implements Serializable {

    private static final long serialVersionUID = 663408095532480033L;

    @Id
    @Column(name="id")
    private String id;

    @Column(name="size")
    private Size size;

    @OneToOne
    @JoinColumn(name="order_id", nullable=false)
    private Order order;

    // ...plain old getters and setters...

    public enum Size {
        EMPTY,
        XXSMALL,
        XSMALL,
        SMALL,
        MEDIUM,
        LARGE
    }

    public String toString() { 
    /* plain old to String which prints all member vars */ 
    }
}

产生错误的代码

Product b = new Product();
b.setId("ABC123");
b.setSize(Product.Size.LARGE);

Product c = new Product();
c.setId("DEF456");
c.setSize(Product.Size.XSMALL);

Order o = new Order();
o.setId(551234L);
o.setContactName("Marco");
o.addProduct(b);
o.addProduct(c);
System.out.println("Order ID=" + o);

堆栈跟踪

Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
    at java.util.HashMap$KeyIterator.<init>(HashMap.java:1451)
    at java.util.HashMap$KeySet.iterator(HashMap.java:912)
    at java.util.HashSet.iterator(HashSet.java:172)
    at java.util.AbstractCollection.toString(AbstractCollection.java:454)
    at java.lang.String.valueOf(String.java:2979)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.code4armour.shippingtracker.ui.model.Order.toString(Order.java:207)
    at java.lang.String.valueOf(String.java:2979)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.code4armour.shippingtracker.ui.model.Band.toString(Band.java:78)
    at java.lang.String.valueOf(String.java:2979)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at java.util.AbstractCollection.toString(AbstractCollection.java:462)
    at java.lang.String.valueOf(String.java:2979)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.code4armour.shippingtracker.ui.model.Order.toString(Order.java:207)
    at java.lang.String.valueOf(String.java:2979)
    at java.lang.StringBuilder.append(StringBuilder.java:131)
    at com.code4armour.shippingtracker.ui.model.Band.toString(Band.java:78)

这里的问题是 Order.toString()调用 Product.toString(),反之亦然

The problem here is the Order.toString() calling the Product.toString(), and vice versa

推荐答案

您可能要考虑包含两个实例的管理类/对象.通过此操作,您可以分别安全地调用这两个 toString()方法.

You may want to consider a managing class/object which contains instance(s) of both. Through this you could call both toString() methods separately and safely.

编辑(从我的第一条评论继续):

Edit (continuing from my first comment):

Order_Product_Link(表)

Order_Product_Link (table)

  • OrderID(FK)
  • 产品ID(FK)

约束:-orderID和productID的组合应该是唯一的

Constraints: - the combination of orderID and productID should be unique

注意事项:

  • 确保级联删除.因此,如果删除产品条目,则需要删除Order_Product_Link中所有引用其ID的条目.但是,您很可能不希望删除订单.反之亦然.

这篇关于休眠实体循环引用产生StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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