Hibernate CollectionOfElements EAGER fetch duplicates elements

后端 未结 6 1877
礼貌的吻别
礼貌的吻别 2020-12-04 11:28

I have a class called SynonymMapping which has a collection of values mapped as a CollectionOfElements

@Entity(name = \"synonymmapping\")
public class Synony         


        
相关标签:
6条回答
  • 2020-12-04 11:47

    It's generally not a good idea to enforce eager fetching in the mapping - it's better to specify eager joins in appropriate queries (unless you're 100% sure that under any and all circumstances your object won't make sense / be valid without that collection being populated).

    The reason you're getting duplicates is because Hibernate internally joins your root and collection tables. Note that they really are duplicates, e.g. for 2 SynonymMappings with 3 collection elements each you would get 6 results (2x3), 3 copies of each SynonymMapping entity. So the easiest workaround is to wrap results in a Set thereby ensuring they're unique.

    0 讨论(0)
  • 2020-12-04 11:50

    Instead of FetchMode.SELECT with N+1 queries it is better using BatchSize e.q. @BatchSize(size = 200).

    DISTINCT and Criteria.DISTINCT_ROOT_ENTITY doesn't help, if you have to fetch more than 1 association. For this case see other solutions: https://stackoverflow.com/a/46013654/548473

    0 讨论(0)
  • 2020-12-04 12:01

    I stepped into the same problem - when you set the FetchType.EAGER for a @CollectionOfElements, the Hibernate tries to get everything in one shot, i.e. using one single query for each entry of element linked to a "master" object. This problem can be successfully solved at a cost of N+1 query, if you add the @Fetch (FetchMode.SELECT) annotation to your collection. In my case I wanted to have a MediaObject entity with a collection of its metadata items (video codec, audio codec, sizes, etc.). The mapping for a metadataItems collection looks as follows:

    
    @CollectionOfElements (targetElement = String.class, fetch = FetchType.EAGER)
    @JoinTable(name = "mo_metadata_item", joinColumns = @JoinColumn(name = "media_object_id"))
    @MapKey(columns = @Column(name = "name"))
    @Column (name = "value")
    @Fetch (FetchMode.SELECT)
    private Map<String, String> metadataItems = new HashMap<String, String>();
    
    0 讨论(0)
  • 2020-12-04 12:06

    I have achieved it via simply add

    session.createCriteria(ModelClass.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
    

    This help to remove duplicate.

    0 讨论(0)
  • 2020-12-04 12:10

    I have faced this problem and I solved it using

    criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

    This clears out the duplicates which are caused by the join made to the child tables.

    0 讨论(0)
  • 2020-12-04 12:10

    You could use a SELECT DISTINCT (Hibernate Query Language) clause as follows

    SELECT DISTINCT synonym FROM SynonymMapping synonym LEFT JOIN FETCH synonym.values
    

    DISTINCT clause removes duplicate references in Hibernate.

    Although both component and value-type collection has its lifecycle bound to the owning entity class, you should declare them in select clause in order to retrieve them. (LEFT JOIN FETCH synonym.values)

    ChssPly76's answer is another approach, but does not forget override equals and hashcode method according to Set semantic

    regards,

    0 讨论(0)
提交回复
热议问题