使用Hibernate获取重复条目 [英] Getting Duplicate Entries using Hibernate

查看:96
本文介绍了使用Hibernate获取重复条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用JPA / Hibernate时遇到了一个奇怪的问题。我在测试期间看到重复的条目。

I am experiencing a weird issue when using JPA/Hibernate. I am seeing duplicate entries during testing.

这是我的BaseEntity类:

Here is my BaseEntity class:

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class BaseEntity {

    @Id
    @Column(name = "ID", updatable = false, nullable = false)
    @GenericGenerator(name = "uniqueIDGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = {
            @org.hibernate.annotations.Parameter(name = "sequence_name", value = "ID_SEQUENCE"),
            @org.hibernate.annotations.Parameter(name = "increment_size", value = "100"),
            @org.hibernate.annotations.Parameter(name = "optimizer ", value = "pooled") })
    @GeneratedValue(generator = "uniqueIDGenerator")
    @NotNull
    protected int id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}

这是我的主要合作伙伴类:

Here is my main partner class:

@Entity
@Table(name = "partner")
public class Partner extends BaseEntity{

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

    @OneToMany(mappedBy="partner", fetch=FetchType.EAGER)
    @Cascade(CascadeType.DELETE)
    private List<Receipt> receipts;

    @OneToMany(mappedBy="partner", fetch=FetchType.EAGER)
    @Cascade(CascadeType.DELETE)
    private List<Delivery> deliveries;

    public Partner() {
        setReceipts(new ArrayList<Receipt>());
        setDeliveries(new ArrayList<Delivery>());
    }

    public Partner(String name){
        this();

        this.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Receipt> getReceipts() {
        return receipts;
    }

    public void setReceipts(List<Receipt> receipts) {
        this.receipts = receipts;
    }

    public List<Delivery> getDeliveries() {
        return deliveries;
    }

    public void setDeliveries(List<Delivery> deliveries) {
        this.deliveries = deliveries;
    }
}

合作伙伴有两个子类,Receipt和Delivery。这是收据类:

Partner has two subclasses, Receipt and Delivery. Here is the Receipt class:

@Entity
@Table(name = "receipt")
public class Receipt extends BaseEntity{

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="partnerId")
    private Partner partner;

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

    @Transient
    private ReceiptContainer receiptContainer;


    public Receipt() {
    }
    public Receipt(String name){
        this();

        this.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getJson() {
        return json;
    }

    public void setJson(String json) {
        this.json = json;
    }

    public ReceiptContainer getReceiptContainer() {
        return receiptContainer;
    }

    public void setReceiptContainer(ReceiptContainer receiptContainer) {
        this.receiptContainer = receiptContainer;
    }

    public Partner getPartner() {
        return partner;
    }

    public void setPartner(Partner partner) {
        this.partner = partner;
    }

}

这是交付类:

@Entity
@Table(name = "delivery")
public class Delivery extends BaseEntity{

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="partnerId")
    private Partner partner;

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

    @Transient
    private DeliveryContainer deliveryContainer;


    public Delivery() {
    }
    public Delivery(String name){
        this();

        this.setName(name);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getJson() {
        return json;
    }

    public void setJson(String json) {
        this.json = json;
    }

    public DeliveryContainer getDeliveryContainer() {
        return deliveryContainer;
    }

    public void setDeliveryContainer(DeliveryContainer deliveryContainer) {
        this.deliveryContainer = deliveryContainer;
    }

    public Partner getPartner() {
        return partner;
    }

    public void setPartner(Partner partner) {
        this.partner = partner;
    }

}

我得到像这样的对象:

@Transactional
public Partner get(int id){
    Partner partner = entityManager.find(Partner.class, id);
    return partner;
}

如您所见,合作伙伴类包括一个对象列表和一个列表对象,分别存储在他们自己的表中,接收和传递。

As you may see, the partner class includes a List of objects and a List of objects, which are stored in their own tables, receipt and delivery, respectively.

---在进一步讨论之前,我想指出数据库中显示的条目数正确。只有在我的Java应用程序中获取对象时才会出现此问题.---

---Before I go any further, I would like to note that the correct number of entries are displayed in the database. This issue only occurs when getting the objects in my Java app.---

当我添加一个对象但没有对象存在时,将显示一个对象,并且没有对象显示,这是预期的。如果存在一个对象和一个对象,则再次显示一个对象和一个对象,这是预期的。当存在多个或对象时,会发生此问题。例如,如果添加了两个对象但只添加了一个对象,则会显示两个对象和两个对象。

When I add one object and no objects are present, one object is displayed and no objects are displayed, which is expected. If one object and one objects exist, one object and one object are displayed, again, which is expected. The problem occurs when more than one or object are present. For example, if two objects are added but only one object is added, two objects AND two objects are displayed.

为了更好地说明这一点,请参阅下面的测试用例表。意外的结果用破折号包围。

To better illustrate this, see my test case table below. Unexpected results are surrounded with dashes.

<Receipt> Obj Added | <Delivery> Obj Added | <Receipt> Obj Displayed | <Delivery> Obj Displayed
         0          |          0           |           0             |            0
         0          |          1           |           0             |            1
         1          |          0           |           1             |            0
         1          |          1           |           1             |            1
         1          |          2           |        ---2---          |         ---2---
         2          |          1           |        ---2---          |         ---2---
         2          |          2           |        ---4---          |         ---4---

我的问题是,为什么我看到这些意想不到的结果?

My question is, why am I seeing these unexpected results?

推荐答案

您看到重复的原因是因为您正在急切地抓取正在创建外部联接的子项。

The reason you're seeing duplicates is because you're eagerly fetching the children, which is creating an outer join.

(您可以使用@Fetch(FetchMode.SELECT),但这会导致其他查询以检索您的商品)

(You could use @Fetch( FetchMode.SELECT), but this will result in additional queries to retrieve your items)

Hibernate API参考指示外连接需要地点。

以下是对您问题的深入解答: Hibernate Criteria使用FetchType.EAGER多次返回子项

Here is an in depth answer to your question: Hibernate Criteria returns children multiple times with FetchType.EAGER

您可以从List切换到Set(如果这样做,请确保覆盖equals / compareTo / hashCode)。或者,如果您通过条件从数据库中提取这些项目,则可以将结果转换器添加到查询结果中。

You can switch from List to Set (be sure you override equals/compareTo/hashCode if you do so). Or you can add a result transformer to your query results if you're extracting these items from the database via criteria.

对于它的价值,hibernate建议在列表上使用集合

For what its worth, hibernate recommends using sets over lists

这篇关于使用Hibernate获取重复条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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