在 Hibernate 中使用连接表初始化多对多关联
Posted
技术标签:
【中文标题】在 Hibernate 中使用连接表初始化多对多关联【英文标题】:Initializing many-to-many association in Hibernate with join table 【发布时间】:2015-04-11 17:07:04 【问题描述】:我有一个Company
实体,我通过 Hibernate 的 JPQL 查询获取该实体。该实体与Keyword
实体具有多对多关联。由于连接表有一个附加列is_active
,因此该表已映射到CompanyKeyword
实体。所以关联是这样的:
公司 关键字
现在,来自Company
实体的关联是惰性的,它不是由我的 JPQL 查询初始化的,因为我想避免产生笛卡尔积性能问题。这就是为什么我想在运行 JPQL 查询之后初始化关联 ,例如像这样:
@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;
对于“正常”的多对多关联,这会很有效,因为所有关联的实体都将在单个查询中获取。然而,由于我在Company
和Keyword
之间有一个实体,所以Hibernate 只会初始化关联的第一部分,即从Company
到CompanyKeyword
,而不是从CompanyKeyword
到Keyword
。我希望这是有道理的。我正在寻找一种方法来初始化这个关联,而不必做这样的事情:
Company company = this.companyRepository.findOneWithSomeCustomQuery(companyId);
Hibernate.initialize(company.getCompanyKeywords());
for (CompanyKeyword ck : company.getCompanyKeywords())
Hibernate.initialize(ck.getKeyword());
上面的代码既不干净,在性能方面也不好。如果可能的话,我想坚持我目前使用 JPQL 查询来获取我的 Company
实体然后初始化某些关联的方法;在我的项目中改变这一点需要相当多的重构。我应该只是“手动”获取与第二个 JPQL 查询的关联,还是有我没有想到的更好的方法?
以下是我的映射。提前致谢!
公司
@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
公司关键字
@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
公司关键字PK
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()
关键字
@Entity
@Table(name = "keyword")
public class Keyword
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private int id;
// Fields and getters/setters
【问题讨论】:
【参考方案1】:您确实需要执行额外的 JPQL 查询,获取公司及其 companyKeyWords 和每个 CompanyKeyWord 的关键字。
您也可以通过简单地循环和初始化每个实体来做到这一点,并且仍然可以通过启用 batch fetching 来避免执行过多的查询。
【讨论】:
以上是关于在 Hibernate 中使用连接表初始化多对多关联的主要内容,如果未能解决你的问题,请参考以下文章