java 使用 Hibernate 获取重复条目
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26763213/
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
Getting Duplicate Entries using Hibernate
提问by user1472409
I am experiencing a weird issue when using JPA/Hibernate. I am seeing duplicate entries during testing.
我在使用 JPA/Hibernate 时遇到了一个奇怪的问题。我在测试期间看到重复的条目。
Here is my BaseEntity class:
这是我的 BaseEntity 类:
@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;
}
}
Partner has two subclasses, Receipt and Delivery. Here is the Receipt class:
Partner 有两个子类,Receipt 和 Delivery。这是收据类:
@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;
}
}
Here is the Delivery class:
这是交付类:
@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;
}
}
I am getting my objects like this:
我得到这样的对象:
@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.
如您所见,合作伙伴类包括一个 List of objects 和一个 List of objects,它们分别存储在自己的表、收货和交货表中。
---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.---
---在我继续之前,我想注意数据库中显示的条目数是正确的。只有在我的 Java 应用程序中获取对象时才会出现此问题。---
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?
我的问题是,为什么我会看到这些意想不到的结果?
回答by zmf
The reason you're seeing duplicates is because you're eagerly fetching the children, which is creating an outer join.
您看到重复项的原因是因为您急切地获取子项,这正在创建外部联接。
(You could use @Fetch( FetchMode.SELECT), but this will result in additional queries to retrieve your items)
(您可以使用@Fetch(FetchMode.SELECT),但这会导致额外的查询来检索您的项目)
Hibernate API reference indicating outer join takes place.
Here is an in depth answer to your question: Hibernate Criteria returns children multiple times with FetchType.EAGER
这是对您的问题的深入回答:Hibernate Criteria 使用 FetchType.EAGER 多次返回子项
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.
您可以从 List 切换到 Set(如果这样做,请确保覆盖 equals/compareTo/hashCode)。或者,如果您通过条件从数据库中提取这些项目,则可以将结果转换器添加到查询结果中。
For what its worth, hibernate recommends using sets over lists
就其价值而言,hibernate 建议使用集合而不是列表
回答by Gernan
Maybe you can try doing your query using DISTINCT property.
也许您可以尝试使用 DISTINCT 属性进行查询。
Simply add this to your criteria:
只需将此添加到您的标准中:
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
If you are not using criteria:
如果您不使用标准:
SELECT DISTINCT <QUERY>
If it doesn't solve your problem, show your query code.
如果它不能解决您的问题,请显示您的查询代码。
回答by ToYonos
You could store the result of your query in a Set
, it will remove duplicate for you.
您可以将查询结果存储在 a 中Set
,它将为您删除重复项。
回答by dieter
If you are using JPA:
如果您使用的是 JPA:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Receipt> query = cb.createQuery(Receipt.class);
query.distinct(true);
otherwise see Gernan's answer.
否则请参阅 Gernan 的回答。