简体   繁体   English

使用连接表在Hibernate中初始化多对多关联

[英]Initializing many-to-many association in Hibernate with join table

I have a Company entity that I fetch with a JPQL query with Hibernate. 我有一个Company实体,可以通过Hibernate的JPQL查询来获取。 The entity has a many-to-many association with a Keyword entity. 该实体与Keyword实体具有多对多关联。 Since the join table has an additional column is_active , this table has been mapped to a CompanyKeyword entity. 由于is_active表具有附加列is_active ,因此该表已映射到CompanyKeyword实体。 So the association is like this: 所以关联是这样的:

Company <-- CompanyKeyword --> Keyword 公司<-CompanyKeyword->关键字

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. 现在,来自Company实体的关联是惰性的,并且由于我想避免产生笛卡尔产品性能问题,因此我的JPQL查询初始化该关联。 That is why I want to initialize the association after running the JPQL query, eg like this: 这就是为什么我想运行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;
    }
}

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 , ie from Company to CompanyKeyword , and not from CompanyKeyword to Keyword . 但是,由于我在CompanyKeyword之间有一个实体,因此Hibernate将仅初始化关联第一部分 ,即从CompanyCompanyKeyword ,而不是从CompanyKeywordKeyword 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; 如果可能的话,我想坚持使用当前的方法,即使用JPQL查询来获取我的Company实体,然后再初始化某些关联; 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? 我应该使用第二个JPQL查询“手动”获取关联,还是有没有想到的更好的方法?

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 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
}

You'll indeed need to execute an additional JPQL query, fetching the company with its companyKeyWords and with the keyword of each CompanyKeyWord. 实际上,您确实需要执行一个附加的JPQL查询,并使用companyKeyWords和每个CompanyKeyWord的关键字来获取公司。

You could also doing it by simply looping and initializing every entity, and still avoid executing too many queries, by enabling batch fetching . 您还可以通过简单地循环和初始化每个实体来做到这一点,并且通过启用批处理提取仍然避免执行太多查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM