【问题标题】:JPA entity resultset duplication with more than one collection具有多个集合的 JPA 实体结果集重复
【发布时间】:2015-01-18 10:52:07
【问题描述】:

Contact 实体定义了与两个 MySQL 表中存在的电子邮件和昵称类型的两个实体集合的关系。

我的问题是返回的结果集包含重复的电子邮件和昵称。

{
  "contactId": 1,
  "givenName": "toast",
  "middleName": "brown",
  "familyName": "jam",
  "dob": "2014-11-19",
  "contactEmailAddress": [
    {
      "emailAddressId": 1,
      "emailAddress": "donald.duck@disney.com",
      "contactId": 1
    },
    {
      "emailAddressId": 1,
      "emailAddress": "donald.duck@disney.com",
      "contactId": 1
    },
    {
      "emailAddressId": 2,
      "emailAddress": "mickey.mouse@disney.com",
      "contactId": 1
    },
    {
      "emailAddressId": 2,
      "emailAddress": "mickey.mouse@disney.com",
      "contactId": 1
    }
  ],
  "contactNickname": [
    {
      "contactNicknameId": 1,
      "nickname": "mm",
      "contactId": 1
    },
    {
      "contactNicknameId": 2,
      "nickname": "mouse",
      "contactId": 1
    },
    {
      "contactNicknameId": 1,
      "nickname": "mm",
      "contactId": 1
    },
    {
      "contactNicknameId": 2,
      "nickname": "mouse",
      "contactId": 1
    }
  ]
}

如果我从 Contact 实体中删除 ContactNickname 集合,结果集如下。

{
  "contactId": 1,
  "givenName": "toast",
  "middleName": "brown",
  "familyName": "jam",
  "dob": "2014-11-19",
  "contactEmailAddress": [
    {
      "emailAddressId": 1,
      "emailAddress": "donald.duck@disney.com",
      "contactId": 1
    },
    {
      "emailAddressId": 2,
      "emailAddress": "mickey.mouse@disney.com",
      "contactId": 1
    }
  ]
}

我希望有一组不同的电子邮件地址和一组不同的昵称,但事实并非如此。我在做什么不正确。

使用 JPA,我将类映射如下。

@Entity
@Table(name="contact")
public class Contact implements Serializable {    
    @OneToMany(fetch=FetchType.EAGER)
    @JoinColumn(name="contact_id")
    private Collection<ContactEmailAddress> contactEmailAddress;

    @OneToMany(fetch=FetchType.EAGER)
    @JoinColumn(name="contact_id")
    private Collection<ContactNickname> contactNickname;

    public Collection<ContactEmailAddress> getContactEmailAddress(){
        return this.contactEmailAddress;
    }

    public void setContactEmailAddress(Collection<ContactEmailAddress> contactEmailAddress){        
        this.contactEmailAddress=contactEmailAddress;
    }

    public Collection<ContactNickname> getContactNickname(){
        return this.contactNickname;
    }

    public void setContactNickname(final Collection<ContactNickname> contactNickname){
        this.contactNickname=contactNickname;
    }    
}
@Entity
@Table(name="contact_email_address")
public class ContactEmailAddress implements Serializable {   
    @Id
    @GeneratedValue
    @Column(name="email_address_id")
    private int emailAddressId;

    @Column(name="email_address")
    private String emailAddress;

    @Column(name="contact_id")
    private int contactId;

  public void setContactId(int contactId){
        this.contactId=contactId;
    }

    public int getContactId(){
        return this.contactId;
    }.

   public int getEmailAddressId(){
        return emailAddressId;
    }

    public void setEmailAddressId(final int emailAddressId){
        this.emailAddressId=emailAddressId;
    }

    public String getEmailAddress(){
        return emailAddress;
    }

    public void setEmailAddress(String emailAddress){
        this.emailAddress=emailAddress;
    }
}
@Entity
@Table(name="contact_nickname")
public class ContactNickname implements Serializable {
    @Id
    @GeneratedValue
    @Column(name="contact_nickname_id")
    private int contactNicknameId;

    @Column(name="nickname")
    private String nickname;

    @Column(name="contact_id")
    private int contactId; 

    public int getContactNicknameId(){
        return contactNicknameId;
    }

    public void setContactNicknameId(final int contactNicknameId){
        this.contactNicknameId=contactNicknameId;
    }

    public String getNickname(){
        return this.nickname;
    }

    public void setNickname(String nickname){
        this.nickname=nickname;
    }    

    public void setContactId(int contactId){
        this.contactId=contactId;
    }

    public int getContactId(){
        return this.contactId;
    }
}

当复制发生时,Hibernate 正在运行以下内容。

SELECT contact0_.contact_id             AS contact_1_0_0_, 
       contact0_.dob                    AS dob2_0_0_, 
       contact0_.family_name            AS family_n3_0_0_, 
       contact0_.given_name             AS given_na4_0_0_, 
       contact0_.middle_name            AS middle_n5_0_0_, 
       contactema1_.contact_id          AS contact_2_0_1_, 
       contactema1_.email_address_id    AS email_ad1_1_1_, 
       contactema1_.email_address_id    AS email_ad1_1_2_, 
       contactema1_.contact_id          AS contact_2_1_2_, 
       contactema1_.email_address       AS email_ad3_1_2_, 
       contactnic2_.contact_id          AS contact_2_0_3_, 
       contactnic2_.contact_nickname_id AS contact_1_3_3_, 
       contactnic2_.contact_nickname_id AS contact_1_3_4_, 
       contactnic2_.contact_id          AS contact_2_3_4_, 
       contactnic2_.nickname            AS nickname3_3_4_ 
FROM   contact contact0_ 
       LEFT OUTER JOIN contact_email_address contactema1_ 
                    ON contact0_.contact_id = contactema1_.contact_id 
       LEFT OUTER JOIN contact_nickname contactnic2_ 
                    ON contact0_.contact_id = contactnic2_.contact_id 
WHERE  contact0_.contact_id =? 

亲切的问候, 伊恩。

【问题讨论】:

  • 基本上你正在尝试做一个单向的oneToMany映射;您缺少一个“referencedColumnName”属性,正如这个非常相似的问题中所解释的那样:stackoverflow.com/questions/12038380/…
  • @Gimby 设置 referencedColumnName="contact_id" 时我仍然得到相同的结果集
  • 嗯。只是为了排除可能性:当您从集合中删除 EAGER 获取时,是否会发生任何变化?
  • @Gimby 我目前得到 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role... Contact.contactEmailAddress,无法初始化代理 - 没有会话
  • @Gimby 在将两个集合都设置为惰性然后在事务关闭之前对它们都调用 size() 之后,Jackson 生成了没有实体重复的正确 JSON。所以一切都很好。为什么急切加载集合会生成重复。

标签: java hibernate jpa duplication


【解决方案1】:

如果您不想在集合中出现重复项,则应在实体中使用 Set 而不是 Collection

【讨论】:

    猜你喜欢
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多