'Hibernate'에 해당되는 글 10건

  1. 2015.12.17 :: hibernate(10)
  2. 2015.12.07 :: hibernate(9)
  3. 2015.12.07 :: hibernate(8)
  4. 2015.12.07 :: hibernate(7)
  5. 2015.12.07 :: hibernate(6)
  6. 2015.12.04 :: hibernate(5)
  7. 2015.12.04 :: hibernate(4)
  8. 2015.12.04 :: hibernate(3)
  9. 2015.12.04 :: hibernate(2)
  10. 2015.12.04 :: hibernate(1)
개발관련/Spring 2015. 12. 17. 11:50

hibernate의 HQL을 알아보자. 

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
package com.zest.hibernate.chapter10.crud;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.Table;
 
@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
 
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;
    private String userName;
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    
    
    
}
 
 
cs


위와 같은 테이블을 생성한다. 

먼저 데이터를 insert 한다. 이 부분은 기존에 만들어 놓은 코드를 조금 수정해서 insert를 한다. 


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
 
@Test
    public void insertTest() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        for (int i = 0; i < 10; i++) {
            UserDetails user = new UserDetails();
            user.setUserName("user " + i);
            session.save(user);
        }
 
        session.getTransaction().commit();
        // session.close();
    }
cs


user0, user1 ...........  이런 user를 총 10개를 만들었다. 그럼 기존에 사용했던 방식으로 select의 결과물을 가져와보자. 


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
@Test
    public void getTest() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
//        new SchemaExport(config).create(true, true);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        
        UserDetails user = (UserDetails) session.get(UserDetails.class6); 
        System.out.println("name\t"+user.getUserName());
 
        session.getTransaction().commit();
//         session.close();
    }
cs


session.get이라는 함수를 통해 파라미터로 어느 테이블(객체), 기본키를 넣어서 값을 가져오는 예제이다. 


그럼 hql를 해보자. 

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
@Test
    public void hsqlTest1() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
//        new SchemaExport(config).create(true, true);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        //hibernate 용으로. 
        Query query=  session.createQuery("from UserDetails");
        List users = query.list();
        
 
        session.getTransaction().commit();
//         session.close();
        System.out.println("list size==>"+users.size());
    }
cs


위의 내용은 전체 리스트를 가져오는 예제이다. 이때 중요한 메소드는 createQuery라는 메소드인데 이 뒤는 sql문과 매우 흡사하다. 여기서 중요한 점은 UserDetails는 table명이 아니라 객체 라는 점이다. jpa에서는 jpa ql 이라는 것과 거의 비슷하게 맵핑이 될것이다. 


한개더 예제를 해보자. 


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
@Test
    public void hsqlWhereTest() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
//        new SchemaExport(config).create(true, true);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        //hibernate 용으로. 
        Query query=  session.createQuery("from UserDetails where userId >5");
        List users = query.list();
        
 
        session.getTransaction().commit();
//         session.close();
        System.out.println("list size==>"+users.size());
    }
cs


위의 예제는 where절이 추가 되었으며 마찬가지로 UserDetails의 멤버 변수의 값을 5보다 큰 값을 가져오는 예제이다. 

이번엔 게시판 또는 그리드에서 많이 쓰는 paging에 대해 보자. 

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
@Test
    public void hsqlpageingTest2() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
//        new SchemaExport(config).create(true, true);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        //hibernate 용으로. 
        Query query=  session.createQuery("from UserDetails ");
        //시작 row를 설정. 
        query.setFirstResult(5);
        //결과 개수
        query.setMaxResults(4);
        
        List<UserDetails> users = (List<UserDetails>)query.list();
        
 
        session.getTransaction().commit();
//         session.close();
        for(UserDetails u : users){
            System.out.println(u.getUserName());
        }
    }
cs


setFirstResult 메소드와 setMaxResults가 추가 되었다. 이 메소드를 이용해 paging을 쉽게 구현할 것이다. 


이번엔 preparedstatement와 비슷한 binding에 대해 알아보자. 

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
@Test
    public void hsqlBindingTest2() {
 
        // hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(UserDetails.class);
        // db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
 
        // db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        // <property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시
        // 마찬가지임.
//        new SchemaExport(config).create(true, true);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        String minUserId= "5";
        //hibernate 용으로.
        
        
        Query query=  session.createQuery("from UserDetails where userId > ?");
        query.setInteger(0, Integer.parseInt(minUserId));
        List<UserDetails> users = (List<UserDetails>)query.list();
        
 
        session.getTransaction().commit();
//         session.close();
        for(UserDetails u : users){
            System.out.println(u.getUserName());
        }
    }
cs


hql에 ? 라는 바인딩 변수가 있다. 이 값을 setInteger로 바인딩 하는 메소드를 추가하고 리스트를 가져오는 예제이다. preparedstatement와 매우 흡사하다. 


여기까지 하이버네이트는 끝낸다. 


모든 예제는 https://github.com/zest133/hibernateTest.git 에서 있다. 



posted by 제스트
:
개발관련/Spring 2015. 12. 7. 17:57

다대다에 대해서 알아보자. 


바로 소스 공개...

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
51
52
package com.zest.hibernate.chapter8.manytomanymapping;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
 
@Entity
public class Delegate {
 
    
    private int delegateId;
    private String delegateName;
    private List<Event> events = new ArrayList<Event>();
 
    
    @Id
    @GeneratedValue
    public int getDelegateId() {
        return delegateId;
    }
 
    public void setDelegateId(int delegateId) {
        this.delegateId = delegateId;
    }
 
    public String getDelegateName() {
        return delegateName;
    }
 
    public void setDelegateName(String delegateName) {
        this.delegateName = delegateName;
    }
 
    // 결과를 담을 테이블명을 정의 .
    @ManyToMany
    @JoinTable(name = "JOIN_DELEGATE_EVENT", joinColumns = { @JoinColumn(name = "delegateId") }, inverseJoinColumns = { @JoinColumn(name = "eventId") }    )
    public List<Event> getEvents() {
        return events;
    }
 
    public void setEvents(List<Event> events) {
        this.events = events;
    }
 
}
 
cs



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
51
 
package com.zest.hibernate.chapter8.manytomanymapping;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
 
@Entity
public class Event {
 
    
    private int eventId;
    private String eventName;
    private List<Delegate> delegates = new ArrayList<Delegate>();
 
    @Id
    @GeneratedValue
    public int getEventId() {
        return eventId;
    }
 
    public void setEventId(int eventId) {
        this.eventId = eventId;
    }
 
    public String getEventName() {
        return eventName;
    }
 
    public void setEventName(String eventName) {
        this.eventName = eventName;
    }
 
    @ManyToMany
    @JoinTable(name = "JOIN_DELEGATE_EVENT", joinColumns = { @JoinColumn(name = "eventId") }, inverseJoinColumns = { @JoinColumn(name = "delegateId") })
    public List<Delegate> getDelegates() {
        return delegates;
    }
 
    public void setDelegates(List<Delegate> delegates) {
        this.delegates = delegates;
    }
 
}
 
cs


두개의 객체를 선언하였다. 여기도 마찬가지로 새로운 어노테이션이 등장한다. 

@ManyToMany 이다. 그리고 JoinColumn이 아닌 JoinTable이다. 

@ManyToMany는 두개의 객체 두군데 다 선언을 한다. 그리고 필연적으로 @JoinTable을 사용해야한다. 각 속성을 알아보자. name은 m:n에 대한 데이터를 저장하는 테이블 이며, jonColumns와 inverseJoinColumkns가 존재한다. joinColumns는 join이 되는 컬럼 여기선 상호간의 컬럼 아이디를 써준다. 



결과 쿼리를 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
cs


JOIN_DELEGATE_EVENT 테이블 생성되며 각 각의 정보가 m:n으로 맵핑이 된다.


하이버네이트 모든 코드는 https://github.com/zest133/hibernateTest.git 여기에 저장되어 있다.

posted by 제스트
:
개발관련/Spring 2015. 12. 7. 13:32

이번엔 1:N 관계를 살펴보자. 


바로 소스를 보자. 

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
package com.zest.hibernate.chapter7.onetomanymapping;
 
import java.util.List;
 
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
 
@Entity
public class College {
 
    @Id
    @GeneratedValue
    private int collegeId;
    private String collegeName;
    
    @OneToMany(targetEntity=Student.class, mappedBy="college"
            ,cascade= CascadeType.ALL,fetch=FetchType.EAGER)
    private List<Student> students ;
    
    
    public int getCollegeId() {
        return collegeId;
    }
    public void setCollegeId(int collegeId) {
        this.collegeId = collegeId;
    }
    public String getCollegeName() {
        return collegeName;
    }
    public void setCollegeName(String collegeName) {
        this.collegeName = collegeName;
    }
    public List<Student> getStudents() {
        return students;
    }
    public void setStudents(List<Student> students) {
        this.students = students;
    }
    
    
}
 
cs



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
 
package com.zest.hibernate.chapter7.onetomanymapping;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
 
@Entity
public class Student {
 
    @Id
    @GeneratedValue
    private int studentId;
    private String studentName;
    
    @ManyToOne
    @JoinColumn(name="college_id")
    private College college;
    
    public int getStudentId() {
        return studentId;
    }
    public void setStudentId(int studentId) {
        this.studentId = studentId;
    }
    public String getStudentName() {
        return studentName;
    }
    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    public College getCollege() {
        return college;
    }
    public void setCollege(College college) {
        this.college = college;
    }
    
    
}
 
cs


몇가지 새로운 어노테이션이 등장했다. @OneToMany, @ManyToOne

OneToMany가 선언되있는 클래스는 One을 지칭하고 targetEntity는 many가 된다. 


mappedBy는 One에 속하는 테이블 명을 써주면 된다. 

Student 객체는 ManyToOne을 선언하고 JoinColumn의 컬럼 명을 정의해주면 된다. 


그럼 테스트 ㄱㄱ

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
51
52
 
package com.zest.hibernate.chapter7.onetomanymapping;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
 
import com.zest.hibernate.chapter5.inheritancemapping.Module;
import com.zest.hibernate.chapter5.inheritancemapping.Project;
import com.zest.hibernate.chapter5.inheritancemapping.Task;
 
public class OneToManyTest {
 
    @Test
    public void oneTest(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(College.class);
        config.addAnnotatedClass(Student.class);
        config.configure("hibernate.cfg.xml");
        
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        
        College college1 = new College();
        college1.setCollegeName("Newyork College");
        
        Student s1 = new Student();
        s1.setStudentName("Alex Rod");
        
        Student s2 = new Student();
        s2.setStudentName("Linda Berry");
        
        s1.setCollege(college1);
        s2.setCollege(college1);
        
        session.save(college1);
        session.save(s1);
        session.save(s2);
        //session.save(alexdetail); 이건 안함. 카스케이드 라서 
        session.getTransaction().commit();
        
        
    }
}
 
cs


결과는 다음과 같다. 

1
2
3
4
 
Hibernate: insert into TESTSCHEMA.College (collegeName, collegeId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Student (college_id, studentName, studentId) values (?, ?, ?)
Hibernate: insert into TESTSCHEMA.Student (college_id, studentName, studentId) values (?, ?, ?)
cs


예상했던 대로 College_ID는 FK로 셋팅이 된다. 



posted by 제스트
:
개발관련/Spring 2015. 12. 7. 12:01

이번엔 join에 대해 알아보자. join은 1:1 맵핑, 1:m, m:n 아마도 이렇게 구성이 될것이다. 

여기서는 1:1에 대해 알아보자. 


객체는 person과 personDetail 두가지가 있다. 그럼 코드를 보자. 

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package com.zest.hibernate.chapter6.onetoonemapping;
 
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
 
 
/**
 * 
 * one to one
 * ex) person data table
 * person id : 1
 *person name: aaaa
 *pdetail_fk :32768 이넘 
 *
 *person_detail
 *detailId_pk : 32768 이넘
 *income:123456786
 *job : adklja
 *zipcode : 20815
 *
 *위에 '이넘' 두개가 1:1로 맵핑. 
 */
@Entity
public class Person {
 
    @Id
    @GeneratedValue
    private int personId;
    private String personName;
    
    /**
     * CascadeType의 종류에는 다음과 같은 것들이 있다.
CascadeType.RESIST – 엔티티를 생성하고, 연관 엔티티를 추가하였을 때 persist() 를 수행하면 연관 엔티티도 함께 persist()가 수행된다.  만약 연관 엔티티가 DB에 등록된 키값을 가지고 있다면 detached entity passed to persist Exception이 발생한다.
CascadeType.MERGE – 트랜잭션이 종료되고 detach 상태에서 연관 엔티티를 추가하거나 변경된 이후에 부모 엔티티가 merge()를 수행하게 되면 변경사항이 적용된다.(연관 엔티티의 추가 및 수정 모두 반영됨)
CascadeType.REMOVE – 삭제 시 연관된 엔티티도 같이 삭제됨
CascadeType.DETACH – 부모 엔티티가 detach()를 수행하게 되면, 연관된 엔티티도 detach() 상태가 되어 변경사항이 반영되지 않는다.
CascadeType.ALL – 모든 Cascade 적용
fetch 의 순위 두 개 있다
fetch=FetchType.EAGER: 실행 문 바로 꺼냈다
fetch=FetchType.LAZY: 쓸 때 비로소 꺼냈다
     */
    @OneToOne(cascade=CascadeType.ALL, fetch= FetchType.EAGER)
    @JoinColumn(name="pDetail_FK")
    private PersonDetail pDetail;
    
    
    
    public PersonDetail getpDetail() {
        return pDetail;
    }
    public void setpDetail(PersonDetail pDetail) {
        this.pDetail = pDetail;
    }
    public int getPersonId() {
        return personId;
    }
    public void setPersonId(int personId) {
        this.personId = personId;
    }
    public String getPersonName() {
        return personName;
    }
    public void setPersonName(String personName) {
        this.personName = personName;
    }
    
}
 
cs


새로운 어노테이션이 등장한다. OneToOne 과 JoinColumn 이 추가 되었다. 

OneToOne의 경우 외래키를 만들때 선언하는 어노테이션이다. Cascade속성과 Fetch 속성 두가지를 지원한다. JoinColumn은 외래키가 되는 Column의 실제 Column이름을 지정하는것이다. 그냥 테이블 생성시에는 @Column이라는 놈이랑 비슷하다고 생각하면된다.  그리고 중요한 것은 기본키가 되는 객체에 어노테이션을 선언한다는것이다. 


그럼 personDetail을 만들어보자. 

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.chapter6.onetoonemapping;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
 
 
@Entity
public class PersonDetail {
 
    @Id
    @GeneratedValue
    @Column(name="detailId_PK")
    private int personDetailId;
    private String zipCode;
    private String job;
    private double income;
    
    
    
    public int getPersonDetailId() {
        return personDetailId;
    }
    public void setPersonDetailId(int personDetailId) {
        this.personDetailId = personDetailId;
    }
    public String getZipCode() {
        return zipCode;
    }
    public void setZipCode(String zipCode) {
        this.zipCode = zipCode;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public double getIncome() {
        return income;
    }
    public void setIncome(double income) {
        this.income = income;
    }
    
    
}
 
cs


기존 테이블을 만들던 코드와 똑같다. 테스트 코드 ㄱㄱ


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
 
package com.zest.hibernate.chapter6.onetoonemapping;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
 
import com.zest.hibernate.chapter5.inheritancemapping.Module;
import com.zest.hibernate.chapter5.inheritancemapping.Project;
import com.zest.hibernate.chapter5.inheritancemapping.Task;
 
public class OneToOneTest {
 
    @Test
    public void oneTest(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Person.class);
        config.addAnnotatedClass(PersonDetail.class);
        config.configure("hibernate.cfg.xml");
        
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
        
        PersonDetail alexDetail = new PersonDetail();
        alexDetail.setZipCode("20815");
        alexDetail.setJob("Accountant");
        alexDetail.setIncome(67245.56);
        
        Person alex = new Person();
        alex.setPersonName("alex berry");
        
        alex.setpDetail(alexDetail);
        
        session.save(alex);
        //session.save(alexdetail); 이건 안함. 카스케이드 라서 
        session.getTransaction().commit();
        
        
    }
}
 
cs


결과는 다음과 같다. 

1
2
3
 
Hibernate: insert into TESTSCHEMA.PersonDetail (income, job, zipCode, detailId_PK) values (?, ?, ?, ?)
Hibernate: insert into TESTSCHEMA.Person (pDetail_FK, personName, personId) values (?, ?, ?)
cs


테이블 구조를 보자. Person의 테이블을 살펴보면 PersonId는 기본키이며 pDetail_FK는 외래키로 생성이 될것이다. 여기까지 OneAndOne 설명을 마친다. 


posted by 제스트
:
개발관련/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 제스트
:
개발관련/Spring 2015. 12. 4. 17:22

이번엔 복합키에 대해 알아보자. 


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
package com.zest.hibernate.chapter4;
 
import javax.persistence.Entity;
import javax.persistence.Id;
 
@Entity
public class Accounts {
 
    private int userId;
    private int accountId;
    
    
//    @Id
//    //만약 변수에 annotaion을 할꺼면 private는 안된다. 다른 객체이므로. getxxx 에 annotaion을 붙이면 된다. 
//    CompoundKey compoundKey;
    private int accountBalance;
    
    
//    public CompoundKey getCompoundKey() {
//        return compoundKey;
//    }
//    public void setCompoundKey(CompoundKey compoundKey) {
//        this.compoundKey = compoundKey;
//    }
    public int getAccountBalance() {
        return accountBalance;
    }
    public void setAccountBalance(int accountBalance) {
        this.accountBalance = accountBalance;
    }
    
    
}
 
cs


userId와 accountId에 복합키를 걸면 어떻게 할까? 


자 새로운 객체를 한개더 생성하자. 클래스 이름은 CompundKey이다. 

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
 
package com.zest.hibernate.chapter4;
 
import java.io.Serializable;
 
import javax.persistence.Embeddable;
 
//필히 Serializable 해줘야함. 
@Embeddable
public class CompoundKey implements Serializable{
 
    private int userId;
    private int accountId;
    
    public CompoundKey(int userId, int accountId){
        this.accountId = accountId;
        this.userId = userId;
    }
    
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public int getAccountId() {
        return accountId;
    }
    public void setAccountId(int accountId) {
        this.accountId = accountId;
    }
    
    
    
}
 
cs


여기서도 @Embeddable 이라는 어노테이션을 사용한다. 중요한 점은 필히 

Serializable을 해야하는 점이다. 그리고 Accounts 클래스를 수정하자. 


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
 
package com.zest.hibernate.chapter4;
 
import javax.persistence.Entity;
import javax.persistence.Id;
 
@Entity
public class Accounts {
 
    //compound key로 옮겼으니 주석으로 막는다. 
//    private int userId;
//    private int accountId;
    
    
    @Id
    //만약 변수에 annotaion을 할꺼면 private는 안된다. 다른 객체이므로. getxxx 에 annotaion을 붙이면 된다. 
    CompoundKey compoundKey;
    private int accountBalance;
    
    
    public CompoundKey getCompoundKey() {
        return compoundKey;
    }
    public void setCompoundKey(CompoundKey compoundKey) {
        this.compoundKey = compoundKey;
    }
    public int getAccountBalance() {
        return accountBalance;
    }
    public void setAccountBalance(int accountBalance) {
        this.accountBalance = accountBalance;
    }
    
    
}
 
cs


CompoundKey라는 객체에 @Id 붙여 기본키를 만들었다. 다른 예제와 틀리게 private가 없을 것이다. 외부에 있는 변수를 끌어와서 private를 쓰면 에러가 난다. 이때 getxxx의 함수에 @Id를 붙이거나 또는 private 이상의 권한을 줘야만 된다. 


그럼 테스트 코드로... 

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
package com.zest.hibernate.chapter4;
 
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 AccountTest {
 
    @Test
    public void account1() {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Accounts.class);
        config.configure("hibernate.cfg.xml");
 
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
 
        CompoundKey key1 = new CompoundKey(10010001);
        Accounts savings = new Accounts();
        savings.setCompoundKey(key1);
        savings.setAccountBalance(8500);
        
        
        CompoundKey key2 = new CompoundKey(10020001);
        Accounts checking = new Accounts();
        checking.setCompoundKey(key2);
        checking.setAccountBalance(2500);
        
        
        session.save(savings);
        session.save(checking);
        session.getTransaction().commit();
    }
}
 
 
 
cs


index를 확인하면 userid와 accountid가 복합키로 생성되있을 것이다. 

posted by 제스트
:
개발관련/Spring 2015. 12. 4. 16:59

이번엔 두개의 클래스를 하나의 테이블로 만드는 법을 살펴 보자. 


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
package com.zest.hibernate.chapter3;
 
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
 
 
@Entity
public class School {
 
    
    @Id
    @GeneratedValue
    private int schoolId;
    private String schoolName;
    
    @Embedded
    private SchoolDetail schoolDetail;
    
    
    public SchoolDetail getSchoolDetail() {
        return schoolDetail;
    }
    public void setSchoolDetail(SchoolDetail schoolDetail) {
        this.schoolDetail = schoolDetail;
    }
    public int getSchoolId() {
        return schoolId;
    }
    public void setSchoolId(int schoolId) {
        this.schoolId = schoolId;
    }
    public String getSchoolName() {
        return schoolName;
    }
    public void setSchoolName(String schoolName) {
        this.schoolName = schoolName;
    }
    
    
    
    
}
 
cs

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
 
package com.zest.hibernate.chapter3;
 
import javax.persistence.Embeddable;
 
@Embeddable
public class SchoolDetail {
 
    private String schoolAddress;
    private boolean isPublishSchool;
    private int studentCount;
    
    public String getSchoolAddress() {
        return schoolAddress;
    }
    public void setSchoolAddress(String schoolAddress) {
        this.schoolAddress = schoolAddress;
    }
    public boolean isPublishSchool() {
        return isPublishSchool;
    }
    public void setPublishSchool(boolean isPublishSchool) {
        this.isPublishSchool = isPublishSchool;
    }
    public int getStudentCount() {
        return studentCount;
    }
    public void setStudentCount(int studentCount) {
        this.studentCount = studentCount;
    }
    
    
}
 
cs


두개의 클래스가 있는데 새로운 어노테이션 발견....

부모가 되는 클래스는에는 @Embeded 라는 어노테이션을 쓰고 자식이 되는 클래스에는 @Embedable 어노테이션을 사용한다. 


나머진 기존과 다를게 없다. 그럼 테스트코드. ㄱㄱ

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
 
package com.zest.hibernate.chapter3;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.Test;
 
import com.zest.hibernate.chapter2.Customer;
 
public class SchoolTest {
 
    @Test
    public void school1() {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(School.class);
        config.configure("hibernate.cfg.xml");
 
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
 
        SchoolDetail annsDetail= new SchoolDetail();
        annsDetail.setPublishSchool(false);
        annsDetail.setSchoolAddress("101 washington");
        annsDetail.setStudentCount(300);
        
        School stanns = new School();
        stanns.setSchoolName("st. anns school");
        stanns.setSchoolDetail(annsDetail);
        
        session.save(stanns);
        session.getTransaction().commit();
    }
}
 
cs


테스트 코드는 두개의 객체를 사용하여 트랜잰션에 묶어준다. 그럼 결과 sql문을 보자. 

1
2
 
Hibernate: insert into TESTSCHEMA.School (isPublishSchool, schoolAddress, studentCount, schoolName, schoolId) values (?, ?, ?, ?, ?)
cs


이런 문구가 나올것이다. 





posted by 제스트
:
개발관련/Spring 2015. 12. 4. 14:29

하나의 객체에 두개의 테이블 생성하기 를 해보자. 


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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.zest.hibernate.chapter2;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
 
 
@Entity
@Table(name="Customer")
@SecondaryTable(name="CustomerDetail")
public class Customer {
 
    
    @Id
    @GeneratedValue
    private int customerId;
    private String customerName;
    
    @Column(table="CustomerDetail")
    private String customerAddress;
    
    @Column(table="CustomerDetail")
    private int creditScore;
    @Column(table="CustomerDetail")
    private int rewardPoints;
    
    public int getCustomerId() {
        return customerId;
    }
    public void setCustomerId(int customerId) {
        this.customerId = customerId;
    }
    public String getCustomerName() {
        return customerName;
    }
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
    public String getCustomerAddress() {
        return customerAddress;
    }
    public void setCustomerAddress(String customerAddress) {
        this.customerAddress = customerAddress;
    }
    public int getCreditScore() {
        return creditScore;
    }
    public void setCreditScore(int creditScore) {
        this.creditScore = creditScore;
    }
    public int getRewardPoints() {
        return rewardPoints;
    }
    public void setRewardPoints(int rewardPoints) {
        this.rewardPoints = rewardPoints;
    }
    
    
    
}
 
cs


처음 보는 어노테이션이 등장한다. @SecondaryTable 이라는 넘이다. 기존 customer 말고 cumstomerDetail 이라는 테이블로 선언이 되었다. 이 객체의 재미난 점은 기본키는 둘다 같은 column을 사용한다는 것이다. 그리고 detail의 경우 cumstomerId를 기본키로 하면서 외래키를 가진다.  그리고 sencondaryTable에 추가할 컬럼은 @Column 어노테이션을 사용하여 추가한다. 


아마도 1:1 대응 구조에 사용하면 좋을듯 보인다. 그럼 테스트 코드를 보자. 

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
 
package com.zest.hibernate.chapter2;
 
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 CustomerTest {
 
    @Test
    public void customer1() {
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Customer.class);
        config.configure("hibernate.cfg.xml");
 
        new SchemaExport(config).create(truetrue);
 
        // 아래 두개의 구문은 객체를 트랜잭션을 컨트롤.
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
 
        session.beginTransaction();
 
        Customer alex = new Customer();
        alex.setCustomerName("Alex Rod");
        alex.setCustomerAddress("101 washington");
        alex.setCreditScore(780);
        alex.setRewardPoints(12000);
        
        session.save(alex);
        session.getTransaction().commit();
    }
}
 
cs



사용법은 앞서 보여준 방법과 동일한데 결과 로그는 두개의 테이블에 넣는다. 

1
2
3
 
Hibernate: insert into TESTSCHEMA.Customer (customerName, customerId) values (?, ?)
Hibernate: insert into TESTSCHEMA.CustomerDetail (creditScore, customerAddress, rewardPoints, customerId) values (?, ?, ?, ?)
cs




posted by 제스트
:
개발관련/Spring 2015. 12. 4. 13:59
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.zest.hibernate.chapter1;
 
import java.util.Calendar;
import java.util.Date;
 
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;
 
@Entity
@Table(name = "EmployeeInfo")
public class Employee {
 
    @Id
    @Column(name = "EmployeeId", nullable = false)
    /**
     * sequence table을 생성.
     * name= sequence table의 alias 이름.
     * table은 sequence table의 이름.  
     * pkColumnName 은  sequence table의 column이름.
     * pkColumnValue은  sequence table 값을 저장하는 이름.. 
     * 
     */
    
    @TableGenerator(name = "empid", table = "emppktb", pkColumnName = "empkey"
    , pkColumnValue = "empvalue", allocationSize=1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "empid")
    private int empId;
    private String empName;
 
    // db에 등록은 안되고 객체에서 db와 별도의 기능이 필요할 경우 사용되는 어노테이션.
    @Transient
    private String empPassword;
    @Column(nullable = false)
    private String empEmailAddress;
 
    @Basic
    private boolean isPermanent;
 
    @Temporal(TemporalType.DATE)
    private Calendar empJoinDate;
 
    // @Basic
    @Temporal(TemporalType.TIMESTAMP)
    private Date empLoginTime;
 
    public String getEmpPassword() {
        return empPassword;
    }
 
    public void setEmpPassword(String empPassword) {
        this.empPassword = empPassword;
    }
 
    public String getEmpEmailAddress() {
        return empEmailAddress;
    }
 
    public void setEmpEmailAddress(String empEmailAddress) {
        this.empEmailAddress = empEmailAddress;
    }
 
    //
    public boolean isPermanent() {
        return isPermanent;
    }
 
    public void setPermanent(boolean isPermanent) {
        this.isPermanent = isPermanent;
    }
 
    public Calendar getEmpJoinDate() {
        return empJoinDate;
    }
 
    public void setEmpJoinDate(Calendar empJoinDate) {
        this.empJoinDate = empJoinDate;
    }
 
    public Date getEmpLoginTime() {
        return empLoginTime;
    }
 
    public void setEmpLoginTime(Date empLoginTime) {
        this.empLoginTime = empLoginTime;
    }
 
    public int getEmpId() {
        return empId;
    }
 
    public void setEmpId(int empId) {
        this.empId = empId;
    }
 
    public String getEmpName() {
        return empName;
    }
 
    public void setEmpName(String empName) {
        this.empName = empName;
    }
 
}
 
cs


먼저 employee라는 클래스를 생성하자. 

@Entity 라는 어노테이션이 등장한다. 이넘은 db의 table을 지징하는넘이다. nosql에선 collection정도? 


@Table은 table의 이름을 바꾸고자 할 때 사용한다. 만약 이 어노테이션이 생략 되면 테이블 이름은 클래스 명과 동일하게 된다. 


@TableGenerator는 Sequence Table을 정의할 때 사용한다. 옵션은 다음과 같다. 

 name= sequence table의 alias 이름.

 table은 sequence table의 이름.  

 pkColumnName 은  sequence table의 column이름.

 pkColumnValue은  sequence table 값을 저장하는 이름.. 


@GenerartedValue는 auto increment 의 옵션이다. 이때 위의 예제는 segence table의 값을 사용할 때의 예제 이다. 


@Transient는 database의 table과 상관없이 employee 객체 안에서 다른 객체 또는 무언가 다른 작업을 하고 싶을 때 사용하는 옵션이다. 결국 db에 영향을 주지는 않는다. 


@Basic은 lazy 관련 옵션이다. 


@Temporal은 시간,날짜에 대한 옵션을 줄때 사용하는 어노테이션이다. 


이제 실행해보자..

1
2
3
4
5
6
7
8
9
10
11
 
    @Test
    public void entityTest1(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        config.configure("hibernate.cfg.xml");
        
        new SchemaExport(config).create(true,true);
        
        
    }
cs


아주 간단한 소스이다. 여기서 중요한 것은 create의 옵션이다. 첫번째 두번째 파라미터의 설명은 

script print the DDL to the console, export export the script to the database 

해석하자면 첫번째 것은 니가 실행하고자 하는거 콘솔에 찍을까? 두번째 것은 스크립트 실행할래? 이다. 두번째 것이 false로 되어있음 table이 생성되지 않는다.  그럼 로그를 살펴보자. 

1
2
3
4
5
6
7
8
INFO : org.hibernate.connection.DriverManagerConnectionProvider - connection properties: {user=user, password=****}
drop table TESTSCHEMA.EmployeeInfo
drop table TESTSCHEMA.emppktb
create table TESTSCHEMA.EmployeeInfo (EmployeeId integer not null, empEmailAddress varchar(255) not null, empJoinDate date, empLoginTime timestamp, empName varchar(255), isPermanent smallint not null, primary key (EmployeeId))
create table TESTSCHEMA.emppktb ( empkey varchar(255),  sequence_next_hi_value integer ) 
INFO : org.hibernate.tool.hbm2ddl.SchemaExport - schema export complete
INFO : org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:derby://localhost:1527/hibernateDb
 
cs


create 함수를 콜을 하면 기존의 테이블을 삭제하고 생성하는것이 보일것이다. 


이제 데이터를 추가해보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    @Test
    public void entityTest2(){
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        config.configure("hibernate.cfg.xml");
        
//        new SchemaExport(config).create(true,true);
        
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
        
        session.beginTransaction();
        
        Employee alex = new Employee();
        alex.setEmpName("Alex Berry");
        alex.setEmpEmailAddress("aaa@aa.com");
        session.save(alex);
        
        session.getTransaction().commit();
    }
cs


세션을 한개 만들어서 트랜잭션을 시작하게 된다. 작업을 마치고 commit으로 종료를 하게 된다. 

굉장히 심플하다. 아마도 jpa에서 이부분이 조금 변경 될 것이다. session 관련은 bean으로 뺄 것이며, 트랜잭션은 어노테이션 기반으로 처리 할것이고 repository 에서 save등등 sql문을 처리 할 것이다. 어쨋든 하이버네이트에선 위와 같이 처리하게 된다. 


위의 junit테스트를 실행해보면 insert 구문이 나올 것이다. 

empId의 경우는 sequence table에서 가져오므로 그냥 추가가 될것이다. 


이번에는 create함수를 사용하고 모든 컬럼에 값을 넣어보자. 


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
    @Test
    public void entityTest3(){
        //hibernate의 persitst를 위한 클래스
        AnnotationConfiguration config = new AnnotationConfiguration();
        config.addAnnotatedClass(Employee.class);
        //db 접속 정보들을 저장.
        config.configure("hibernate.cfg.xml");
        
        //db 접속후 여러개의 테이블을 자동으로 제너레이트 해주는 객체.
        //<property name="hibernate.default_schema">TESTSCHEMA</property> 이구문역시 마찬가지임.
        new SchemaExport(config).create(true,true);
        
        //아래 두개의 구문은 객체를 트랜잭션을 컨트롤. 
        SessionFactory factory = config.buildSessionFactory();
        Session session = factory.getCurrentSession();
        
        session.beginTransaction();
        
        Employee alex = new Employee();
//        alex.setEmpId(2);
        alex.setEmpName("Alex Berry11");
        alex.setEmpEmailAddress("alex@hibernate.com");
        alex.setEmpPassword("alexpass");
        alex.setEmpJoinDate(new GregorianCalendar(2009,05,26));
        alex.setEmpLoginTime(Date.valueOf("2010-06-05"));
        session.save(alex);
        
        session.getTransaction().commit();
        session.close();
    }
cs


기존 데이터가 삭제되고 한개만 추가 될것이다. 


https://github.com/zest133/hibernateTest.git 소스는 다운받을 수 있다. 

posted by 제스트
:
개발관련/Spring 2015. 12. 4. 11:46


(출처:http://www.dil.univ-mrs.fr/~massat/docs/hibernate-3.1/reference/ko/html_single/)

하이버네이트의 기본 개념은 위와 같다.  

orm(object relation mapping )기반 이며, spring data의 jpa 역시 내부적으로 hibernate를 감싸서 만들었다. 


예제들은 아파치에서 무료로 제공하는 derby 를 사용한다. 사실 머 db는 상관없다. 



먼저 pom파일을 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>3.4.0.GA</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.3.2.GA</version>
        </dependency>
        <dependency>
            <groupId>org.apache.derby</groupId>
            <artifactId>derbyclient</artifactId>
            <version>10.12.1.1</version>
        </dependency>
cs


hibernate를 추가하고 derby database client를 추가한다. 


context.xml을 살펴보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="configLocation" >
      <value>hibernate.cfg.xml</value>
  </property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
      <ref bean="sessionFactory" />
    </property>
</bean>
 
</beans>
 
cs


hibernate.cfg.xml이라는 설정파일이 보이고 hibernateTemplate이라는 객체가 보인다. 위와 같이 설정해주자. 


다음은 hibernate.cfg.xml 설정이다. 

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
 
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
  
     <property name="connection.driver_class">org.apache.derby.jdbc.ClientDriver</property>
       <property name="connection.url">jdbc:derby://localhost:1527/hibernateDb</property
     <property name="connection.username">user</property>
     <property name="connection.password">password</property>
     <!-- SQL dialect -->
     <property name="dialect">org.hibernate.dialect.DerbyDialect</property>
 
     <property name="hibernate.default_schema">TESTSCHEMA</property>
     <!--  session을 사용하기 위한 정의 없으면 No CurrentSessionContext configured! 요에러 뜬다.  -->
     <property name="current_session_context_class">thread</property>
     <!-- JDBC connection pool (use the built-in) -->
     <property name="connection.pool_size">2</property>
 
 
     <!-- Echo all executed SQL to stdout -->
     <property name="show_sql">true</property>
 
     <!-- Drop and re-create the database schema on startup 
     <property name="hbm2ddl.auto">create</property>-->
  </session-factory>
</hibernate-configuration>
cs


여기서 중요한 건 dialect이다. 모든 db마다 dialect가 있고 아마도 저넘이 database마다 존재 하는 것으로 봐선 sql문으로 변환을 해주는 느낌이다. 그리고 마지막 부분의 hdm2ddl.auto 라는 넘이 있는데 저 구분을 활성화 하면 할때마다 기존 것들을 지우고 다시 만든다.  derby는 설치하기 쉬우니 생략~


모든 설정이 끝났다. 다음 글에서 부터 예제를 만들어보자. 



posted by 제스트
: