多対一(N:1)-双方向マッピングの注意点

16495 ワード

複数対1(N:1)ディレクトリ
  • 多対一(N:1)-一方向
  • マルチペア(N:1)-双方向
  • 複数対1(N:1)-双方向関連ディレクトリ
  • 多対一(N:1)の双方向関連
  • 双方向マッピング注意点
  • 双方向マッピングの注意点
    1.双方向マッピングで最もよく発生するエラー
    最初のコード
    Team team = new Team();
    team.setName("teamA");
    em.persist(team);
    
    Member member = new Member();
    member.setName("member1");
    
    // 역방향(주인이 아닌 방향)만 연관관계 설정
    team.getMembers().add(member);
    em.persist(member);
  • Teamのメンバーはホストではないので、TEAM IDには影響しません.
  • したがって,上記のコードはmemberにおいてTEAM IDがNULLである.
    2番目のコード
    Team team = new Team();
    team.setName("teamA");
    em.persist(team);
    
    Member member = new Member();
    member.setName("member1");
    team.getMembers().add(member);
    
    // 연관관계의 주인에 값 설정
    member.setTeam(team);
    em.persist(member);
  • メンバーのチームがオーナーなので、TEAM IDに影響します.
  • ですので、上記のコードのようにメンバーのTEAM IDだけが値します.
  • 2.純オブジェクト状態を考慮し、常に両側に値を設定する
    3番目のコード
    Team team = new Team();
    team.setName("teamA");
    em.persist(team);
    
    Member member = new Member();
    member.setName("member1");
    member.setTeam(team);
    em.persist(member);
    
    em.clear();
    Member findMember = em.find(Member.class, member.getId());
  • の上のコードのように記述されていれば、DBの観点からは何の問題もありません.
  • SELECTクエリーを展開すると、findMemberのチームメンバーのサイズは1になります.
  • ただし、純オブジェクト状態(SELECTクエリ失敗X)では、チームメンバーには何も含まれません.->今後、ビジネスロジックに問題が発生する可能性があります.
  • したがって、3番目のコードと比較して、2番目のコードのようにチームのgetMembersに値を入力する必要があります.
    3番目のコードよりも良い方法は、関連関係編を作成する方法です.
    [Member]
    @Entity
     public class Member { 
    		 
    	@Id @GeneratedValue
    	private Long id;
    
    	@Column(name = "USERNAME")
    	private String name;
    
    	private int age;
    
    	@ManyToOne
    	@JoinColumn(name = "TEAM_ID")
    	private Team team
    
    	// 연관관계 편의 메소드
    	public Team setTeam(Team team) {
    	    this.team = team;
     	    team.getMembers().add(this);
        	}
    }
    上記のコードに示すように、関連するメソッドを作成できます.
    member.setTeam(team);操作を実行すると、チームメンバーにも値が入力されます.
    必ずチームを組むgetMembers().add(member);作成するコードは必要ありません.
    3.双方向マッピング時に無限ループに注意
    例:toString()、lombok、JSONライブラリの作成
    [Member]
    @Entity
    public class Member {
    
        @Id @GeneratedValue
        private Long id;
    
        @Column(name="USERNAME")
        private String username;   
    
        @ManyToOne
        @JoinColumn(name = "TEAM_ID")
        private Team team;
    
        @Override
        public String toString() {
            return "Member{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", team=" + team +
                    '}';
        }
    
    }
    [Team]
    @Entity
    public class Team {
    
        @Id @GeneratedValue
        @Column(name="TEAM_ID")
        private Long id;
    
        @Column(name = "NAME")
        private String name;
    
        @OneToMany(mappedBy = "team")
        private List<Member> members = new ArrayList<>();
    
        @Override
        public String toString() {
            return "Team{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", members=" + members +
                    '}';
        }
    
    }
    この場合、チームでもメンバーでもtoString()を呼び出すと無限ループが発生します.
    1.メンバーのtoString()を呼び出す
    2.メンバーのtoString()からチームのtoString()を呼び出す
    3.チームのtoString()からメンバーを呼び出す->メンバーからメンバーを呼び出すtoString()
    4.無限に繰り返す