首页 > 解决方案 > 与@IdClass 的多对一关系

问题描述

使用 Spring Data JPA & Hibernate,我正在保存一个对象 Company,它具有 0 到多个 AccountMapping。AccountMappings 主键是字符串 accountNumber 和公司主键的组合。当我保存新公司时,公司对象中的 COMP_NUM 未设置到 AccountMapping 对象中。当我使用 long companyNumber 时,它是零,而 Long 是 NUM。Hibernate首先执行插入语句,但是如何让它将主键从公司设置为子对象?

@Entity
@Table(name = "COMPANY")
public class Company implements Serializable {

    @Id
    @Column(name = "COMP_NUM")
    @SequenceGenerator(name = "comp_num_seq", sequenceName = "comp_num_seq", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "comp_num_seq")
    private long number;

    @OneToMany(mappedBy = "companyNumber", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<AccountMapping> accountMappings;
    
    public Company() {
        super();
    }

    public long getNumber() {
        return this.number;
    }

    public void setNumber(long id) {
        this.number = id;
    }

    public List<AccountMapping> getAccountMappings() {
        return accountMappings;
    }

    public void setAccountMappings(List<AccountMapping> accountMappings) {
        this.accountMappings = accountMappings;
    }     
}

@Entity
@IdClass(value = AccountMappingPK.class)
@Table(name = "ACCOUNT_MAPPING")
public class AccountMapping implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ACCNT_NUM")
    private String accountNumber;

    @Id
    @Column(name = "COMP_NUM")
    private Long companyNumber;
   
    @Column(name = "IS_PRIMARY")
    private Boolean isPrimary;

    public String getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNumber(String accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Long getCompanyNumber() {
        return companyNumber;
    }

    public void setCompanyNumber(Long companyNumber) {
        this.companyNumber = companyNumber;
    }

    public Boolean getIsPrimary() {
        return isPrimary;
    }

    public void setIsPrimary(Boolean isPrimary) {
        this.isPrimary = isPrimary;
    }

}

public class AccountMapping implements Serializable {

    @Column(name = "EA_ACCNT_NUM", nullable = false)
    private String accountNumber;

    @Column(name = "COMP_NUM", nullable = false)
    private Long companyNumber;

    public AccountMapping() {
        // default constructor
    }
    
    public String getAccountNumber() {
        return accountNumber;
    }

    public void setAccountNum(String accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Long getCompanyNumber() {
        return companyNumber;
    }

    public void setCompanyNumber(Long companyNumber) {
        this.companyNumber = companyNumber;
    }    

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof AccountMappingPK) {
            AccountMappingPK accntPk = (AccountMappingPK) obj;

            if (!(accountNumber.equals(accntPk.getAccountNumber()))) {
                return false;
            }

            if (!(accntPk.getCompanyNumber() == (companyNumber))) {
                return false;
            }

            return true;
        }

        return false;
    }

    @Override
    public int hashCode() {
        int hash = (accountNumber == null ? 1 : accountNumber.hashCode());
        return (int) (hash * companyNumber);
    }

}

标签: spring-boothibernatespring-data-jpa

解决方案


@Entity
@IdClass(value = AccountMappingPK.class)
@Table(name = "ACCOUNT_MAPPING")
public class AccountMapping implements Serializable {

    @Id
    @Column(name = "ACCNT_NUM")
    private String accountNumber;

    @Id
    @ManyToOne
    @JoinColumn(name = "COMP_NUM")
    private Company company;

    ...
}

// No annotations in this class
public class AccountMappingPK implements Serializable {

    private String accountNumber;

    private Company company;

    ...
    // All the getter/setter, constructors, and so on ...

}

Hibernate ORM 文档有更多关于映射的详细信息@IdClass:参见示例 134。带有 @ManyToOne 的 IdClass


推荐阅读