2016-12-07 5 views
0

私はSpringブートアプリケーションの2つのエンティティ間に多対多リレーションシップを追加しています。Hibernateの多対多リレーションは空のコレクションを返します

Business.java:

@ManyToMany(cascade = CascadeType.ALL) 
@JoinTable(name = "business_vendor", 
     joinColumns = @JoinColumn(name = "business_id"), 
     inverseJoinColumns = @JoinColumn(name = "vendor_id")) 
@JSON(include = false) 
protected List<Vendor> vendors; 

Vendor.java

@ManyToMany(cascade = CascadeType.ALL, mappedBy = "vendors") 
@JSON(include = false) 
protected List<Business> businesses; 

私は、その後のビジネスにベンダーを追加し、それをデータベースに保存することができる午前私は、以下のマッピングを持っています。しかし、(新しい要求で)私はビジネスを読み込んでbusiness.getVendors()と呼ぶと、私は空のリストを取得します。私はアプリケーションログからHibernateがリンクテーブルから選択していることを知ることができます。データベースに対して手動でHibernateが生成したクエリを手動で実行すると、期待どおりに1つの行が表示されます。私は熱心にFetchModeを切り替えようとしましたが、いずれも助けにならなかったCascadeType.ALLを削除しようとしました。

このアプリケーションはHibernate 4.3.11です(この時点では「理由」はアップグレードできません)。

編集:ここでは、最小限の例です:

public List<Vendor> getVendorsForBusiness(UUID businessId) { 
    Business business = businessRepository.findOne(businessId.toString()); 
    return business.getVendors(); 
} 

行がデータベースにリンクテーブルにあるにもかかわらず、私はこれが1つのベンダーとのリストを返すことを期待するが、私は空のリストを取得します。

編集2:

public void addVendorToBusiness(UUID businessId, UUID vendorId) { 
    Vendor vendor = vendorRepository.findOne(vendorId.toString()); 
    Business business = businessRepository.findOne(businessId.toString()); 
    business.getVendors().add(vendor); 
    vendor.getBusinesses().add(business); // This line doesn't make a difference 
    businessRepository.save(business); 
} 
+1

persistメソッドを使用して最小限の例を作成します。マッピングは良いようです。 – jklee

+0

私は@jkleeと合意しています。他の人があなたの質問に答えるのを助けるもっと完全な例です。 – Dale

+0

エンティティをどのように保存しますか?私のプロジェクトにマッピングされます。 – jklee

答えて

0

は単に双方向の戦略を使用する:ここで正常business_vendorテーブルの行を作成しない私が使用してい持続方法の関連部分です。このような何か:

Business.java

@Entity 
@Table(name = "BUSINESS") 
public class Business implements Serializable { 

    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) 
    @JoinTable(name = "business_vendor", 
      joinColumns = @JoinColumn(name = "business_id"), 
      inverseJoinColumns = @JoinColumn(name = "vendor_id")) 
//@JSON(include = false) 
    private List<Vendor> vendors; 

    public Business() { 
    } 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public List<Vendor> getVendors() { 
     return vendors; 
    } 

    public void setVendors(List<Vendor> vendors) { 
     this.vendors = vendors; 
    } 
} 

Vendor.java

@Entity 
@Table(name = "VENDOR") 
public class Vendor implements Serializable { 

    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "vendors", fetch = FetchType.EAGER) 
// @JSON(include = false) 
    private List<Business> businesses; 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public List<Business> getBusinesses() { 
     return businesses; 
    } 

    public void setBusinesses(List<Business> businesses) { 
     this.businesses = businesses; 
    } 

    public Vendor() { 
    } 
} 

Main.java

public class Main { 

    private static final SessionFactory SESSION_FACTORY = new AnnotationConfiguration().configure().buildSessionFactory(); 
    private Session session; 
    private Transaction transaction; 

    public static void main(String[] args) { 

     Main main = new Main(); 
     main.save(); 
     List<Vendor> vList = main.getVendorFromBusinessId(2L); 
     main.displayVendors(vList); 

     SESSION_FACTORY.close(); 
     System.exit(0); 
    } 

    private void save() { 

     this.session = SESSION_FACTORY.openSession(); 
     this.transaction = null; 
     try { 

      this.transaction = this.session.beginTransaction(); 
      Business b1 = new Business(); 
      Business b2 = new Business(); 
      Business b3 = new Business(); 

      Vendor v1 = new Vendor(); 
      Vendor v2 = new Vendor(); 

      List<Business> bList = new ArrayList<>(); 
      bList.add(b1); 
      bList.add(b2); 
      bList.add(b3); 

      List<Vendor> vList = new ArrayList<>(); 
      vList.add(v1); 
      vList.add(v2); 

      b1.setVendors(vList); 
      b2.setVendors(vList); 
      b3.setVendors(vList); 

      v1.setBusinesses(bList); 
      v2.setBusinesses(bList); 

      this.session.save(b1); 
      this.session.save(b2); 
      this.session.save(b3); 

      this.transaction.commit(); 
     } catch (Exception e) { 

      if (this.transaction == null) { 

       this.transaction.rollback(); 
      } 
     } finally { 

      this.session.close(); 
     } 
    } 

    private List<Vendor> getVendorFromBusinessId(Long businessId) { 

     List<Vendor> vList = null; 
     this.session = SESSION_FACTORY.openSession(); 
     this.transaction = null; 

     try { 

      this.transaction = this.session.beginTransaction(); 
      Business business = (Business) this.session.get(Business.class, businessId); 
      vList = business.getVendors(); 
      this.transaction.commit(); 
     } catch (Exception e) { 

      if (this.transaction == null) { 

       this.transaction.rollback(); 
      } 
     } finally { 

      this.session.close(); 
     } 

     return vList; 
    } 

    private void displayVendors(List<Vendor> vList) { 

     if (vList != null) { 

      System.out.print("Vendor List IDs: "); 
      vList.forEach((vendor) -> { 
       System.out.print(vendor.getId() + " "); 
      }); 

      System.out.println(); 
     } 
    } 
} 

が、これはあなたの問題を解決することを願っています。

マイ出力:データベースで My Output Image

+0

私は関係を保存する際に問題はありません。問題が発生しています。そして、すでに 'fetch = FetchType.EAGER'を追加しようとしました。 – NeuroXc

+0

さて、双方向戦略を試しましたか?双方向マッピングを使用した後、getVendors()は空を返しますか? – ashik

+0

私は双方向戦略を試していて、持続してからgetVendors()から空リストを取得しています。 – NeuroXc

0

、私たちは、主キーのためにUUIDを使用します。しかし、このアプリケーションを作成した人は、JavaのUUIDタイプを使用する代わりに、UUIDにStringを使用することを決定しました。したがって、アプリケーションは小文字のUUIDをデータベースに送信することもあり、時には大文字のUUIDを送信することもあります。 SQL ServerのUUIDは大文字と小文字を区別しないため、データベースには関係ありませんが、Java Stringsでは大文字と小文字が区別されるため、Hibernateは小文字のUUIDを持つBusinessが大文字のUUIDのBusinessと同じであることを認識しません。だから私は.toString().toUpperCase()のすべてのIDをそれらが同じであることを確認するためにデータベースに送信する前にしなければならなかった。

もちろん、Java UUIDは大文字と小文字を区別しないので、このソフトウェアを作成した人がStringの代わりにこれらの問題を使用した場合、この問題は回避できます。

0
@ManyToMany(cascade = CascadeType.ALL) 
@JoinTable(name = "business_vendor", 
     joinColumns = @JoinColumn(name = "business_id"**, referencedColumnName = "enter business Id name"**), 
     inverseJoinColumns = @JoinColumn(name = "vendor_id", **referencedColumnName = "enter vendor Id name"**)) 
@JSON(include = false) 
protected List<Vendor> vendors; 

**OR** 

@ManyToMany(cascade = CascadeType.ALL) 
@JoinTable(name = "business_vendor", 
     joinColumns = @JoinColumn(**name = "tablename_idname"**), 
     inverseJoinColumns = @JoinColumn(**name = "tablename_idname"**)) 
@JSON(include = false) 
protected List<Vendor> vendors; 
+1

コードは質問に答えるかもしれませんが、OPはなぜこれが今働いているのか学ばないでしょう。だからあなたのコードスニペットがその質問に答える理由を説明してください。 – Markus

+0

referencedColumnNameを指定すると、データをフェッチするときにテーブルを参照するのに役立ちますが、referencedColumnNameが指定されていない場合、HibernateはJoinColumn名からreferencedColumnNameを生成しようとします。 – stanlee

関連する問題