Traversing ORM relationships returns duplicate results
I have 4 tables -- store, catalog_galleries, catalog_images, and catalog_financials
.
When I traverse the relationship from store --> catalog_galleries --> catalog_images
in other words: store.getCatalogGallery().getCatalogImages()
I get duplicate records. Does anyone know what could be the cause of this? Any suggestions on where to look?
The store
table has a OneToOne
relationship with catalog_galleries
which in turn has a OneToMany
relationship with catalog_images
and an eager fetch type. The store
table also has a OneToMany
relationship with catalog_financials
.
Below are the relevant entities:
Store entity
@Entity
@Table(name="store")
public class Store {
...
private CatalogGallery gallery;
...
@OneToOne(mappedBy="store")
public CatalogGallery getGallery() {
return gallery;
}
}
CatalogGallery entity
@Entity
@Table(name="catalog_galleries")
public class CatalogGallery {
...
private Store store;
private Collection<CatalogImage> catalogImages;
...
@OneToOne
@PrimaryKeyJoinColumn
public Store getStore() {
return store;
}
@OneToMany(mappedBy="catalogGallery", fetch=FetchType.EAGER)
public Collection<CatalogImage> getCatalogImages {
return catalogImages;
}
}
CatalogImage entity
@Entity
@Table(name="catalog_images")
public class CatalogImage {
...
private 开发者_如何学运维CatalogGallery catalogGallery;
...
@ManyToOne
@JoinColumn(name="gallery_id", insertable=false, updatable=false)
public CatalogGallery getCatalogGallery() {
return catalogGallery;
}
}
This is because of your fetch = FetchType.EAGER
.
Hibernate creates JOINs and tries to get all your collections with one query.
If you really need FetchType.EAGER
and don't want to replace your collection with Set you can use @Fetch (FetchMode.SELECT)
annotation for your collection:
@OneToMany(mappedBy="catalogGallery", fetch=FetchType.EAGER)
@Fetch (FetchMode.SELECT)
public Collection<CatalogImage> getCatalogImages {
return catalogImages;
}
For more information see this post
If you implement the equals and hashcode methods correctly and store in a Set rather than a Collection, it is less of an issue unless the volume of duplicates is excessive.
- Your getter
catalogImages()
does not follow Java Bean naming convention. I'm not sure, but it might confuse JPA provider somehow. - By using
Collection<CatalogImage>
you've explicitly told JPA provider that duplicates are allowed. As it was already told, usingSet
instead ofCollection
solves duplicates-issue in most cases and allows avoidingFetchType.EAGER
unless you really need it.
精彩评论