LoginSignup
0
1

More than 5 years have passed since last update.

JSF 多対多 記述方法

Posted at

こんにちは! 
JavaでWEBアプリ開発を勉強している人間です。

今回、ある参考書の中で「オブジェクト関係マッピング(ORM)・@ManyToMany」が個人的に1週間くらい苦戦していたので同じ境遇の方たちに参考になればと思い記事を書かせていただきます。

実行環境

NetBeans IDE 8.0.2
cpu i5

対象

JSF 作成者(初心者)
ManyToManyの設定に苦戦している人

プログラムの説明

名前・年齢・タイトル・著者を入力しデータベースへ登録をし双方向から呼び出す。
(snp → super / super → snp)

まずはEntityから

今回用意したEntityは「Snp」・「Super」です。

Entityの記述はそんなに難しくはないです。
というか、この記事では難しいところの解説ではなくつまずきポイントの明確化なのでその点ご了承を...

Snp.java
    @Entity
    public class Snp {   
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long snpid;
      private String name;
      private Integer age;
      @ManyToMany(mappedBy = "snp", cascade = {CascadeType.ALL})
      private List<Super> sper = new ArrayList();   

      public Snp(){
      }

      public Snp(String name, Integer age){
        this.name = name;
        this.age = age;
      }

Super.java
   @Entity
   public class Super implements Serializable{   
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      private Long sperid;
      private String title;
      private String name_t;
      @ManyToMany
      private List<Snp> snp = new ArrayList();

      public Super(){
      }

      public Super(String title, String name_t){
         this.title = title;
         this.name_t = name_t;
      }

とりあえず、コンストラクターまでを表示します。
ここではget・setメソッドは省略していますが通常通りの宣言で問題ありません。
あと、カスケードやmappedByはお好みでw

簡単な記述ですが注意点が2個ほどあります。

1.idの名前は「クラス名 + id」

このidの名前で間違ってしまうとデータベースのほうでうまく外部キーが合わず関係マッピングができなくなってしまいます。

Snp.java
   private Long snpid;

自分はこれに気付くのにも結構な時間がかかってしまいました...

2.List宣言でArrayList()を先に代入

これに関しては絶対ここでやらなければならないわけではないのですが、自分は面倒臭いのでここで宣言しておきます。

snp.java
    @ManyToMany
    private List<Snp> snp = new ArrayList();

この宣言がないと、たまに「NullPointerException」のエラーが出るので注意してください。

次にバッキングビーン

こちらも簡単なので
さらっと

Bb.java
    public String creat(){

                Snp d = new Snp(name, age);

                Super sd = new Super(title, name_t);

                List<Super> ld = d.getSper();
                ld.add(sd);

                List<Snp> sld = sd.getSnp();
                sld.add(d);

                add1(d);

           return null;
    }

    public void add1(Snp da){
        try{
            db.Snpcreat(da);
        }catch(Exception e){
            System.out.println("エラー1です");
        }
    }

変数名が適当ですいませんw

ここでは注意点はないのですが、簡単なアドバイスがあります。
それは「ListをEntityへ代入したいとき、インスタンスからではなくgetメソッドを使って代入すること!!」
です!

まあ、ArrayListにしてから入れすのもいいですがそこは好みの問題ですね。

戦慄のxhtml

自分の場合ここに問題があり一番最後にバグです(泣)

データベースから呼び出すところに注目です。

content01.xhtml
       Snpデータベース
        <h:dataTable value="#{bb.all01}" var="v" class="data1">
                <h:column>#{v.name}</h:column>
                <h:column>#{v.age}</h:column>
                <h:column>
                     <h:dataTable value="#{v.sper}" var="o">
                            <h:column>#{o.title}</h:column>
                            <h:column>#{o.name_t}</h:column>
                     </h:dataTable>
                </h:column>
        </h:dataTable>

Listとして宣言したsperは<h:dataTable...を使ってあげることが大切です。
このバグをどれだけ長い時間追っていたか...

ただこれだけですが気付かないと長い時間が奪われてしまうので気を付けてくださいね

ちなみに「all01」ではこんなプログラムです。

Bb.java
    public List<Snp> getAll01(){
        return db.getAll01();
    }

ここからEntityManagerへ

SnpDb.java
    public List<Snp> getAll01(){
         List<Snp> snp = em.createQuery("SELECT c FROM Snp c").getResultList();
        return snp;
    }

となっています。(参考になれば...)

実行結果

スクリーンショット (7).png

終わりに

いかがだったでしょうか?

もちろん、これが絶対というわけではありません。
実務だと不足しているアノテーションやらなんやらがあるかもしれませんがとりあえず動くのでその点よろしくですwww

(ただ、どの記事よりアノテーションとかが少なくあまりない記事だったので参考になる方はいると思う)

あと、この説明で何か足りないところがあればぜひご指摘を

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1