[JAVA] 객체지향-다대일 양방향 연관 관계

Category: JAVA | March 09, 2017

양방향 연관 객체 관계

  • 회원에서 팀으로 접근할 수 있고 팀에서 회원으로 접근 할 수 있다.
  • 데이터베이스 테이블은 외래키 하나로 양방향 조회 할 수 있다.
  • 객체에는 양방향 연관 관계라는게 없다.
  • 양방향의 장점은 반대 방향으로 객체 그래프 탐색 기능이 추가된 것 뿐이다.
package com.sample;

public class Member {

    Team team;
    private String id;
    private String userName;

}

package com.sample;

import java.util.*;

public class Team {

    private Stirng id;
    private Stirng name;
    List memers;

}</pre>

Visual Paradigm으로 연관 관계 매핑

1.클래스 스트레오 타입을 ORM Persitable로 선택한다.

2.클래스 다이어그램 빈 공간에서 마우스 오른쪽 버튼을 선택해서 엔티티 다이어그램 동기화를 선택한다.

동기화가 완료 되면 엔티티 관계 다이어그램에 ERD가 생성된다.(Primary Key는 지정 되지 않아 ERD에서 설정했다.)

3.클래스 다이어그램 빈공간에서 마우스 오른쪽 버튼을 선택해서 ORM 코드 생성을 클릭한다.

클릭하면 다음과 같은 화면이 나오는데 Spring Data Jpa를 사용할 것이기 때문에 Framework를 JPA로 선택한 후 OK 버튼을 클릭한다.

package com.sample;

import java.io.Serializable;
import javax.persistence.*;
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="MEMBER")
public class Member implements Serializable {
    public Member() {
    }
    
    @Column(name="ID", nullable=false, length=255)  
    @Id 
    @GeneratedValue(generator="COM_SAMPLE_MEMBER_ID_GENERATOR") 
    @org.hibernate.annotations.GenericGenerator(name="COM_SAMPLE_MEMBER_ID_GENERATOR", strategy="native")   
    private String id;
    
    @Column(name="USERNAME", nullable=true, length=255) 
    private String userName;
    
    @ManyToOne(targetEntity=com.sample.Team.class, fetch=FetchType.LAZY)    
    @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.LOCK})    
    @JoinColumns({ @JoinColumn(name="TEAMID", referencedColumnName="ID") }) 
    private com.sample.Team team;
    
    public void setId(String value) {
        this.id = value;
    }
    
    public String getId() {
        return id;
    }
    
    public String getORMID() {
        return getId();
    }
    
    public void setUserName(String value) {
        this.userName = value;
    }
    
    public String getUserName() {
        return userName;
    }
    
    public void setTeam(com.sample.Team value) {
        this.team = value;
    }
    
    public com.sample.Team getTeam() {
        return team;
    }
    
    public String toString() {
        return String.valueOf(getId());
    }
    
    @Transient  
    private boolean _saved = false;
    
    public void onSave() {
        _saved=true;
    }
    
    
    public void onLoad() {
        _saved=true;
    }
    
    
    public boolean isSaved() {
        return _saved;
    }
    
    
}

import java.io.Serializable;
import javax.persistence.*;
@Entity
@org.hibernate.annotations.Proxy(lazy=false)
@Table(name="TEAM")
public class Team implements Serializable {
 public Team() {
 }
 
 private java.util.Set this_getSet (int key) {
 if (key == com.sample.ORMConstants.KEY_TEAM_MEMBERS) {
 return ORM_members;
 }
 
 return null;
 }
 
 @Transient 
 org.orm.util.ORMAdapter _ormAdapter = new org.orm.util.AbstractORMAdapter() {
 public java.util.Set getSet(int key) {
 return this_getSet(key);
 }
 
 };
 
 @Column(name="ID", nullable=false, length=255) 
 @Id 
 @GeneratedValue(generator="COM_SAMPLE_TEAM_ID_GENERATOR") 
 @org.hibernate.annotations.GenericGenerator(name="COM_SAMPLE_TEAM_ID_GENERATOR", strategy="native") 
 private String id;
 
 @Column(name="NAME", nullable=true, length=10) 
 private String name;
 
 @OneToMany(mappedBy="team", targetEntity=com.sample.Member.class) 
 @org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.LOCK}) 
 @org.hibernate.annotations.LazyCollection(org.hibernate.annotations.LazyCollectionOption.TRUE) 
 private java.util.Set ORM_members = new java.util.HashSet();
 
 public void setId(String value) {
 this.id = value;
 }
 
 public String getId() {
 return id;
 }
 
 public String getORMID() {
 return getId();
 }
 
 public void setName(String value) {
 this.name = value;
 }
 
 public String getName() {
 return name;
 }
 
 private void setORM_Members(java.util.Set value) {
 this.ORM_members = value;
 }
 
 private java.util.Set getORM_Members() {
 return ORM_members;
 }
 
 @Transient 
 public final com.sample.MemberSetCollection members = new com.sample.MemberSetCollection(this, _ormAdapter, com.sample.ORMConstants.KEY_TEAM_MEMBERS, com.sample.ORMConstants.KEY_MEMBER_TEAM, com.sample.ORMConstants.KEY_MUL_ONE_TO_MANY);
 
 public String toString() {
 return String.valueOf(getId());
 }
 
}

 

생성된 코드를 보면 주의 할 부분이 있다.

  • @Id, @Column 순서가 틀리면 스프링 부트에서 에러가 나기 때문에  생성된 코드를 잘 봐야 한다.
  • 클래스를 생성할 때 연관 핸들링 옵션을 smart를 선택하면 연관 관계 편의 메소드를 생성해 준다.
    //기존 연관 관계를 삭제하고 연관 관계를 설정한다.
    public void setTeam(com.sample.Team value) {
        if (team != null) {
            team.members.remove(this);
        }
        if (value != null) {
            value.members.add(this);
        }
    }

     </li>

  • 현재 JPA 2.1 까지 나온 상태인데 Visual Paradigm 12.1은 JPA 2까지만 지원된다.
  • 글로벌 페치 전략이 잘못 되어 있는 것 같다.
    생성된 코드를 보면 @ManyToOn가 다음과 같이 LAZY로 되어 있다.</p>
    @ManyToOne(targetEntity=com.sample.Team.class, fetch=FetchType.LAZY)

    그러나 JPA 기본 페치 전략은 다음과 같다.
    @ManyToOne=FetchType.EAGER
    @OneToMany=FetchType.Lazy</li> </ul>