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ページには、特定のサイトとidxのSiteIp.ipを示す3つのフィールドがあります。これまでのところ、サイトエンティティでヘルパーゲッターメソッドを作成しました。

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

「JPAを使用した複合主キー」をグーグルで検索する必要があります。しかし、あなたがここにいるのは初めてなので、以下に簡単な説明と実用的な解決策を示します.

ちょっとした説明

複合主キーは、それ自体が@Embeddable注釈付きのクラスです。そして、@Entity主複合キー フィールドを でマークするとすぐに、それらはクラスの主キーになります@EmbeddedId。残された唯一のことは、両方のクラスでequalsand を適切に実装することです。hashcode

解決

ソリューションは@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 に答える