My domain has a Category entity which has a biderectional relationship on itself. Each category can have a parent and children.
@Entity
public class Category implements DomainObject {
private Long id;
private Integer version;
private String name;
private Category parent;
private Set<Category> children;
@Override
@Id
@GeneratedValue
public final Long getId() {
return id;
}
@Version
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
public void setId(Long id) {
this.id = id;
}
@Column(unique=true, nullable=false)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne
public Category getParent() {
return parent;
}
public void setParent(Category parent) {
this.parent = parent;
}
@OneToMany
@JoinColumn(name = "parent_id")
public Set<Category> getChildren() {
return children;
}
public void setChildren(Set<Category> children) {
this.children = children;
}
}
I have created the following query to fetch the “root” categories with their direct (level 1) children.
select distinct c from Category c left join fetch c.children where c.parent is null order by c.name
This actually works. My question is: why do I need the “JoinColumn” annotation on getChildren() to make this work and why can’t I just make a “foin fetch” query, without “distinct”? If I remove “distinct” I get a multiplication. For each child of a parent, the entire parent is copied in the result set.
Is there a better way to do this? It just feels… a bit crappy.
In JPA you need to set distinct when you join a OneToMany, otherwise it will return duplicates.
This is required.
The JPA spec requires this, but it is an odd default, but relates to what happens in database joins.