I have a Company
entity that I fetch with a JPQL query with Hibernate. The entity has a many-to-many association with a Keyword
entity. Since the join table has an additional column is_active
, this table has been mapped to a CompanyKeyword
entity. So the association is like this:
Company <-- CompanyKeyword --> Keyword
Now, the association from the Company
entity is lazy, and it is not initialized by my JPQL query, as I want to avoid creating a cartesian product performance problem. That is why I want to initialize the association after running the JPQL query, e.g. like this:
@Service
class CompanyServiceImpl implements CompanyService {
@Autowired
private CompanyRepository companyRepository;
@Transactional
public Company findOne(int companyId) {
Company company = this.companyRepository.findOneWithSomeCustomQuery(companyId);
Hibernate.initialize(company.companyKeywords());
return company;
}
}
For a "normal" many-to-many association, this would work great, as all of the associated entities would be fetched in a single query. However, since I have an entity between Company
and Keyword
, Hibernate will only initialize the first part of the association, i.e. from Company
to CompanyKeyword
, and not from CompanyKeyword
to Keyword
. I hope that makes sense. I am looking for a way to initialize this association all the way without having to do something like this:
Company company = this.companyRepository.findOneWithSomeCustomQuery(companyId);
Hibernate.initialize(company.getCompanyKeywords());
for (CompanyKeyword ck : company.getCompanyKeywords()) {
Hibernate.initialize(ck.getKeyword());
}
The above code is neither clean, nor good in terms of performance. If possible, I would like to stick to my current approach of using a JPQL query to fetch my Company
entity and then initializing certain associations afterwards; it would take quite a bit of refactoring to change this in my project. Should I just "manually" fetch the association with a second JPQL query, or is there a better way of doing it that I haven't thought of?
Below are my mappings. Thanks in advance!
Company
@Entity
@Table(name = "company")
public class Company implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private int id;
@Size(max = 20)
@OneToMany(fetch = FetchType.LAZY, mappedBy = "company")
private Set<CompanyKeyword> companyKeywords = new HashSet<>();
// Getters and setters
}
CompanyKeyword
@Entity
@Table(name = "company_service")
@IdClass(CompanyServicePK.class)
public class CompanyKeyword implements Serializable {
@Id
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Company.class)
@JoinColumn(name = "company_id")
private Company company;
@Id
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Keyword.class)
@JoinColumn(name = "keyword_id")
private Keyword keyword;
@Column(nullable = true)
private boolean isActive;
// Getters and setters
}
CompanyKeywordPK
public class CompanyServicePK implements Serializable {
private Company company;
private Service service;
public CompanyServicePK() { }
public CompanyServicePK(Company company, Service service) {
this.company = company;
this.service = service;
}
// Getters and setters
// hashCode()
// equals()
}
Keyword
@Entity
@Table(name = "keyword")
public class Keyword {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private int id;
// Fields and getters/setters
}