0

我正在寻找好的做法和干净的解决方案来解决我的问题。有2个实体类:

@Entity
public class Site implements Serializable {
  ...
  @OneToMany(mappedBy = "site")
  private List<SiteIp> siteIpList;
  ...
  public List<SiteIp> getSiteIpList() {
    return siteIpList;
  }
  public void setSiteIpList(List<SiteIp> siteIpList) {
    this.siteIpList = siteIpList;
  }
}

@Entity
@IdClass(SiteIpPK.class)
public class SiteIp implements Serializable {

  @Id
  @ManyToOne(fetch = FetchType.LAZY)
  private Site site;

  @Id
  private int idx;

  private String ip;

  /* other stuff such as constructors, getters and setters */

}

SiteIpPK 有 2 列,应该是干净的 :) 显然,这是世界上常用的模型。

接下来,有一个视图层。JSF 页面有 3 个字段显示给定站点和 idx 的 SiteIp.ip。到目前为止,我已经在 Site 实体上编写了 helper getter 方法:

public String getIpForIdx(Integer idx) {
  // there's no simple siteIpList.get(idx), because of additional logic in getter
  // so let's iterate through entire list

  for (SiteIp siteIp : this.siteIpList) {
    if (/* other logic returns true value && */ siteIp.getIdx() == idx) {
      return siteIp.getIp();
    }
  }

  return null;
}

JSF 表达式语言的构造如下:

<h:inputText id="sync1_ip" value="#{siteController.editContext.site.getIpForIdx(1)}" />

现在,当页面被访问时,正确的 IP 值被传播到输入文本字段,到目前为止一切都很好。但是,当 IP 更改并提交表单时,EL 会抛出异常:

javax.el.PropertyNotWritableException: /edit/siteEdit.xhtml @47,123 value="#{siteController.editContext.site.getIpForIdx(1)}": Illegal Syntax for Set Operation

我理解并承认这一点,所以我的问题是:

处理此问题的最佳做法是什么?有点糟糕的解决方案是编写与存在唯一索引一样多的辅助方法:

public String getIp1() {
    return this.IpForIdx(1);
}
public String getIp2() {
    return this.IpForIdx(2);
}
/* ... */

public void setIp1(String newIp) {
    this.siteIpList.add(1, newIp);
}
public void setIp2(String newIp) {
    this.siteIpList.add(2, newIp);
}
/* ... and so on... */

使用 JSF EL:

<h:inputText id="sync1_ip" value="#{siteController.editContext.site.ip1}" />

还有其他更灵活、更美观的解决方案吗?

4

1 回答 1

1

您最好在 google 上搜索“使用 JPA 的复合主键”。但由于您是新来的,下面是一个简单的解释和一个可行的解决方案。

小解释

复合主键本身就是带有@Embeddable注释的类。@Entity一旦您用 .标记您的主复合键字段,它们就会成为您班级中的主键@EmbeddedId。剩下的唯一一件事就是在两个类中实现equalshashcode适当地实现。

解决方案

解决方案包括一个@Entity

@Entity
@Table(name="...")
@AssociationOverride(name = "pk.site", joinColumns = @JoinColumn(name = "..."))
public class SiteIp implements Serializable {

    private SiteIpPk pk = new SiteIpPK();
    private String ip;

    public SiteIp() {   }

    @EmbeddedId
    public SiteIpPK getPk() {
        return pk;
    }
    public void setPk(SiteIpPk pk) {
        this.pk = pk;
    } 

    @Transient
    public Site getSite() {
        return pk.getSite();
    }
    public void setSite(Site site) {
        pk.setSite(site);
    }

    @Transient
    public Integer getIdx() {
        return pk.getIdx();
    }
    public void setIdx(Integer idx) {
        pk.setIdx(idx);
    }

    @Column(name="...")
    public String getIp() {
        return ip;
    }
    public void setIp(String ip) {
        this.ip = ip;
    }

    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        SiteIp that = (SiteIp) o;
        if (pk != null ? !pk.equals(that.pk) : that.pk != null)
            return false;
        return true;
    }

    public int hashCode() {
        return (pk != null ? pk.hashCode() : 0);
    }

}

@Embeddable班级

@Embeddable
public class SiteIpPk implements Serializable {

    private Site site;
    private Integer idx;

    @ManyToOne
    public Site getSite() {
        return site();
    }
    public void setSite(Site site) {
        this.site = site;
    }

    @Column(name="...", nullable = false)
    public Integer getIdx() {
        return idx;
    }
    public void setIdx(Integer idx) {
        this.idx = idx;
    }

    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        SiteIpPk that = (SiteIpPk) o;
        if (site != null ? !site.equals(that.site) : that.site != null)
            return false;
        if (idx != null ? !idx.equals(that.idx) : that.idx != null)
            return false;
        return true;
    }

    public int hashCode() {
        int result;
        result = (site != null ? site.hashCode() : 0);
        result = 17 * result + (idx != null ? idx.hashCode() : 0);
        return result;
    }

}

最后,自己了解更多,并检查问题是否已经调查过!

于 2013-02-15T09:44:14.370 回答