Skip to content
Advertisement

hibernate multiple @OneToMany relationships generating more results in parent relationship

I will start with the result. In the next image I am displaying the result content of company.userAccount. In the database I have only two companies assigned to the same user and 7 services attached to one of the companies.

enter image description here

@Entity
@Table(name = "user_account")
@Data
@Introspected
@JsonIgnoreProperties(value = {"id"})
public class UserAccount {
    ...

    @OneToMany(mappedBy = "userAccount", fetch = FetchType.EAGER)
    private List<Company> companies = new ArrayList<>();

}


@Entity
@Table(name = "company")
@Data
@Introspected
@ToString(exclude = {"userAccount"})
@JsonIgnoreProperties(value = {"id", "userAccount"})
public class Company {
    ...

    @ManyToOne(optional = false)
    @JoinColumn(name = "user_account_id", updatable = false, nullable = false)
    private UserAccount userAccount;

}


@Entity
@Table(name = "service")
@Data
@Introspected
@ToString(exclude = {"company"})
@JsonIgnoreProperties(value= {"id", "company"})
public class Service {
    ...

    @ManyToOne(optional = false)
    @JoinColumn(name = "company_id", updatable = false, nullable = false)
    private Company company;

}


@Transactional
public Service saveService(@Valid @Uuid UUID companyUuid, SaveServiceCommand command) {
    Company company = companyRepository.getCompanyByUuid(companyUuid).orElseThrow(() -> new NoSuchElementException("unrecognized company"));

    Service service = new Service();
    service.setCompany(company);
    service.setName(command.getName());
    service.setUuid(UUID.randomUUID().toString());

    return companyRepository.saveCompanyService(service);
}

@Transactional
public Service saveCompanyService(@Valid Service service) {
    entityManager.persist(service);
    return service;
}

The generated query (simplified) is

select * from user_account a left outer join company c on a.id=c.user_account_id left outer join service s on c.id=s.company_id; 

This will generate

enter image description here

Expected result: I was expecting in the UserAccount to see only 2 companies and in one of the companies to have 6 services. Why do I have this result? Why is the same company object multiple times in the list? How can I avoid this?

I believe that one solution would be to change the fetching type of the @OneToMany relationships to LAZY (as they are default) (already tested this solution and it works) but what if I need this type of scenario?

Advertisement

Answer

Yes, there are 2 companies, just like you said. You can notice, that all objects are the same (hashes match). The reason behind this is that the query generates 6 rows for one company and PersistenceBag used by hibernate does not remove duplicates by default. Passing distinct to your sql would not work, because there is only one parent entity.

But this can be achieved by using hibernate’s query hints. Passing QueryHints.HINT_PASS_DISTINCT_THROUGH to your Query simply removes duplicated children.

For more information you can refer to this source.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement