You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

관계형 DB에서 엔티티간 연관관계를 맺는것은 , 데이터 모델 설계와도 관련된 중요한 내용이며

JPA에서도 설계된 연관관계를 CLASS OBJECT로 맵핑처리 하는것은 아주 중요한 내용입니다.


데이터 중심 접근  VS 객체지향 접근

사용자와 주소테이블이 분리되었고

사용자와 사용자와 연관된 주소정보를 각각 가져온다라고 가정해봅시다.

데이터 중심

User user =  sql.find( User , "select * from user u where u.id=", 1234 );
.....
Address address = sql.find( Address , "select t.* from address t join user u on u.addressid = " + user.addressid  );

사용자 정보를 조회하고, 사용자 테이블에 등록된 외래키인 addressid를 가지고 주소 정보를 한번더 탐색해야

우리가 원하는 User와 Address정보가 완성이 됩니다. 객체관점에서 User와 Address는 아무런 연관이 없습니다. 

이것이 데이터베이스의 ERD와, 객체에서 연관관계를 표현하는 UML과 맞추지 못하는 이유입니다. 

여기서 User 와 Address의 관계는  UML에서 어떠한 관계도 명시할수 없는 별개의 객체이며

연관성이 끊겼을뿐더러, 객체지향의 요소를 잃은 단순한 임시 데이터 반환 객체입니다.


객체중심

User user = em.find( User , 1234 );
.....
Address address = user.getAddress();

객체는 조인처리 대신, 참조를 얻을수 있어야합니다.  JPA는 실제 데이터조회를 위와같이 이용을 합니다.

사용자를 통해 주소의 참조값을 얻을수 있기때문에   데이터베이스의 ERD와 ,객체를 표현하는 UML의

아주 큰차이가 좁혀졌습니다. 


하지만 데이터를 객체중심 접근방법을 사용하기위해서는 각종 연관키가 설정된 엔티티를 ,

참조형태의 객체모델로 변환하는 방법을 알아야합니다. 이것은 생각보다 여려우며

외래키를 사용하여 조인을 걸어 연관 객체를 얻어오는것은 여러차례의 SQL문을 통해 성공하고 사용될수 있으나

JPA에서는 테이블에 걸려있는 연관키를 파악하고 머릿속에 정확한 ERD를 그려내지 못하면

참조를 얻는것은 실패할것입니다.


Entity 설계

데이터베이스의 엔티티를 단순하게 맵핑을 하고 사용을 한다고 하면, 연관성 설정은 필요가 없습니다.

하지만 외래키를 통해 이루어지는  연관 속성을 , 객체에도 반영을 하려면 연관성을 설정하는

다음 JPA 어노테이션을 알고 있어야 합니다.

  • ManyToOne : N VS 1 관계
  • OneToMany : 1 VS N 관계
  • ManyToMany : N VS N 관계


ManyToOne

CREATE TABLE `group_info` (
  `group_id` int(11) NOT NULL AUTO_INCREMENT,
  `namevarchar(255) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`group_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
 
 
CREATE TABLE `user` (
  `user_id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) COLLATE utf8_bin DEFAULT NULL,
  `namevarchar(255) COLLATE utf8_bin DEFAULT NULL,
  `group_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`user_id`),
  KEY `FKa36i4ekojwk70bxen390i6tek` (`group_id`),
  CONSTRAINT `FKa36i4ekojwk70bxen390i6tek` FOREIGN KEY (`group_id`) REFERENCES `group_info` (`group_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;



외래키로 설정된 두 테이블의 엔티티입니다. 사용자가 여러명있고 그룹은 여러명의 사용자를

가질수 있기때문에   N : 1 관계 입니다.

선언

클래서 정의 코드내에서는 '@ManyToOne' 어노테이션 설정을통해 연관관계를 설정을 하기만하면됩니다.

데이터베이스와 유사하게 몇가지 제약조건( 널허용 )을 적용 하는것도 가능합니다.

@Entity
public class User {
    @Id
    @GeneratedValue
    @Column(name = "USER_ID")
    private Integer id;
 
    private String name;
 
    private String email;
  
    @ManyToOne
    @JoinColumn(name = "GROUP_ID", nullable=true )
    private GroupInfo groupInfo;   
}

관련소스:http://git.webnori.com/projects/WEBF/repos/spring_jpa/browse/src/main/java/com/example/demo/data2/User.java


사용예

로직순서:

  • 존재하는 그룹을 찾는다.
  • 사용자를 등록하고, 찾은 그룹을 지정한다.
  • 사용자를 찾고, 지정된 그룹을 조회한다.
GroupInfo someGroup = groupRepository.findByName("학생");


//저장시
User addUser = new User();
addUser.setName("minsu");
addUser.setEmail("test@x.com");
addUser.setGroupInfo(someGroup);


//조회시
User someUser =  userRepository.findByName("minsu")
GroupInfo someUserMyGroup = someUser.getGroupInfo();

객체 지향적으로 접근을 한 예입니다. 데이터 베이스가 가진 정보를 단순하고 직관적이게 접근을 할수 있습니다.


기존방식의 문제:

위 로직을, 전통적인 방법으로 어플리케이션내에서  SQL/SP문으로 각각 처리한다라고 가정하면 ,

JAVA코드내에 SQL문이 썩여서 처리되거나, 별도의 관리 공간에 코드를 분리하거나? 처리가 된다고 해도 ,

사용자의 객체로부터 그룹참조를 얻어내는것은 어려울수 있습니다. 또한 약간의 옵션변경에따라 다른기능을하는,

거의 중복에 가까운 유사 SQL문 반복 작성을 해야할수도 있습니다.



  • No labels