JPA、Spring、Hibernate 加载实体 OneToMany 关联的问题

Posted

技术标签:

【中文标题】JPA、Spring、Hibernate 加载实体 OneToMany 关联的问题【英文标题】:JPA, Spring, Hibernate problem with loading entities ManyToMany Assotiation 【发布时间】:2010-08-24 15:37:53 【问题描述】:

我正在尝试从关联 N:N 获取数据,但我收到空白字段。 还有我的 Hibernate 映射类:

@Entity
@Table(name = "companies")
public class Company extends NamedEntity 
 //some_code

@ManyToMany(
        targetEntity = com.hqcargo.shippingstock.domain.CompanyProfile.class,
        cascade = CascadeType.ALL, CascadeType.ALL ,
        fetch = FetchType.EAGER
        )
@JoinTable(
        name = "company_company_profiles",
        joinColumns = @JoinColumn(
                        name = "company_id",
                        referencedColumnName = "id") ,
        inverseJoinColumns = @JoinColumn(
                        name = "company_profile_id",
                        referencedColumnName = "id") 
        )
private List<CompanyProfile> profiles;
// getters and setters + other code

其他类:

@Entity
@Table(name = "company_profiles")
public class CompanyProfile extends NamedEntity 
//some_code
@ManyToMany(
        targetEntity = com.hqcargo.shippingstock.domain.Company.class,
        cascade = CascadeType.ALL, CascadeType.ALL , 
        mappedBy = "profiles",
        fetch = FetchType.EAGER
        )
@JoinTable(
        name = "company_company_profiles",
        joinColumns = @JoinColumn(
                        name = "company_profile_id",
                        referencedColumnName = "id") ,
        inverseJoinColumns = @JoinColumn(
                        name = "company_id",
                        referencedColumnName = "id") 
        )
 private List<Company> companies;
 // getters and setters + other code

这些类可以很好地保存数据,但不能用于加载数据。 下面我添加DAO类:

public class CompanyJpaDAO extends JpaDaoSupport
implements CompanyDAO 

@Transactional(readOnly = true)
public Company readById(Long id) 
    Company tempCompany = getJpaTemplate().find(Company.class, id);
    return tempCompany;
    


@Transactional
public void update(Company existingInstance) 
    if (existingInstance.isNew()) 
        throw new InvalidDataAccessApiUsageException(
            "Can't update record. Given instance don't have assigned ID");
    
    save(existingInstance);

当我更新每个都可以(由 Hibernate 生成的 sql):

251252 [13627369@qtp-8132032-9] DEBUG org.hibernate.SQL  -
update
    companies
set
    name=?,
where
    id=?
Hibernate:
update
    companies
set
    name=?,
where
    id=?
251295 [13627369@qtp-8132032-9] DEBUG org.hibernate.SQL  -
insert
into
    company_company_profiles
    (company_id, company_profile_id)
values
    (?, ?)
Hibernate:
insert
into
    company_company_profiles
    (company_id, company_profile_id)
values
    (?, ?)

但是当我加载数据时,我没有从 company_company_profiles(Hibernate 生成的 sql)中获取信息

36088 [13507994@qtp-8132032-13] DEBUG org.hibernate.SQL  -
select
    companies0_.company_profile_id as company2_8_,
    companies0_.company_id as company1_8_,
    company1_.id as id3_0_,
    company1_.name as name3_0_,
from
    company_company_profiles companies0_
left outer join
    companies company1_
        on companies0_.company_id=company1_.id
where
    companies0_.company_profile_id=?
Hibernate:
select
    companies0_.company_profile_id as company2_8_,
    companies0_.company_id as company1_8_,
    company1_.id as id3_0_,
    company1_.name as name3_0_,
from
    company_company_profiles companies0_
left outer join
    companies company1_
        on companies0_.company_id=company1_.id
where
    companies0_.company_profile_id=?

您发现我的代码中有任何错误吗?

【问题讨论】:

【参考方案1】:

我不确定这是否是问题的原因,但您不应该在多对多关联的两侧指定 JoinTable。根据 JPA 规范,JoinTable 注释位于关联的拥有方(在您的情况下为 Company):

9.1.25 JoinTable 注解

JoinTable 注解用于 关联的映射。一种 JoinTable 注释指定在 多对多的拥有方 关联,或单向 一对多关联。

所以在CompanyProfile实体中删除它:

@Entity
@Table(name = "company_profiles")
public class CompanyProfile extends NamedEntity 
    //some_code
    @ManyToMany(
        targetEntity = com.hqcargo.shippingstock.domain.Company.class,
        cascade = CascadeType.ALL, CascadeType.ALL , 
        mappedBy = "profiles",
        fetch = FetchType.EAGER
    )
    private List<Company> companies;
    // getters and setters + other code

然后再试一次。

参考文献

JPA 1.0 规范 第 2.1.8.4 节“双向多对多关系” 第 9.1.25 节“JoinTable 注释” 第 9.1.26 节“ManyToMany 注释”

【讨论】:

以上是关于JPA、Spring、Hibernate 加载实体 OneToMany 关联的问题的主要内容,如果未能解决你的问题,请参考以下文章

从 JPA/Hibernate 中的视图加载实体

JPA/Spring/Hibernate/etc 中是不是有类似于 JPA 的 @PrePersist 允许更改相关实体的功能?

保存后刷新并获取实体(JPA/Spring Data/Hibernate)

如何使用 Spring Data JPA(Hibernate) 跨映射表过滤关联实体?

Spring JPA,Hibernate 仅从其他实体获取 PK 或 Id

EAGER 和分页:Spring MVC + JPA Repository + Hibernate