2016-05-04 47 views
1

エンティティに子エンティティの2つのリストがあります。 EntityManager.find()を呼び出すと、2つのリストの乗算に基づいて重複が返されます。JPA - EntityManager findメソッドが重複を返します

私はHibernateとSQL ServerでSpring、Jackson、JPAを使用しています。

N最初の要素と2番目の子実体の Mそれは常に両方のエンティティの N * Mの要素を返すを持つ親でテスト。例えば

は以下 タスクコメントあるとJPAは、両方のリストのを返します。

Comments 15 
Tasks 15 

そして残りのコードは以下の通りです:コントローラから(タスクリストの5つのコピー、およびコメントの一覧の3つのコピー)

出力があります。

controller.java

@RequestMapping(method = RequestMethod.GET) 
public String listAll(Model model) { 

    Goal goal = new Goal(); 

    goal = service.getGoalById(25); 

    System.out.println("Comments " + goal.getComments().size()); 
    System.out.println("Tasks " + goal.getTasks().size()); 

    return "home"; 
} 

service.java

@Transactional 
public Goal getGoalById(int goalId) { 
    Goal goal = em.find(Goal.class, goalId); 

    return goal; 
} 

goal.java

@Entity 
@Table(name = "goal") 
public class Goal { 

@Id 
@GeneratedValue 
private int id; 

@JsonManagedReference 
@OneToMany(mappedBy = "tasksGoal", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) 
private List<Task> projectTasks = new ArrayList<Task>(); 

@JsonManagedReference 
@OneToMany(mappedBy = "commentsGoal", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) 
private List<Comment> goalComments = new ArrayList<Comment>(); 

... 

} 

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" 
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
<persistence-unit name="persistenceUnit" 
    transaction-type="RESOURCE_LOCAL"> 
    <provider>org.hibernate.ejb.HibernatePersistence</provider> 
    <properties> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServer2008Dialect" /> 
     <property name="hibernate.hbm2ddl.auto" value="update" /> 
     <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" /> 
     <property name="hibernate.connection.charSet" value="UTF-8" /> 

     <!-- Hibernate prints SQL --> 
     <property name="hibernate.show_sql" value="true" /> 

    </properties> 
</persistence-unit> 

+0

[Hibernate CriteriaはFetchType.EAGER]で複数回返す可能性があります(http://stackoverflow.com/questions/1995080/hibernate-criteria-returns-children-multiple-times-with-fetchtype-eager) –

+1

重複としてマーク。可能な迅速な修正。関連からEagerフェッチを削除するか、ListからSetにコレクションを変更します。 –

+0

すみません、ありがとう、私はセットを使用しました。しかし、私はまだこの質問は重複していないと思う。私はHQLを使用していないので、JPAがfindメソッドを使用するときにこのエラーについて処理したり通知してくれると期待しています。私はこれがなぜ起こっているのか完全に理解していますが、答えを見つけるのは簡単だとは思わない。全体的に大変ありがとうございました! :) –

答えて

1

のpersistence.xmltask.java

@Entity 
@Table(name="projectTask") 
public class Task { 

@Id 
@GeneratedValue 
private int id; 

@JsonBackReference 
@ManyToOne (fetch = FetchType.LAZY) 
@JoinColumn(name = "task_goal_id") 
private Goal tasksGoal; 

... 

} 

comment.java

@Entity 
@Table (name="goalComment") 
public class Comment { 

@Id 
@GeneratedValue 
private int id; 

@JsonBackReference 
@ManyToOne (fetch = FetchType.LAZY) 
@JoinColumn(name = "goal_id") 
private Goal commentsGoal; 

... 

} 

これは=理由は、あなたのフェッチでありますFetchType.EAGER。 Hibernateは、「マスター」オブジェクトにリンクされている要素の各エントリに対して1つのクエリを使用して、すべてを取得しようとします。 HibernateはJOINを作成し、すべてのコレクションを1つのクエリで取得しようとします。

この問題は、コレクションに@Fetch(FetchMode.SELECT)アノテーションを追加すると、N + 1クエリを実行しても正常に解決できます。

あなたが本当にFetchType.EAGERを必要とSetあなたのコレクションのために@Fetch(FetchMode.SELECT)アノテーションを使用することができてあなたのコレクションを交換したくない場合は、次の @JsonManagedReference @OneToMany(mappedBy =「tasksGoal」、 cascade = CascadeType.PERSIST、fetch = FetchType.EAGER) @Fetch(FetchMode。SELECT) プライベートリストprojectTasks = new ArrayList();

@JsonManagedReference 
@OneToMany(mappedBy = "commentsGoal", cascade = CascadeType.PERSIST, fetch = FetchType.EAGER) 
@Fetch (FetchMode.SELECT) 
private List<Comment> goalComments = new ArrayList<Comment>(); 
0
@Fetch (FetchMode.SELECT) 

お手伝いをすることができます。これはデフォルトのフェッチ戦略です。それはすべての関連するコレクションの怠惰な読み込みを可能にしました。

関連する問題