开发者

Traversing ORM relationships returns duplicate results

开发者 https://www.devze.com 2023-02-03 03:20 出处:网络
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.

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.


  1. Your getter catalogImages() does not follow Java Bean naming convention. I'm not sure, but it might confuse JPA provider somehow.
  2. By using Collection<CatalogImage> you've explicitly told JPA provider that duplicates are allowed. As it was already told, using Set instead of Collection solves duplicates-issue in most cases and allows avoiding FetchType.EAGER unless you really need it.
0

精彩评论

暂无评论...
验证码 换一张
取 消