Help us understand the problem. What is going on with this article?

JSF 多対多 記述方法

More than 1 year has passed since last update.

こんにちは! 
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

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

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

macaroni-salad
こんにちは!現在JSFでWEBアプリ開発の勉強をしているものです。javaでWEBアプリを作っている人がなかなかいませんでしたが学生時代に使ったC言語の知識を活かしコンパイル言語に挑戦しています。 Qiitaでは独学中に苦戦した・理解不能だったことをまたその解決策も登校するのでよろしくお願いします!!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away