개발관련/Spring 2015. 12. 7. 11:49

이번엔 상속 관계에 대해 알아보자. 

Project, Module, Task 이 3개 객체가 있다. 

최상위 객체는 Project이며, 그 자식으로 Module 이 있으며, Module의 자식으로 Task가 있다. 

먼저 소스를 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 
package com.zest.hibernate.chapter5.inheritancemapping;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
 
 
@Entity
//single table 실행시 stategy가 없는것과 동일한 결과를 볼수있다. 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
 
//각 class마다 table이 생성되며, 하위 class들은 pk키를 기준으로 테이블이 생성된다. 
//또, 최상위 클래스는 pk와 하위 컬럼만 존재한다. 
//@Inheritance(strategy=InheritanceType.JOINED)
 
//class에 맞는 컬럼 값만 저장하며, pk는 최상위 클래스 값으로 중복되지 않은 값으로 저장된다. 
//@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Project {
 
    @Id
    @GeneratedValue
    private int projectId;
    private String projectName;
    
    
    public int getProjectId() {
        return projectId;
    }
    public void setProjectId(int projectId) {
        this.projectId = projectId;
    }
    public String getProjectName() {
        return projectName;
    }
    public void setProjectName(String projectName) {
        this.projectName = projectName;
    }
    
    
}
 
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
package com.zest.hibernate.chapter5.inheritancemapping;
 
import javax.persistence.Entity;
 
@Entity
public class Module extends Project{
 
    private String moduleName;
 
    public String getModuleName() {
        return moduleName;
    }
 
    public void setModuleName(String moduleName) {
        this.moduleName = moduleName;
    }
    
}
 
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
package com.zest.hibernate.chapter5.inheritancemapping;
 
import javax.persistence.Entity;
 
@Entity
public class Task extends Module{
 
    private String taskName;
 
    public String getTaskName() {
        return taskName;
    }
 
    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }
    
    
}
 
cs


먼저 상속에 관한 옵션은 3가지 어노테이션이 존재한다. 

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)  - 디폴트 선언이며, 하위 자식의 값들은 무시되며, 최상위 클래스의 테이블에만 정보를 넣는다. 

@Inheritance(strategy=InheritanceType.JOINED) - 이름에서 알듯이 자식들은 부모와 fk로 엮이며, 부모는 자식의 값을 가지고 있고, 자식은 자신의 값을 가지고 있는다. 결국 부모는 전체의 데이터를 가지고 있고 자식은 fk로 본인의 값들을 가지고 있는다. 

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) - 부모 자식 포함해서 중복되지 않는 값을 서로간에 가지고 있는다. 


아마도 제일 많이 쓰이는건 2번이 아닐까 싶다. 그럼 테스트 코드를 보자. 먼저 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)  일 경우 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 
package com.zest.hibernate.chapter5.inheritancemapping;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
 
 
public class InheritaceMappingTest {
 
    @Test
    public void defaultRunTableTest(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Project.class);
        config.addAnnotatedClass(Module.class);
        config.addAnnotatedClass(Task.class);
        config.configure("hibernate.cfg.xml");
 
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        
        Project p = new Project();
        p.setProjectName("hibernate lessons");
        
        Module m = new Module();
        m.setProjectName("spring lessons");
        m.setModuleName("aop");
        
        Task t = new Task();
        t.setProjectName("java lessons");
        t.setModuleName("collections");
        t.setTaskName("arraylist");
        
        session.save(p);
        session.save(m);
        session.save(t);
        
        session.getTransaction().commit();
    }
    
 
}
 
cs


1
2
3
4
 
Hibernate: insert into TESTSCHEMA.Project (projectName, DTYPE, projectId) values (?, 'Project', ?)
Hibernate: insert into TESTSCHEMA.Project (projectName, moduleName, DTYPE, projectId) values (?, ?, 'Module', ?)
Hibernate: insert into TESTSCHEMA.Project (projectName, moduleName, taskName, DTYPE, projectId) values (?, ?, ?, 'Task', ?)
cs


위의 형태로 로그가 나올 것이다. 결과를 보면 project 말고는 다른 테이블은 생성이 안될 것이다. 

1
2
3
4
drop table testschema.task;
drop table testschema.module;
drop table testschema.project;
 
cs


다시 테이블을 드랍 시키고 @Inheritance(strategy=InheritanceType.JOINED) 이 어노테이션을 적용해보자. 


1
2
3
4
5
6
7
 
Hibernate: insert into TESTSCHEMA.Project (projectName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Project (projectName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Module (moduleName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Project (projectName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Module (moduleName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Task (taskName, projectId) values (?, ?)
cs

Project에는 결과가 총 3개가 생성이 된다. Module에 두개의 row가 생성되며, 마지막 task에는 1개의 row가 생성 될것이다. 그리고 테이블의 구조를 살펴보면 module.projectId , task.projectId는 pk,fk로 되어있다. 


마지막 @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)를 해보자. 먼저 테이블을 drop후 위에 선언한 project 객체의 주석을 변경한다. 그리고 테스트 ㄱㄱㄱㄱ


1
2
3
Hibernate: insert into TESTSCHEMA.Project (projectName, projectId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Module (projectName, moduleName, projectId) values (?, ?, ?)
Hibernate: insert into TESTSCHEMA.Task (projectName, moduleName, taskName, projectId) values (?, ?, ?, ?)
cs


자신의 데이터만 row에 생길 것이다. 


소스는 https://github.com/zest133/hibernateTest.git 여기에




posted by 제스트
: