I. Installation Install a Hibernate Plugin... 2 II. Hibernate Configuration DataSource 속성정의 Generated SQL 속성정의..

Size: px
Start display at page:

Download "I. Installation Install a Hibernate Plugin... 2 II. Hibernate Configuration DataSource 속성정의 Generated SQL 속성정의.."

Transcription

1 Anyframe Hibernate Plugin Version 저작권 삼성 SDS 본문서의저작권은삼성 SDS 에있으며 Anyframe 오픈소스커뮤니티활동의목적하에서자유로운이용이가능합니다. 본문서를복제, 배포할경우에는저작권자를명시하여주시기바라며본문서를변경하실경우에는원문과변경된내용을표시하여주시기바랍니다. 원문과변경된문서에대한상업적용도의활용은허용되지않습니다. 본문서에오류가있다고판단될경우이슈로등록해주시면적절한조치를취하도록하겠습니다.

2 I. Installation Install a Hibernate Plugin... 2 II. Hibernate Configuration DataSource 속성정의 Generated SQL 속성정의 Cache 속성정의 Logging 속성정의 기타속성정의 매핑파일정의 Mapping File Mapping File 의작성 Mapping File 구성 Data Type 의매핑 Data Type 의매핑 Hibernate Generator Hibernate 기본 Id Generator 직접생성 Persistence Mapping Persistence Mapping - Association One to One Mapping One to Many Mapping Many to Many Mapping Persistence Mapping - Inheritance Table per Class Hierarchy Table per Subclass Table per Concrete Class Basic CRUD 단건조회 단건저장 Tip. A:B=1:m 인경우 A 에대한 save() 단건수정 단건저장또는수정 단건삭제 복수건저장 HQL(Hibernate Query Language) 구성요소 [ 선택 ] SELECT 절 [ 필수 ] FROM 절 [ 선택 ] WHERE 절 [ 선택 ] ORDER BY 절 [ 선택 ] GROUP BY 절 기본적인사용방법 Case 1. Basic Case 2. Join 원하는객체형태로전달 Case 1. 특정객체형태로전달 Case 2. Map 형태로전달 Case 3. List 형태로전달 XML 에 HQL 정의하여사용 Pagination HQL 을이용한 CUD 등록 (Insert) 수정 (Update) 삭제 (Delete) ii

3 Anyframe Hibernate Plugin 7. Criteria Queries 기본적인사용방법 Case 1. Basic Case 2. Join 원하는객체형태로전달 Case 1. 특정객체형태로전달 Case 2. Map 형태로전달 Pagination Native SQL 기본적인사용방법 Case 1. Basic Case 2. Join Case 3. 검색조건명시 XML 에 Native SQL 정의하여사용 Pagination Callable Statement Case 1. XML 에정의한 Procedure 호출 Case 2. Function 을이용한 HQL 실행 Performance Strategy Cache LC (1 Level Cache) LC (2 Level Cache) 분산 Cache Fetch Strategy Batch 를이용하여데이터조회 Sub-Query 를이용하여데이터조회 join fetch 를이용하여데이터한꺼번에조회 Concurrency Optimistic Locking Pessimistic Locking Offline Locking Transaction Management JDBC - HibernateTransactionManager JTA - JTATransactionManager Spring Integration Hibernate 속성정의파일작성 Session Factory 속성정의 Dynamic HQL, Dynamic Native SQL 실행을위한 DynamicHibernateService 속성정의 Mapping XML 파일작성 DAO 클래스생성 DAO 속성정의파일작성 DAO 클래스개발 Test Code 작성 선언적인트랜잭션관리 III. Dynamic Hibernate Configuration Dynamic HQL(Hibernate Query Language) Dynamic Native SQL iii

4 I.Installation Hibernate Plugin 은대표적인 ORM(Object Relational Mapping) 도구인 Hibernate [ 의기본활용방법을가이드하기위한샘플코드와이오픈소스들을활용하는데필요한참조라이브러리들로구성되어있다.

5 1.Install a Hibernate Plugin 본장에서는 Hibernate Plugin 설치로생성된샘플코드를중심으로보다폭넓게오픈소스활용방법에대해보다상세히다루게될것이다. 본장의내용을본격적으로시작하기에앞서로컬 PC 에 Hibernate Plugin 을설치해보도록하자. 1. Hibernate Plugin 을설치하기위해서는모든 Plugin 의기반이되는 Foundation Plugin 이설치되어있어야한다. Foundation Plugin 설치가필요한경우에는 Foundation Plugin 설치하기 [ foundation.html#foundation_installation] 를참조하도록한다. 2. Command 창에서샘플프로젝트의위치로이동한후, db/hsqldb/start.cmd (or start.sh) 을실행시킴으로써샘플 DB 를시작시킨다. ( 기본적으로제공되는 HsqlDB 가아닌다른 DB 를활용하고자하는경우에는본문서내의 DB 변경 [ htmlsingle/ide.html#cli_maven_db] 을참조하도록한다.) 3. Command 창에서다음과같이명령어를입력하여 hibernate plugin 을설치한다. mvn anyframe:install -DpluginName=hibernate 4. Command 창에서다음과같이명령어를입력한후, Jetty Server 가정상적으로시작되었으면브라우저를통해 hibernate plugin 이정상적으로설치되었는지확인한다. ( 생성된샘플프로젝트명이 myproject 인경우브라우저주소창에 를입력한다.) mvn clean jetty:run 위그림에서보이는바와같이왼쪽메뉴에 Foundation Sample 메뉴외에 Hibernate Sample 메뉴가추가된것을확인할수있을것이다. Hibernate Sample 메뉴를클릭하여 Hibernate 기반에서실행되는샘플어플리케이션의기능을확인해보도록하자. WAS(Web Application Server) 별유의사항 본문서에서는 Plugin 설치로생성된샘플어플리케이션을실행시키기위한 WAS 로써 Jetty, Tomcat 를채택하여설명을기술하고있다. 그러나 Plugin 설치로생성된샘플어플리케이션은특정 WAS 에종속되지않으므로 mvn clean compile war:war 와같은명령어실행을통해패키징한후 WebLogic, JEUS 와같은다른 WAS 에 deploy 하여실행시키는것도가능하다. 단, 샘플어플리케이션이참조하는일부라이브러리의버전을해당 WAS 에서지원하지않는경우가있어조치사항을언급하고자한다. 먼저, Foundation 매뉴얼내의 WAS(Web Application Server) 별유의사항 [ htmlsingle/foundation.html#foundation_overview_note] 을참고하도록한다. Foundation Plugin 외에도설치된다른 Plugin 이있는경우에는, 각 Plugin 매뉴얼내의 Installation > "WAS(Web Application Server) 별유의사항 " 도함께참고하도록한다. 2

6 Install a Hibernate Plugin 다음은 Hibernate Plugin 이설치된샘플어플리케이션에대한 WAS 별유의사항이다. WebLogic 10.1 : JavaEE 5 를지원하는 WebLogic 10.1 에서는 JPA 1.0 라이브러리가표준으로포함되어있기때문에, 다음과같은문제가발생할수있다. Hibernate Plugin 설치로생성된샘플어플리케이션프로젝트는 Hibernate 기반 Movie 관리정보를수행하기위해 Hibernate 라이브러리를활용하고있으며이라이브러리는 JPA 2.0 라이브러리를참조한다. 그런데 WebLogic 10.1 은 JPA 1.0 라이브러리를기준으로동작하므로 javax.persistence.onetomany.orphanremoval() 실행시, NoSuchMethodException 이발생한다. 이는 weblogic.xml 에서 prefer-web-inf-classes을 true로조정하여도별다른효과가없으므로, Foundation Plugin 내에기술된 WAS(Web Application Server) 별유의사항 [ reference/htmlsingle/foundation.html#foundation_overview_note] 을참고하여해당문제점을회피할수있다 : JavaEE 6 를지원하는 WebLogic 에서는 JPA 1.0 라이브러리가표준으로포함되어있기때문에, 다음과같은문제가발생할수있다. Hibernate Plugin 설치로생성된샘플어플리케이션프로젝트는 Hibernate 기반 Movie 관리정보를수행하기위해 Hibernate 라이브러리를활용하고있으며이라이브러리는 JPA 2.0 라이브러리를참조한다. 그런데 WebLogic 10.1 은 JPA 1.0 라이브러리를기준으로동작하므로 javax.persistence.onetomany.orphanremoval() 실행시, NoSuchMethodException 이발생한다. 이는 Foundation Plugin 내에기술된 WAS(Web Application Server) 별유의사항 [ reference/htmlsingle/foundation.html#foundation_overview_note] 을참고하여해당문제점을회피할수있다. 3

7 II.Hibernate Hibernate 는객체모델링 (Object Oriented Modeling) 과관계형데이터모델링 (Relational Data Modeling) 사이의불일치를해결해주는 ORM 도구로, EJB 의 Entity Bean 과같이특정플랫폼에의존적인제약을정의하고있지않기때문에 POJO 기반개발이가능하다. 또한 Java 에서지원하는다양한 Collection 유형을지원함으로써객체모델링을관계형모델링으로매핑하는데따르는제약을최소화하고있다. Hibernate 의특징을살펴보면, 다음과같다. Hibernate 기반개발시특정 DBMS 에영향을받지않으므로 DBMS 가변경되더라도데이터액세스처리코드에대한변경없이설정정보의변경만으로도올바르게동작가능하다. SQL 을작성하고 SQL 실행결과로부터전달하고자하는객체로변경하는코드를작성하는시간이줄어들기때문에개발자는비즈니스로직에집중할수있게되고, 개발시간이단축될수있다. JDBC Api 를사용한코드의양이줄어들고, 매핑파일을별도로관리하게되면서 DB 정보변경으로인해영향을받는부분또한감소한다. 다음과같은접근방법을취함으로써, DBMS 에대한접근횟수를줄여나가궁극적으로어플리케이션의성능향상을도모한다. 기본적으로필요시점에만 DBMS 에접근하는 Lazy Loading 전략채택 Session 종료시에변경사항에대해일괄 batch 처리 1st Level Cache, 2nd Level Cache 를활용하여 DBMS 에대한재접근없이 Caching 된객체사용 대부분의개발자가어플리케이션의데이터액세스로직을개발하기위해 DTO(Data Transfer Object), DAO 패턴을사용하는데익숙하기때문에데이터와로직을가진객체를설계하는데익숙하지못하다는단점을가지고있다. 본페이지에서는 Hibernate Final 버전을이용하여 Hibernate 기본개념에대해서살펴볼것이다. 먼저어플리케이션실행여부와상관없이물리적으로존재하는데이터들을정의하고있는 Persistent Class 와 Persistent Class 의 Lifecycle 에대해알아보고이러한객체들의영속성을관리하는 Hibernate Session 에대해정리해보고자한다. Conceptual Architecture Hibernate 기본구성은다음그림과같다.

8 위그림에서와같이 Hibernate 이 DBMS 기반의어플리케이션수행을하기위해필요한주요구성요소는 Persistent Objects, Hibernate Properties, XML Mapping 이며, 각각은다음과같은역할을수행한다. Persistent Objects : Persistent Object 는어플리케이션실행여부와상관없이물리적으로존재하는데이터들을다룬다. 일반적으로 DBMS 데이터를이용하는어플리케이션을개발할경우어플리케이션의비즈니스레이어에서특정 DBMS 에맞는 SQL 을통해어플리케이션의데이터를처리하게된다. 그러나 Hibernate 기반의어플리케이션에서는 Persistent Object 를중심으로하여어플리케이션의데이터와 DBMS 연동이가능해진다. Hibernate Properties : Hibernate 실행에관련된속성정보를포함하고있는파일로, hibernate.cfg.xml 또는 hibernate.properties 형태로정의할수있다. 주로 DBMS, Logging, Cache, Mapping File 정보등을다루고있다. XML Mapping :Persistent Object 과특정테이블사이의다양한매핑정보를명시하기위한 XML 파일이다. Hibernate 는 Hibernate Mapping XML 을기반으로하여실행할 SQL 을생성하고있다. Persistent Classes Persistent Class 는 Hibernate 를이용하여 DB 의특정테이블과매핑되는객체로 Hibernate 를제대로사용하기위해서는 Persistence Class 작성이중요하다. Java Class 를 Hibernate 의 Persistent Class 로사용하기위한기본요건은다음과같다. [ 필수 ] Default Constructor 구현 : Hibernate 에서는 Constructor.newInstance() 를이용하여해당클래스의인스턴스를생성하므로 Persistence Object 로사용하기위해서는해당클래스내에입력인자를갖지않은 Default Constructor 를생성해야함에유의하도록한다. public class Category implements java.io.serializable { <!-- 중략 --> public Category() { [ 권장 ] 테이블의 Primary Key 칼럼과매핑되는 identifier field 정의 : 일반적인경우 Hibernate Persistent Class 에 DB 테이블의 primary key 와매핑되는 identifier field 가반드시존재해야할필요는없지만몇가지경우에반드시필요하다. ( 예 : Session.saveOrUpdate or Session.merge 메소드이용시 ) 하지만일반적인 Domain Object 에서 identifier 를갖는것이일반적이므로 Persistent Class 에 identifier field 정의하는것을추천한다. [ 권장 ] final 클래스로정의하지않음 : Hibernate 의 lazy loading 은 proxy 를사용해야하는데 final 로 Persistent class 를선언할경우 proxy 를사용할수없다. [ 권장 ] 속성정보접근을위한 getter, setter 정의 : Hibernate 는 getter/setter 로구성된 method 가존재할경우매핑처리를할수있다. public class Category implements java.io.serializable { private String categoryid; private String categoryname; public String getcategoryid() { return this.categoryid; public void setcategoryid(string categoryid) { this.categoryid = categoryid; public String getcategoryname() { return this.categoryname; public void setcategoryname(string categoryname) {

9 this.categoryname = categoryname; 만약 Mapping File 에 DB 컬럼에대한매핑정보를아래와같이설정한다면 gettter/setter 메소드가필요없다. <property name="name" column="name" access="field"/> [ 선택 ] equals(), hashcode() 메소드구현 : 다음에서동일한테이블의동일한행의데이터를읽어온 category1 과 category2 는다른 Session 을통해얻어졌으므로동일한객체가아닌것으로처리된다. 이처럼다른 Session 을통해얻어온객체의동일함을비교할필요가있을경우에는 equals() 메소드를적절히구현해주도록한다. Session session1 = SessionFactory.openSession(); Category category1 = (Category)session1.get(Category.class, "test"); session1.close(); Session session2 = SessionFactory.openSession(); Category category2 = (Category)session2.get(Category.class, "test"); session2.close(); public boolean equals(object other) { if (!(other instanceof Category) ) return false; Category castother = (Category) other; return new EqualsBuilder().append(this.getCategoryId(), castother.getcategoryid()).isequals(); public int hashcode() { return new HashCodeBuilder().append(getCategoryId()).toHashCode(); [ 선택 ] Serializable 인터페이스구현 : Hibernate 에서 persistent class 들이 java.io.serializable 인터페이스를반드시 implement 해야하는것은아니지만, persistent object 가 HttpSession 에저장되거나 RMI 를이용해서전달할때는반드시필요한다. public class Category implements java.io.serializable { 중략 Dynamic Model Hibernate 는 Dynamic Model(Map) 을지원하기때문에 Persistent entity 가 JavaBean 이나 POJO 일필요는없다. Dynamic Model 을이용할때는 Persistent Class 를작성하지않고 Hibernate Mapping 파일에정의만하면된다. 다음은 Map 을이용해 Hiberante 의 Session 에접근하는소스의일부이다. Session sessions = SessionFactory.openSession(); Map categorymap = new HashMap(); categorymap.put("categoryid", "CTGR-0001"); categorymap.put("categoryname", "Romantic"); categorymap.put("categorydesc, "Romantic genre"); sessions.save("category", categorymap); 중략 Hibernate Session Session 은 Hibernate 과 DB Connection 사이의연결고리역할을수행하는객체로써, Session 생성시에단일 DB Connection 을열고 Session 이종료될때까지 Connection 을유지하게된다. Hibernate 에의해로드된모든객체

10 (Persistent 객체 ) 는 Session 과연관되어있어, Session 에의해객체의변경사항이자동반영되거나 Lazy Loading 처리될수있다. Session 은 Hibernate 과 DB Connection 사이의연결고리역할을수행하는객체로써, Session 생성시에단일 DB Connection 을열고 Session 이종료될때까지 Connection 을유지하게된다. Hibernate 에의해로드된모든객체 (Persistent 객체 ) 는 Session 과연관되어있어, Session 에의해객체의변경사항이자동반영되거나 Lazy Loading 처리될수있다. 새로운 Session 생성은 SessionFactory 를통해이루어질수있으며다음은 Hibernate 에서 hibernate.cfg.xml 파일을기반으로 SessionFactory 를초기화시키는예제코드이다. SessionFactory initialsessionfactory = new Configuration().configure(hibernateconfig/hibernate.cfg.xml").buildSessionFactory(); SessionFactory 를통해신규 Session 을생성하는방법은 opensession() 과 getcurrentsession() 두가지로구분해볼수있다. opensession SessionFactory 의 opensession() 메소드를호출할때마다새로운 Session 이생성된다. Session session1 = SessionFactory.openSession(); Session session2 = SessionFactory.openSession(); 위소스에서생성된 session1 과 session2 는서로다른 session 이다. getcurrentsession SessionFactory 에서 Session 을생성하는또다른방법으로, getcurrentsession() 메소드를이용하는방법이있다. getcurrentsession() 은 Proxy 를리턴하고생성된 Session 이있을경우에는생성된 Session 을, 없을경우에는신규 Session 을리턴한다. Session session1 = initialsessionfactory.getcurrentsession(); Session session2 = initialsessionfactory.getcurrentsession(); session1.close(); Session session3 = initialsessionfactory.getcurrentsession(); getcurrentsession() 을호출하는경우로 session1 과 session2 는동일한 Session 의 Proxy 객체이나 session3 은다른 Proxy 객체임을확인할수있다. opensession(), getcurrentsession() 메소드를호출해서얻어진 Session 에는차이가있다. opensession() 으로생성된 Session 은관련된트랜잭션이종료되더라도종료되지않는반면, getcurrentsession() 으로얻어진 Session 은트랜잭션종료시해당 Session 도함께종료된다. 따라서 opensession() 으로얻어진 Session 에대해서는 session.close() 를호출해서직접 Session 을종료해주어야하며, getcurrentsession() 으로얻어진 Session 에대해서는따로 Session.close() 메소드를호출하지않아야한다. Persistent Object States Lifecycle Hibernate 에서 Persistent Object 는 Transient, Persistent, Detached 의 3 가지상태를가질수있으며, 상태변이를발생시킨다. 각상태에관한내용은다음과같다.

11 Transient : 객체는생성되었으나아직 Hibernate 에의해관리되지않는경우 Category category = new Category(); category.setcategoryid("ctgr-0001"); category.setcategoryname("romantic"); category.setcategorydesc("romantic genre");.. 중략 위의소스에서처럼 persistent class 의인스턴스는생성되었지만 Hibernate 에의해서아직관리되지않은상태를 Transient 상태라고한다. Persistent : Hibernate 에의해관리되는객체로써 Hibernate 에서제공하는기능 ( 테이블의특정행과매핑되며변경값자동반영, Lazy Loading 등 ) 이적용되는경우 Category category = new Category(); category.setcategoryid("ctgr-0001"); category.setcategoryname("romantic"); category.setcategorydesc("romantic genre"); // -- transient 상태 session.save(category); // -- Persistent 상태 Transient 상태의 persistent class 를 Hibernate 의 Session 의 save(),persist() 와같은 method 를이용하면 Hibernate 에서제공하는기능을사용할수있는상태인 Persistent 상태가된다. 아래는 Persistent 상태인 Object 의값을변경했을때자동으로 DB 에변경된내용이반영되는것을테스트하기위한 HibernatePersistentObjcetStates.java 의일부분이다. public void persistentstate() throws Exception { newsession(); Category category = new Category(); category.setcategoryid("ctgr-0001"); category.setcategoryname("romantic"); category.setcategorydesc("romantic genre"); session.save(category); category.setcategoryname("comedy"); category.setcategorydesc("comedy consists..."); closesession();

12 다음은위테스트코드를실행시켰을때 query log 의일부분이다. 1: insert into PUBLIC.CATEGORY (CATEGORY_NAME, CATEGORY_DESC, CATEGORY_ID) values ('Romantic','Romantic genre', 'CTGR-0001') 1: update PUBLIC.CATEGORY set CATEGORY_NAME='Comedy', CATEGORY_DESC='Comedy consists' where CATEGORY_ID='CTGR-0001' 위로그에서알수있듯이 category 의값을변경한후 save 나 update 명령을실행하지않았음에도불구하고 transaction 이종료됐을때 update query 가실행된다. 이처럼 persistent 상태가되면 DB 테이블의특정행과매핑되어값이자동으로반영된다. Detached : Hibernate 에의해관리되는객체이나 Persistent 상태와는달리 Hibernate 에서제공하는기능이지원되지않는상태로객체의속성값이바뀌더라도 DB 에변경된값이자동반영되지않는경우 아래는 Detached 상태가된 persistent object 의값을변경시키고 Session 을닫았을때 DB 에반영이안되는경우를테스트하는 HibernatePersistentObjcetStates.java 의일부분이다. public void detachedstate() throws Exception { newsession(); Category category = new Category(); category.setcategoryid("ctgr-0001"); category.setcategoryname("romantic"); category.setcategorydesc("romantic genre"); session.save(category); closesession(); newsession(); category.setcategoryname("comedy"); category.setcategorydesc("comedy consists"); closesession(); 위테스트케이스에서보면 closesession() 을해서 persistent object 의 state 를 detached 상태로만든후에값을변경하고다음 Session 을 close 시키면 persistent state 때와는달리 update 가되지않는다. 실행되는 query 로그는다음과같다. insert into PUBLIC.CATEGORY (CATEGORY_NAME, CATEGORY_DESC, CATEGORY_ID) values ('Romantic', 'Romantic genre', 'CTGR-0001' 위 query 로그에서보듯이 persistent state 상태일때와는달리 persistent object 가변경되었음에도 update query 가실행되지않는다. 참고 : 한 Session 내에서 Initialize 되지않은객체는해당 Session 종료로인해 Detached 상태로변경되었을때에는객체정보를읽을수없다. 아래는 Session 이종료되서 Detached 상태로된객체에서 initialize 되지않은연관객체의정보를읽을때 LazyInitializationException 발생하는것을확인하는테스트코드 HibernateLazyInitializationException.java 의일부분이다. public void findmovie() throws Exception { Movie movie = (Movie) session.get(movie.class, "MV-00001"); session.close();

13 try { movie.getcategories().iterator(); fail("expected LazyInitializationException"); catch (Exception e) { Movie 와 Category 는 1:n 관계를갖고있다. MOVIE 테이블을대상으로단건조회작업을수행한후, Session 을종료하여 Movie Object 를 Detached 상태로만든다. 그리고 initialize 되지않은 Category 목록정보를얻으려할때 LazyInitializationException 이발생한다.

14 2.Configuration Hibernate 은실행속성을포함하고있는 hibernate.cfg.xml ( 또는 hibernate.properties) 을기반으로하여동작하도록구성되어있다. 본페이지에서는 hibernate.cfg.xml 파일의주요구성요소와속성정의방법에대해살펴보기로한다. 먼저, hibernate.cfg.xml 파일은가장상위에 <hibernateconfiguration> 태그를포함하고있으며 <hibernate-configuration> 태그내에 <security> 와 <sessionfactory> 를포함할수있다. <session-factory> 는 Hibernate SessionFactory 가 DB 정보와 Hibernate Mapping XML 정보를기반으로 Session 을생성하여전달하는데필요한정보를정의하기위한태그이다. <session-factory> 내에는다양한속성정의가가능하나본페이지에서는그중일부속성에대해서만다루기로한다. Hibernate Configuration 에대한자세한내용은 Hibernate Documentation Chapter 3. Configuration [ html-single/reference_guide/index.html#configuration] 원본을참고하도록한다. 2.1.DataSource 속성정의 다음속성들을통해 Hibernate 는특정 DB 에접근하여데이터액세스처리가가능하다. 구분 Name Description JDBC hibernate.connection.driver_class 접근대상이되는 DB의 Driver 클래스명을정의하 기위한속성 JDBC hibernate.connection.url 접근대상이되는 DB 의 URL 을정의하기위한속성 JDBC hibernate.connection.username DB에접근할때사용할사용자명을정의하기위한 속성 JDBC hibernate.connection.password DB에접근할때사용할패스워드를정의하기위한 속성 JDBC hibernate.connection.pool_size Connection Pool에생성할최대 Connection 크기를정의하기위한속성. Hibernate는자체적으로기본 Connection Pool을사용할수있으나운영시스템용도로개발된것이아니어서다양한기능을제공하지못하고안정적이지못하다. 따라서 DBCP나 C3P0 등과같은 Connection Pool 구현체를채택하여 Connecction을관리하는것이좋다. J2EE hibernate.connection.datasource JNDI를통해연결할 DataSource의 JNDI 명을정의 하기위한속성 J2EE hibernate.jndi.url JNDI Provider URL 을정의하기위한속성 J2EE hibernate.jndi.class JNDI InitialContextFactory 클래스명을정의하기위 한속성 J2EE hibernate.connection.username DB에접근할때사용할사용자명을정의하기위한 속성 J2EE hibernate.connection.password DB에접근할때사용할패스워드를정의하기위한 속성 다음은위에서언급한속성들을포함하고있는 hibernate.cfg.xml 파일의일부이다. <session-factory> <property name="hibernate.connection.driver_class">net.sf.log4jdbc.driverspy</property> <property name="hibernate.connection.url"> jdbc:log4jdbc:oracle:thin:@localhost:1521:xe</property> <property name="hibernate.connection.username">user</property> <property name="hibernate.connection.password">password</property> 11

15 Configuration... </session-factory> 2.2.Generated SQL 속성정의 Name hibernate.dialect hibernate.default_schema hibernate.default_catalog Description Hibernate 기반개발시 DB 에특화된 SQL 을구성하지않더라도 DB 에따라알맞은 SQL 을생성할수있다. 이를위해서 Dialect 클래스를사용한다. hibernate.dialect 는 Dialect 클래스명을정의하기위한속성 Hibernate 에서 SQL 을생성할때특정테이블에대해별도정의된 Schema 가없는경우적용할 DB Schema 명을정의하기위한속성 Hibernate 에서 SQL 을생성할때특정테이블에대해별도정의된 Catalog 가없는경우적용할 DB Catalog 명을정의하기위한속성 다음은위에서언급한속성들을포함하고있는 hibernate.cfg.xml 파일의일부이다. <session-factory>... <property name="hibernate.default_schema">athena</property> <property name="hibernate.dialect">org.hibernate.dialect.oracle10gdialect</property>... </session-factory> 다음은 Hibernate 에서제공하는주요 Dialect 클래스목록이다. DB 종류 DB2 HSQLDB Informix MySQL 5.x MySQL 4.x, 3.x Oracle 10g Oracle 9i/10i Oracle ( 모든버전 ) SAP DB SQL Server 2000 Sybase Sybase Anywhere Dialect 클래스 org.hibernate.dialect.db2dialect org.hibernate.dialect.hsqldialect org.hibernate.dialect.informixdialect org.hibernate.dialect.mysql5dialect org.hibernate.dialect.mysqldialect org.hibernate.dialect.oracle10gdialect org.hibernate.dialect.oracle9idialect org.hibernate.dialect.oracledialect org.hibernate.dialect.sapdbdialect org.hibernate.dialect.sqlserverdialect org.hibernate.dialect.sybase11dialect org.hibernate.dialect.sybaseanywheredialect 2.3.Cache 속성정의 Name hibernate.cache.provider_class hibernate.cache.use_second_level_cache hibernate.cache.use_query_cache Description Cache 기능을구현하고있는구현체의클래스명을정의하기위한속성 2nd Level Cache 를적용할지여부를정의하기위한속성 (true false) Hibernate Query 를 Caching 할지여부를정의하기위한속성 (true false) 12

16 Configuration 다음은위에서언급한속성들을포함하고있는 hibernate.cfg.xml 파일의일부이다. 2nd Level Cache 를적용하고, Cache Provider 로 EhCacheProvider 를사용한예이다. <session-factory>... <property name="hibernate.cache.provider_class">org.hibernate.cache.ehcacheprovider</ property> <property name="hibernate.cache.use_second_level_cache">true</property>... </session-factory> 2.4.Logging 속성정의 Name hibernate.show_sql hibernate.format_sql hibernate.use_sql_comments Description Hibernate 을통해생성된 SQL 을콘솔에남길것인지여부를정의하는속성 (true false) hibernate.show_sql=true 인경우해당 SQL 문의포맷을정돈하여콘솔에남길것인지여부를정의하는속성 (true false) Hibernate 을통해생성된 SQL 을콘솔에남길때 Comments 도같이남길것인지여부를정의하는속성 (true false) 위에서언급한 hibernate.show_sql, hibernate.format_sql 속성을정의하였을경우 Hibernate 를통해생성된 SQL 문은다음과같은형태로콘솔에남게된다. Hibernate: insert into PUBLIC.COUNTRY(COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values(?,?,?) Hibernate 기본 Logging 은생성된 SQL 문을확인할때에는유용하나전달된인자값을확인할수가없어서개발시불편할것이다. Hibernate 에서는기본 SQL Logging 외에도 Jakarta commons-logging API 를사용하여로그를처리하고있어서, logging 을위한속성파일을정의하고다음과같은로그카테고리목록을활용하면개발시로그를통해좀더유용한정보를얻어낼수있을것이다. org.hibernate.sql org.hibernate.type 카테고리 org.hibernate.tool.hbm2ddl 설명 실행되는모든 DML 쿼리 Logging 모든 JDBC 인자 Logging 실행되는모든 DDL 쿼리 Logging org.hibernate.pretty Flush 수행시세션에저장된모든개체 ( 최대 20 개 ) 의상태를 Logging org.hibernate.cache org.hibernate.transaction org.hibernate.jdbc org.hibernate.hql.ast.ast org.hibernate.secure 2nd Level Cache 수행내역을 Logging 트랜잭션수행내역을 Logging 모든 JDBC 자원요청을 Logging 쿼리를파싱하는동안 HQL 과 SQL AST 를 Logging 모든 JAAS 인증요청을 Logging 다음은 hibernate.cfg.xml 파일내의 hibernate.show_sql 설정과무관하게, log4j.xml 파일내에 org.hibernate.sql, rg.hibernate.type Logger 의로그레벨을 DEBUG 로정의하였을경우 HibernateBasicCRUD.java 실행으로인해콘솔에남은 SQL 문의일부이다. 1. log4j.xml 13

17 Configuration <log4j:configuration xmlns:log4j=" <logger name="org.hibernate.sql"> <level value="debug" /> </logger> <logger name="org.hibernate.type"> <level value="debug" /> </logger>... </log4j:configuration> 2. Console - Hibernate Log DEBUG: org.hibernate.sql - insert into PUBLIC.COUNTRY(COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values(?,?,?) DEBUG: org.hibernate.type.stringtype - binding 'KR' to parameter: 1 DEBUG: org.hibernate.type.stringtype - binding 'Korea' to parameter: 2 DEBUG: org.hibernate.type.stringtype - binding 'COUNTRY-0001' to parameter: 3 위에서언급한 2 가지방법외에도 Log4jdbc( sourceforge.net/) [ code.google.com/p/log4jdbc/] 라는오픈소스를활용하면다음과같이 SQL 문에입력인자가대체된형태의 SQL 문을로그를통해확인할수도있다. Log4jdbc 를활용한 Query Logging 방법에대해서자세히알고싶은경우여기 [ htmlsingle/foundation.html#foundation_logging_sqllogging] 를참조하도록한다. DEBUG: jdbc.sqlonly - org.hibernate.jdbc.batchingbatcher.doexecutebatch (BatchingBatcher.java:48) 1. batching 1 statements: 1: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') 2.5. 기타속성정의 Name hibernate.hbm2ddl.auto hibernate.jdbc.batch_size Description Hibernate Mapping XML File (*.hbm.xml) 을기반으로 DDL 을자동으로검증, 생성또는수정할지여부를정의하기위한속성 (validate update create create-drop) Hibernate 는일반적으로실행해야할 SQL 들에대해일괄적으로 batch 처리를수행하는데이때 batch 로처리할 SQL 의개수를정의하기위한속성 hibernate.hbm2ddl.auto 속성을정의한경우별도 DDL 없이도정의된 Hibernate Mapping XML 파일을기반으로해당 DB 에관련된테이블을생성, 수정, 검증등을수행하게된다. 다음은 hibernate.hbm2ddl.auto=create 로정의한 hibernate.cfg. xml 과이를기반으로해당 DB 에관련테이블을생성하면서실행된 DDL 의일부이다. 1. hibernate.cfg.xml <session-factory>... <property name="hbm2ddl.auto">create</property>... </session-factory> 2. Console - Hibernate Log 14

18 Configuration... DEBUG: jdbc.sqlonly - org.hibernate.tool.hbm2ddl.schemaexport.execute(schemaexport.java:308) 1. {WARNING: Statement used to run SQL create table MOVIE_CATEGORY (CATEGORY_ID varchar(9) not null, MOVIE_ID varchar(255) not null, primary key (MOVIE_ID, CATEGORY_ID)) DEBUG: jdbc.sqlonly - org.hibernate.tool.hbm2ddl.schemaexport.execute(schemaexport.java:308) 1. {WARNING: Statement used to run SQL create table PUBLIC.CATEGORY (CATEGORY_ID varchar(9) not null, CATEGORY_NAME varchar(50) not null, CATEGORY_DESC varchar(100), primary key (CATEGORY_ID)) DEBUG: jdbc.sqlonly - org.hibernate.tool.hbm2ddl.schemaexport.execute(schemaexport.java:308) 1. {WARNING: Statement used to run SQL create table PUBLIC.COUNTRY (COUNTRY_CODE varchar(12) not null, COUNTRY_ID varchar(2) not null, COUNTRY_NAME varchar(50) not null, primary key (COUNTRY_CODE)) DEBUG: jdbc.sqlonly - org.hibernate.tool.hbm2ddl.schemaexport.execute(schemaexport.java:308) 1. {WARNING: Statement used to run SQL create table PUBLIC.MOVIE (MOVIE_ID varchar(255) not null, COUNTRY_CODE varchar(12), TITLE varchar(100) not null, DIRECTOR varchar(10) not null, RELEASE_DATE date, primary key (MOVIE_ID))... 다음은 hibernate.jdbc.batch_size=10 으로정의한 hibernate.cfg.xml 과이를기반으로하는 HibernateMultiDataSave 의실행결과의일부이다. HibernateMultiDataSave 코드의 session.flush() 부분을 breakpoint 로지정하고, DEBUG 모드로실행시켜보면서 batch 처리가제대로이루어지는지확인해보자. DEBUG: jdbc.sqlonly - org.hibernate.jdbc.batchingbatcher.doexecutebatch(batchingbatcher.java:48) 1. batching 10 statements: 1: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR0', 'Korea0', 'COUNTRY-0000') 2: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR1', 'Korea1', 'COUNTRY-0001') 3: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR2', 'Korea2', 'COUNTRY-0002') 4: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR3', 'Korea3', 'COUNTRY-0003') 5: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR4', 'Korea4', 'COUNTRY-0004') 6: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR5', 'Korea5', 'COUNTRY-0005') 7: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR6', 'Korea6', 'COUNTRY-0006') 8: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR7', 'Korea7', 'COUNTRY-0007') 9: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR8', 'Korea8', 'COUNTRY-0008') 10: insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR9', 'Korea9', 'COUNTRY-0009') 2.6. 매핑파일정의 Hibernate 를통해관리되어야할 Mapping XML File 목록을정의하기위한속성이며, 다음과같이정의할수있다. <session-factory> 15

19 Configuration... <mapping resource="anyframe/sample/model/bidirection/category.hbm.xml"/> <mapping resource="anyframe/sample/model/bidirection/country.hbm.xml"/> <mapping resource="anyframe/sample/model/bidirection/movie.hbm.xml"/>... </session-factory> 16

20 3.Mapping File Mapping XML File 은모델객체와데이터베이스의테이블간의매핑정보를담고있는설정파일이다. Mapping File 을작성할때는일정한규약이있으며 에맞게작성을해야한다. 다음은 Mapping File 작성방법, Java Data Type 와 DB 의 Data Type 과의매핑, 그리고 Hibernate Generator 에대한내용이다. 3.1.Mapping File 의작성 Mapping File 구성 Mapping File 의전체적인구성은아래와같다. Movie.hbm.xml 파일의일부이다. <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" " <hibernate-mapping> <class name="anyframe.sample.model.bidirection.country" table="country" lazy="true" schema="public"> <id name="countrycode" type="string"> <column name="country_code" length="12" /> <generator class="assigned" /> </id> <property name="countryid" type="string"> <column name="country_id" length="2" not-null="true" /> </property> <property name="countryname" type="string"> <column name="country_name" length="50" not-null="true" /> </property> </class> </hibernate-mapping> Hibernate 매핑파일은크게다섯부분으로나눠져있다. 1. Hibernate mapping DTD 정의 Hibernate mapping DTD 를정의하는부분으로 XML 파일의 validation 체크를위해서필요하다. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" " 2. <hibernate-mapping> 태그 <hibernate-mapping> 태그안에는위에서보는것처럼여러개의하위태그를정의한다. 속성 설명 필수 / 선택 기본값 schema DB schema의이름 선택 N/A catalog DB catalog의이름 선택 N/A package 매핑클래스가있는패키지이름 선택 N/A default-lazy Class, Class 내정의된 Collection 에대한기본 lazy 로딩속성 선택 true 3. 클래스와 DB 테이블매핑 17

21 Mapping File <hibernate-mapping> 하위에한개이상의 <class> 를정의할수있다. <hibernate-mapping schema=".." package= > <class name="foo" table= TBL_FOO"> </class> </hibernate-mapping> <class> 태그의 property 는다음과같다. 속성설명필수 / 선택기본값 name 매핑클래스의이름 (hibernate-mapping 태그에서 package 를정의하지않았다면클래스의패키지명도함께정의한다.) 필수 table DB 테이블명필수 N/A lazy schema true 일경우객체가필요한순간에로딩한다. DB schema 의이름 ( 상위태그에서명시를안했을경우정의할수있다.) 선택 선택 N/A <hibernate-mapping> 내의 default-lazy 속성값 <hibernate-mapping> 내의 schema 속성값 4. 식별자필드매핑 <id> 태그는 DB 의특정 Table 의 Primary Key 와매핑될 attribute 를명시한다. <id> 태그는 <generator> 태그와함께사용된다. <generator> 에대한상세내용은 Hibernate Generator 를참고한다. <class name="foo" table="tbl_foo"> <id name="id" column="id" type="int"> <generator class="assigned"/> </id> <property name="name" column="name" type="string" /> </class> Primary Key 가여러개인경우, 아래와같이 <composite-id> 태그를사용하여정의한다. <class name="foo" table="tbl_foo"> <composite-id> <key-property name="username" column="username" /> <key-property name="organizationid" column="organization_id" /> </composite-id> 중략 </class> <id> 의 property 는다음과같다. 속성설명필수 / 선택기본값 name DB 의 primary key 칼럼과매핑될 attribute 이름선택 N/A column DB 테이블의 key칼럼이름 선택 name 속 성의값 type attribute 타입 (Java 객체의 type 가아니라 Hibernate 의매핑타입 ) 선택 N/A * name 속성값이정의되어있지않은경우해당클래스는식별자를가지지않은것으로간주된다. 또한 type 속성값이정의되어있지않은경우해당클래스의식별자필드의타입을찾아, Hibernate 의타입으로매핑된다. 18

22 Mapping File 5. 일반필드매핑 <property> 태그는 DB 의일반컬럼과매핑클래스의 attribute 를명시한다. <property> 의태그를사용하여매핑정보를설정하는방법은다음과같다. <property> 는하위에 <column>, <formula>, <meta> 를가질수있으나, 여기에서는일반적으로사용되는 <column> 태그를사용해서작성하는방법에대해서만다루기로한다. <property name="countryid" type="string"> <column name="country_id" length="2" not-null="true" /> </property> <property> 태그 속성설명필수 / 선택기본값 name 매핑될 attribute 이름필수 N/A type attribute 타입 (Java 객체의 type 가아니라 Hibernate 의매핑타입 ) 선택 N/A * type 속성값이정의되어있지않은경우해당클래스의필드타입을찾아, Hibernate 의타입으로매핑된다. <column> 태그 속성설명필수 / 선택기본값 name DB 테이블의컬럼이름필수 N/A length 컴럼의값의길이선택 255 not-null 컬럼값이필수인지아닌지설정 (true or false) N/A true 3.2.Data Type 의매핑 Data Type 의매핑 Mapping File 에대한기본설정방법은위에서언급한것처럼다음과같다. <property name="countryid" type="string"> <column name="country_id" length="2" not-null="true" /> </property> 위의설정에서보면 type 은 countryid 라는자바 attribute 와 COUNTRY_ID 라는 DB 컬럼의매핑을위해설정한다. type 에설정된매핑타입을이용해자바 attribute 와 DB 컬럼사이의값을알맞게변환한다. type 에설정되는매핑타입은 Hibernate 에서기본적으로제공하는것외에개발자가커스터마이즈할수있다. Java Primitive Mapping Type 다음은 Hibernate 에서제공하는 Java primitive mapping type 이다. ( 참고 : Oracle Data Type 는 Oracle 10g 에서테이블생성시설정할 Column Type 이다.) Mapping Type Java Type Standard SQL built-in type Oracle Column Type integer int or java.lang.integer INTEGER NUMBER(10,0) long long or java.lang.long BIGINT NUMBER(19,0) short short or java.lang.short SMALLINT NUMBER(5,0) 19

23 Mapping File Mapping Type Java Type Standard SQL built-in type Oracle Column Type float float or java.lang.float FLOAT FLOAT double double or java.lang.double DOUBLE DOUBLE PRECISION big_decimal java.math.bigdecimal NUMERIC NUMBER(19,2) character char or java.lang.character CHAR(1) CHAR(1 CHAR) string java.lang.string VARCHAR VARCHAR2(255 CHAR) byte byte or java.lang.byte TINYINT NUMBER(3,0) boolean boolean or java.lang.boolean BIT NUMBER(1,0) yes_no boolean or java.lang.boolean CHAR(1) ( ture : false = Y : N ) true_false boolean or java.lang.boolean CHAR(1) ( ture : false = T : F ) CHAR(1 CHAR) CHAR(1 CHAR) 위표를참고하여자바프로퍼티와 DB 컬럼 type 에맞게설정하면된다. 다음은 Java primitive type 을테스트하기위해작성한 JavaDataType.java 파일의일부이다. public class JavaDataType { private int id; private int inttype; private long longtype; private short shorttype; private float floattype; private double doubletype; private java.math.bigdecimal bigdecimaltype; private String stringtype; private char chartype; private byte bytetype; private boolean booleantype; private boolean yesnotype; private boolean truefalsetype; 아래는 JavaDataType.java 에정의된 attribute 타입과 DB Coulmn 타입매핑설정을위해작성한 JavaDataType.hbm.xml 파일의일부이다. <property name="inttype" column="int_type" type="int"/> <property name="longtype" column="long_type" type="long"/> <property name="shorttype" column="short_type" type="short"/> <property name="floattype" column="float_type" type="float"/> <property name="doubletype" column="double_type" type="double"/> <property name="bigdecimaltype" column="bigdecimal_type" type="big_decimal"/> <property name="chartype" column="char_type" type="character"/> <property name="stringtype" column="string_type" type="string"/> <property name="bytetype" column="byte_type" type="byte"/> <property name="booleantype" column="boolean_type" type="boolean"/> <property name="yesnotype" column="yes_no_type" type="yes_no"/> <property name="truefalsetype" column="true_false_type" type="true_false"/> Java primitive type 과 DB Column type 에대한테스트코드보기 Date And Time Mapping Type 20

24 Mapping File 아래는 Hibernate 에서제공하는 date 와 time 에대한 mapping type 이다. ( 참고 :Oracle Data Type 는 Oracle 10g 에서테이블생성시설정할 Column Type 이다.) Mapping Type Java Type Standard SQL built-in type Oracle Column Type date java.util.date or java.sql.date DATE DATE time java.util.date or java.sql.time TIME DATE timestamp java.util.date or java.sql.timestamp TIMESTAMP TIMESTAMP calendar java.util.calendar TIMESTAMP TIMESTAMP calendar_date java.util.calendar TIMESTAMP DATE mapping flie 작성시위표를참고하여자바객체의 attribute 타입에맞게 mapping file 을작성하면된다. 다음은 time, data type 을테스트하기위해작성한 TimeDateType.java 파일의일부이다. public class TimeDateType { private java.sql.date datetype; private java.sql.time timetype; private java.sql.timestamp timestamptype; private java.util.calendar calendartype; private java.util.calendar calendardatetype; 위의 attribute 타입에맞게 mapping file 를설정하면된다. 다음은 TimeDataType.java 파일과 DB 테이블의 mapping 정보를설정한 TimeDateType.hbm.xml 파일의일부이다. <property name="datetype" column="date_type" type="date"/> <property name="timetype" column="time_type" type="time"/> <property name="timestamptype" column="timestamp_type" type="timestamp"/> <property name="calendartype" column="calendar_type" type="calendar"/> <property name="calendardatetype" column="calendar_date_type" type="calendar_date"/> Java Date, Time type 과 DB Column type 에대한테스트코드보기 Binary And Large Object Mapping Type Mapping Type Java Type Standard SQL built-in type Oracle Column Type binary byte[] VARBINARY BLOB( 자동생 성시 RAW) text java.lang.string CLOB CLOB clob java.sql.clob CLOB CLOB blob java.sql.blob BLOB BLOB serializable java.io.serializable VARBINARY - mapping flie 작성시위표를참고하여자바 attribute 타입에맞게 mapping file 을작성하면된다. 다음은 binary, large object type 을테스트하기위해작성한 BlobDataType.java, ClobDataType.java 의일부분이다. public class BlobDataType { private String filename; private java.math.bigdecimal filesize; private byte[] filecontentbyte; private Blob filecontentblob; 21

25 Mapping File public class ClobDataType { private String title; private String contentstring; private Clob contentclob; 위의 attribute 타입에맞게 mapping file 을설정하면된다. 다음은 BlobData.java 파일과 DB 테이블의 mapping 정보를설정한 BlobDataType.hbm.xml 과 ClobDataType.hbm.xml 파일의일부이다. <property name="filename" column="file_name" type="text"/> <property name="filesize" column="file_size" type="big_decimal"/> <property name="filecontentbyte" column="file_content_byte" type="binary" /> <property name="filecontentblob" column="file_content_blob" type="blob"/> <property name="title" column="title" type="text"/> <property name="contentstring" column="content_string" type="text"/> <property name="contentclob" column="content_clob" type="clob"/> Binary, LOB Type 과 DB Column type 매핑에대한테스트코드보기 CLOB Type 과 DB Column type 매핑에대한테스트코드보기 3.3.Hibernate Generator 앞에서설명한식별자필드매핑에이용되는 <id> 태그안의 <generator> 태그는객체저장시식별자값의생성방식을지정한다. 그렇기때문에 Mapping XML 파일작성시신규데이터를추가하기위해해당데이터의유일한 Id 를할당받기위한방법을선택해야한다. 생성방법에는 Hibernate 에서제공하는기본 Id Generator 이용하는방법과직접생성하는방법이있다 Hibernate 기본 Id Generator Hibernate 에서제공하는기본 Id Generator identity : DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL 에서제공하는 identity column 을지원하고 return 되는 identifier type 는 int, short, long 이다. native : DB 에의존하여 Hibernate 가자동으로신규 Id 를할당한다. hilo : hi/lo 알고리즘이적용된특정테이블의칼럼값을이용하여 Id 를생성한다. return 되는 identifier type 는 int, short, long 이다. increment : Hibernate 가값을 1 씩증가시켜 Id 를생성한다. guid : MS SQL 과 MySQL 에서생성한 GUID 문자열을 Id 로전달한다. sequence : Oracle, DB2, PostgreSQL, SAP DB, Mckoi 에서사용하는 Sequence 를사용하여 Id 를생성한다. 리턴되는 identifier type 는 int, short, long 이다. uuid : UUID 알고리즘을이용하여 128 bit Id 를생성한다. 생성된문자열은 32 글자의 16 진법으로인코딩되어표시된다. seqhilo : hilo 와동일하나주어진 DB 의 Sequence 로부터 hi 값을가져온다. identity identity 는 MySQL, MS SQL Server 와같이 DBMS 에서제공하는 identifier 를제공한다. identity generator 를이용하여 identifier 를생성하기위한설정을보여주는 CountryWithIdentity.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithidentity" table="country_identity" lazy="true" schema="public"> 22

26 Mapping File <id name="countrycode" column="country_code" type="int"> <generator class="identity" /> </id> 아래는 identity generator 를이용하여 COUNTRY 테이블의 primary key 인 COUNTRY_CODE 를자동생성하고테스트하는 HibernateIdGenerator.java 의일부분이다. public void addcountrywithidentitygenerator() throws Exception { CountryWithIdentity country1 = new CountryWithIdentity(); country1.setcountryid("kr"); country1.setcountryname("korea"); Integer countrycode = (Integer) session.save(country1); 위테스트케이스를실행해보면 COUNTRY_CODE 에자동으로 identifier 가생성되어저장되는것을확인할수있다. sequence Oracle 과같이 Sequence 를사용할수있는 DBMS 에서 Sequence 를사용하여 Id 를생성한다. 다음은 sequence generator 를이용하여 identifier 를생성하기위한설정파일 CountryWithSequence.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithsequence" table="country_seq" lazy="true" schema="public"> <id name="countrycode" type="int"> <column name="country_code" length="12" /> <generator class="sequence"> <param name="sequence">country_id_seq</param> </generator> </id> DBMS 의 COUNTRY_ID_SEQ 이름의 Sequence 값으로 identifier 를생성한다. 아래는 sequence generator 를이용해 DBMS 의특정 Sequence 으로 primary key column 에데이터를저장하고테스트하는 HibernateIdGenerator.java 의일부분이다. public void addcountrywithsequencegenerator() throws Exception { CountryWithSequence country1 = new CountryWithSequence(); country1.setcountryid("kr"); country1.setcountryname("korea"); Integer countrycode = (Integer) session.save(country1); 위테스트케이스를실행해보면 DBMS 에서 COUNTRY_ID_SEQ 의 Sequence 값이 COUNTRY_CODE 에입력되는것을확인할수있다. hilo hilo generator 는 hi/lo 알고리즘을사용하여 identifier 를생성한다. 다음은 hilo 를이용해 identifier 를생성하도록설정한 CountryWithHilo.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithhilo" table="country_hilo" lazy="true" schema="public"> <id name="countrycode" column="country_code" type="int"> 23

27 Mapping File <generator class="hilo"> <param name="table">id_management</param> <param name="column">next_value</param> <param name="max_lo">2</param> </generator> </id> 위 Mapping File 는 ID_MANAGEMENT 테이블의 NEXT_VALUE 컬럼에서 identifier 를얻고다음에유일한아이디를제공하기위해 NEXT_VALUE 컬럼의값에 1 을더한값을업데이트한다. max_lo 는 hilo generator 실행시생성되는신규 identifier 의개수이다. 다음은위 Mapping File 로테스트케이스를실행했을때 identifier 가생성되는 query 에대한로그이다. select NEXT_VALUE from ID_MANAGEMENT update ID_MANAGEMENT set NEXT_VALUE = 1 where NEXT_VALUE = 0 ID_MANAGEMENT 테이블에서 NEXT_VALUE 을얻어와서 identifier 를생성한다음 update 하는 query 를볼수있다. 다음은 hilo generator 를테스트하기위한 HibernateIdGenerator.java 의일부분이다. public void addcountrywithhilogenerator() throws Exception { CountryWithSeqHilo country1 = new CountryWithSeqHilo(); country1.setcountryid("kr"); country1.setcountryname("korea"); Integer countrycode1 = (Integer) session.save(country1); CountryWithSeqHilo country2 = new CountryWithSeqHilo(); country2.setcountryid("jp"); country2.setcountryname("japan"); Integer countrycode2 = (Integer) session.save(country2); CountryWithSeqHilo country3 = new CountryWithSeqHilo(); country3.setcountryid("us"); country3.setcountryname("u.s.a"); Integer countrycode3 = (Integer) session.save(country3); 위테스트코드를디버그모드로실행해보면 country2 를저장할때까지는 ID_MANAGEMENT 테이블에서 NEXT_VALUE 컬럼의값을 select 하는로그는한번만남을것이다. 그리고 country3 를저장할때다시한번 ID_MANAGEMENT 테이블에서 NEXT_VALUE 컬럼의값을 select 하는로그가남는것을확인할수있다. 이는 Mapping File 에 max_lo 값을 2 로세팅했기때문에처음 identifier 생성시 2 개를생성하기때문이다. # 참고 : table, column 을 Mapping File 에세팅하지않을경우기본 table, column 은 hibernate_unique_key, next_hi 이다. seqhilo hilo 와동일하지만 DB 의특정테이블의컬럼이아닌 DBMS 의 Sequence 로부터 hi 값을가져와 identifier 를생성한다. 아래는 seqhilo 를이용하여 identifier 를생성하기위한 CountryWithSeqHilo.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithseqhilo" table="country_seqhilo" lazy="true" schema="public"> <id name="countrycode" column="country_code" type="int"> <generator class="seqhilo"> <param name="sequence">country_id_seq</param> <param name="max_lo">2</param> 24

28 Mapping File </generator> </id> 위 Mapping File 에서는 Primary Key 인 COUNTRY_CODE 의 identifier 를생성하기위해서 DBMS 의 COUNTRY_ID_SEQ 란이름의 sequence 를이용해 identifier 를생성한다. 아래는 seqhilo generator 를이용해 identifier 를생성할때 DBMS 에서값을얻기위해실행되는 query 로그이다. call next value for COUNTRY_ID_SEQ 다음은 seqhilo generator 에대한테스트코드 HibernateIdGenerator.java 의일부분이다. public void addcountrywithseqhilogenerator() throws Exception { CountryWithSeqHilo country1 = new CountryWithSeqHilo(); country1.setcountryid("kr"); country1.setcountryname("korea"); Integer countrycode1 = (Integer) session.save(country1); CountryWithSeqHilo country2 = new CountryWithSeqHilo(); country2.setcountryid("jp"); country2.setcountryname("japan"); Integer countrycode2 = (Integer) session.save(country2); CountryWithSeqHilo country3 = new CountryWithSeqHilo(); country3.setcountryid("us"); country3.setcountryname("u.s.a"); Integer countrycode3 = (Integer) session.save(country3); 위의테스트케이스도 hilo 와마찬가지로 max_lo 를 2 로설정했기때문에 country2 를 save 할때까지 DBMS 의 sequence 를이용해 identifier 를생성하는로그가한번만남는다. 그리고 country3 를 save 할때 identifier 를생성하기위해 DBMS 에서 sequence 를얻어오는로그가남는다. increment increment generator 는매핑되는 primary key 값의최고값을얻어와서 Hibernate 가 1 을증가시킨다음에 identifier 를생성한다. 아래는 increment generator 를이용해 identifier 를생성하기위해설정한 CountryWithIncrement.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithincrement" table="country_increment" lazy="true" schema="public"> <id name="countrycode" type="int"> <column name="country_code" length="12" /> <generator class="increment" /> </id>.. 중략 increment generator 를이용하여키생성이필요할때실행되는 query 는아래와같다. select max(country_code) from COUNTRY_INCREMENT 위의 query 는 identifier 가필요할때마다생성되는것이아니라처음실행된이후메모리에서 1 씩증가하는것이기때문에분산환경에서사용할경우제대로된 identifier 를생성하지못할수도있다. 다음은 increment generator 를이용해 identifier 를생성하는테스트코드 HibernateIdGenerator.java 의일부분이다. 25

29 Mapping File public void addcountrywithincrementgenerator() throws Exception { CountryWithIncrement country1 = new CountryWithIncrement(); country1.setcountryid("kr"); country1.setcountryname("korea"); Integer countrycode1 = (Integer) session.save(country1); CountryWithIncrement country2 = new CountryWithIncrement(); country2.setcountryid("jp"); country2.setcountryname("japan"); Integer countrycode2 = (Integer) session.save(country2); CountryWithIncrement country3 = new CountryWithIncrement(); country3.setcountryid("us"); country3.setcountryname("u.s.a"); Integer countrycode3 = (Integer) session.save(country3); 위의테스트코드를실행해보면처음 DB 에서최대키값을얻어온이후다시얻어오는 query 는실행되지않는다. uuid UUID 알고리즘을사용하여 16 진법으로 32 글자의 identifier 를생성한다. 아래는 UUID 를사용해 identifier 를생성하기위해설정한 CountryWithUUID.hbm.xml 의일부분이다. <class name="anyframe.sample.model.unidirection.generator.countrywithuuid" table="country_uuid" lazy="true" schema="public"> <id name="countrycode" column="country_code" type="string"> <generator class="uuid"> <param name="separator">#</param> </generator> </id> 다음은 UUID generator 에대한테스트코드 HibernateIdGenerator.java 의일부분이다. public void addcountrywithuuidgenerator() throws Exception { CountryWithUUID country1 = new CountryWithUUID(); country1.setcountryid("kr"); country1.setcountryname(" 대한민국 "); String countrycode = (String) session.save(country1); 위의테스트코드를실행시켰을때 query 로그는다음과같다. insert into PUBLIC.COUNTRY_UUID (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', ' 대한민국 ', 'c687b6dc#1c894fc4#011c#894fc5ef#0001') Mapping File 에 separator 에대한값을 # 으로했기때문에생성되는 identifier 값에구분자로 '#' 이사용된것을확인할수있다. 26

30 Mapping File 직접생성 Hibernate 에서제공하는기본 gernerator 를이용할수도있겠지만직접키값을생성해서저장하는경우도있다. 'product-00001', 'product-00002' 과같이 identifier 를저장하고싶을때는위에서언급한 Hibernate 기본 generator 를사용할수없다. assigned <generator> 의 class 속성값을 assigned 로정의한경우객체에저장된값을그대로이용하게된다. 사용자가정의한별도 Id Generator 가있는경우 class 속성값에해당클래스를정의할수있다. 다음은 assigned 하기위해 Mappping File 에설정한샘플소스이다. <id name="categoryno" type="string"> <column name="category_no" length="16" /> <generator class="assigned" /> </id> generator 를 assigned 로설정했다면객체를저장하기전에 categoryno 에값을세팅해야한다. 다음은 Anyframe 의기술공통서비스인 IdGenerationService 를이용해 identifier 을얻어서객체에세팅하고저장하는샘플소스이다. category.setcategoryno(idgenerationservice.getnextstringid()); session.save(category); assigned generator 는일반적으로가장많이이용하는형태로 Anyframe 의 IdGenerationService 과함께사용시유용하다. 27

31 4.Persistence Mapping Hibernate 을이용하여영속성을가지는 Persistence 객체를특정테이블과매핑하는 Object Relational Mapping 작업이필요하다. 이페이지에서는하나의객체를하나의테이블로매핑하기위해필요한사항들에대해서는언급하지않으며, Association 과 Inheritance 관계에놓여있는객체사이의관계를테이블로매핑하는방법에대해살펴보도록할것이다. (* 참고. 하나의객체를하나의테이블로매핑하기위해필요한사항들에대해서는 Hibernate 하위메뉴인 Mapping XML File 를참고하도록한다.) 4.1.Persistence Mapping - Association 본페이지에서는두클래스사이의 Association 유형별매핑방법에대해자세히살펴보도록하자. 특히, 객체모델링에서가장많이사용될 One to Many Mapping 에서는다양한 Collection 매핑방법및 Collection 의주요속성인 inverse, cascade 에대해샘플코드를중심으로분석해볼것이다 One to One Mapping A:B = 1:1 관계에놓여있는두클래스사이의관계를매핑하는방법은여러가지가있는데그중의하나가동일한 Primary Key 를기반으로클래스사이의참조관계를매핑하는것이다. 왼쪽그림은클래스다이어그램으로 Foo : Bar = 1:1 이며, 단방향참조관계를표현하고있다. 이것은오른쪽그림상단의 ERD 와같이각각 TBL_FOO 와 TBL_BAR 로매핑될수있으며, 별도추가컬럼을필요로하지는않으면서동일한 Primary Key 를사용하고있음을알수있다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림하단의내용과같다. 그림내용에대해설명하자면, Foo, Bar 각각의클래스및속성정보를 class 태그를이용하여정의하고, 두클래스간참조관계에대해서는참조하는측에서 one-to-one 태그를이용하여참조관계에놓인클래스와테이블을명시하고있다 One to Many Mapping A:B = 1:m 관계에놓여있는두클래스사이의관계를매핑할때객체 B 는기본적으로 Collection 의형태이다. One to Many Mapping 에서는샘플을기반으로 Hibernate Mapping XML 파일정의방법에대해살펴본후, Hibernate 에서지원하는다양한 Collection 유형과 Collection 의중요한속성중의하나인 inverse 와 cascade 에대해알아보도록한다. 28

32 Persistence Mapping 왼쪽그림은클래스다이어그램으로 Foo : Bar = 1:m 이며, 단방향참조관계를표현하고있다. 이것은오른쪽그림상단의 ERD 와같이각각 TBL_FOO, TBL_BAR 로매핑될수있으며, TBL_BAR 테이블은 TBL_FOO 테이블에대한 Foreign Key 가필요하다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림하단의내용과같다. 그림내용에대해설명하자면, Foo, Bar 각각의클래스및속성정보를 class 태그를이용하여정의하고, A 측에서 B 클래스에대해 set 태그를이용하여 Collection 형태를표현한다. 또한 set 태그내에서는 one-to-many 태그를이용하여두객체사이의관계를명시하면서, key 태그를통해 Foreign Key 컬럼을명시하고있다. 1:m 단방향관계에대한 Hibernate Mapping XML 정의방법은 Country : Movie = 1:m 단방향관계를표현한 Country.hbm.xml 과 Movie.hbm.xml 를참고하도록한다. Hibernate Mapping XML 파일내의 B 측에다음과같이매핑정보를추가할경우양방향참조도가능해진다. <class name="bar" table="tbl_bar"> <many-to-one name="tbl_foo" class="foo" column="foo_id"/> </class> 1:m 양방향관계에대한 Hibernate Mapping XML 정의방법은 Country : Movie = 1:m 양방향관계를표현한 Country. hbm.xml 과 Movie.hbm.xml 를참고하도록한다 Collection Mapping 앞서언급한것처럼, 1:m 관계에놓여있는두클래스사이의관계를매핑할때객체 B 는기본적으로 Collection 의형태이며, Hibernate 에서지원하는 Collection 타입은 set 외에도다음과같이여러가지가있다. set : java.util.set 타입으로 <set> 을이용하여정의한다. 객체의저장순서를알수없으며, 동일객체의중복저장을허용하지않는다. (HashSet 이용 ) 다음은 set 태그를이용하여 Collection 객체를정의한 Hibernate Mapping XML 과소스코드의예이다. 1. Hibernate Mapping XML <class name="anyframe.sample.model.unidirection.relation.collection.countrywithset" table="country_set" lazy="true" schema="public"> <set name="movies" inverse="true" cascade="save-update"> <key> <column name="country_code" length="12" /> </key> <one-to-many class="anyframe.sample.model.bidirection.movie" /> </set> 29

33 Persistence Mapping </class> 2. CountryWithSet.java public class CountryWithSet implements java.io.serializable { private String countrycode; private String countryid; private String countryname; private Set movies = new HashSet(0); list : java.util.list 타입으로 <list> 를이용하여정의한다. List 타입의경우저장된객체의순서를알수있으며, 저장순서를테이블에보관하기위해서별도인덱스컬럼정의가필요하다. 객체저장순서를저장할별도컬럼은 <list> 하위에 <list-index> 를이용하면된다. (ArrayList 이용 ) 다음은 list 태그를이용하여 Collection 객체를정의한 Hibernate Mapping XML 과소스코드의예이다. 1. Hibernate Mapping XML <class name="anyframe.sample.model.unidirection.relation.collection.countrywithlist" table="country_list" lazy="true" schema="public"> <list name="movies" cascade="save-update"> <key> <column name="country_code" length="12" /> </key> <list-index column="movie_idx"/> <one-to-many class="anyframe.sample.model.unidirection.movie" /> </list> </class> 2. CountryWithList.java public class CountryWithList implements java.io.serializable { private String countrycode; private String countryid; private String countryname; private List movies = new ArrayList(0); bag : java.util.collection 타입인경우 <bag> 또는 <idbag> 을이용하여정의한다. 객체의저장순서를알수없으나, 동일객체의중복저장은허용한다. 내부적으로 List 를사용하나인덱스값을사용하지는않는다. (ArrayList 이용 ) 또한 Bag 은 Set 과비슷하나모든 Collection 를로드하지않고도해당 Collection 에신규객체를추가할수있으므로성능면에서유리하다. 다음은 <bag> 을이용하여 Collection 객체를정의한 Hibernate Mapping XML 과소스코드의예이다. 1. Hibernate Mapping XML <class name="anyframe.sample.model.unidirection.relation.collection.countrywithbag" table="country_bag" lazy="true" schema="public"> <bag name="movies" inverse="true" cascade="save-update"> <key> <column name="country_code" length="12" /> 30

34 Persistence Mapping </key> <one-to-many class="anyframe.sample.model.unidirection.movie" /> </bag> </class> 2. CountryWithBag.java public class CountryWithBag implements java.io.serializable { private String countrycode; private String countryid; private String countryname; private Collection movies = new ArrayList(0); 다음은 <idbag> 을이용하여 Collection 객체를정의한 Hibernate Mapping XML 과소스코드의예이다. idbag 은 bag 과는달리순서가보장되며, One to Many 관계에서다른 Collection 매핑방법과는다르게 composite-element 태그를이용한 value type 으로정의해야한다. 1. Hibernate Mapping XML <class name="anyframe.sample.model.unidirection.relation.collection.countrywithidbag" table="country_idbag" lazy="true" schema="public"> <idbag name="movies" table="movie"> <collection-id column="id" type="java.lang.string"> <generator class="uuid"/> </collection-id> <key column="country_code" /> <composite-element class="anyframe.sample.model.unidirection.movie"> <property name="title" type="string"> <column name="title" length="100" not-null="true" /> </property> <property name="director" type="string"> <column name="director" length="10" not-null="true" /> </property> <property name="releasedate" type="date"> <column name="release_date" length="0" /> </property> </composite-element> </idbag> </class> 2. CountryWithIdBag.java public class CountryWithIdBag implements java.io.serializable { private String countrycode; private String countryid; private String countryname; private Collection movies = new ArrayList(0); map : java.util.map 타입으로 <map> 을이용하여 ( 키, 값 ) 을쌍으로정의한다. (HashMap 이용 ) 다음은 <map> 을이용하여 Collection 객체를정의한 Hibernate Mapping XML 과소스코드의예이다. 1. Hibernate Mapping XML 31

35 Persistence Mapping <class name="anyframe.sample.model.unidirection.relation.collection.countrywithmap" table="country_map" lazy="true" schema="public"> <map name="movies" cascade="save-update"> <key> <column name="country_code" length="12" /> </key> <map-key column="movie_map_key" type="string"/> <one-to-many class="anyframe.sample.model.unidirection.movie" /> </map> </class> 2. CountryWithMap.java public class CountryWithMap implements java.io.serializable { private String countrycode; private String countryid; private String countryname; private Map movies = new HashMap(0); StoredSet, StoredMap : <set>, <map> 을그대로이용하되, sort 라는 attribute 를이용하여정렬방식을정의한다. (TreeSet, TreeMap 이용 ) HibernateCollectionMapping.java 코드를통해위에서언급한각종유형별 Collection 에대한사용방법및차이점을직접확인할수있을것이다 Inverse, Cascade 속성 inverse 와 cascade 는 Collection 정의시중요한의미를가지는속성중의하나로, 다음과같은의미를지닌다. inverse : 객체간관계의책임을어디에둘지에대한옵션을정의하기위한속성이다. 즉, 한쪽은 owner 의역할을맡기고, 다른한쪽에는 sub 의역할을맡기기위함이다. cascade : 부모객체에대한 CUD 를자식객체에도전이할지에대한옵션을정의하기위한속성이다. 이제부터 inverse, cascade 속성정의에따라실행되는쿼리문이어떻게달라지는지를살펴봄으로써, inverse 와 cascade 속성에대해자세히알아보도록하자. 단방향 1:m 관계 1. inverse="false", cascade="false" public void addcountrymoviewithoutinversecascade() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/unidirection/" + "hibernate-without-inversecascade.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie /* #1 */ country.getmovies().add(movie); // 3. try to insert a country, movie /* #2 */ session.save(country); /* #3 */ session.save(movie); 32

36 Persistence Mapping closesession(); addcountrymoviewithoutinversecascade() 메소드실행결과 #2,#3 번코드에의해신규 Country 정보와 Movie 정보를등록하기위한 INSERT 문이실행된다. 그리고, Country 측에 Movie Collection 에대한 inverse 속성값을 false 로설정하였으므로, #1 번코드에의해 Country 와 Movie 관계정보셋팅을수행하기위한 UPDATE 문이한번더실행된다. 즉, 다음과같이 3 개의쿼리문이수행된다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') update PUBLIC.MOVIE set COUNTRY_CODE='COUNTRY-0001' where MOVIE_ID='MV-00001' 2. inverse="true", cascade="false" public void addcountrymoviewithoutcascade() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/unidirection/" + "hibernate-without-cascade.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie country.getmovies().add(movie); // no effect code!! // 3. try to insert a country, movie /* #1 */ session.save(country); /* #3 */ // movie.setcountrycode(country.getcountrycode()); /* #2 */ session.save(movie); closesession(); addcountrymoviewithoutcascade() 메소드실행결과 #1,#2 번코드에의해신규 Country 정보와 Movie 정보를등록하기위한 INSERT 문이실행된다. 또한 inverse="true" 인경우 Move 측에서관련된 Country 정보와의 Relation 정보셋팅을해야하나 Country -> Movie 인단방향관계이므로이것도가능하지않다. 따라서 Country 와 Movie 사이의 Relation 정보누락이발생할수있다. 이러한경우에서는 #3 번코드에서와같이 Movie Mapping File 내에 COUNTRY_CODE 컬럼을위한별도속성정보를정의하고, Movie 등록시에 countrycode 를직접셋팅해줌으로써두객체사이의관계를유지시킬수있도록해야할것이다. 다음은 addcountrymoviewithoutcascade() 메소드실행결과수행되는쿼리문이다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) 33

37 Persistence Mapping values ('My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') 3. inverse="false", cascade="true" public void addcountrymoviewithoutinverse() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/unidirection/" + "hibernate-without-inverse.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie /* #2 */ country.getmovies().add(movie); // 3. try to insert a country /* #1 */ session.save(country); closesession(); addcountrymoviewithoutinverse() 메소드실행결과 #1 번코드와 cascade 속성값에의해신규 Country 정보와함께 Movie 정보가함께 INSERT 된다. 그리고, Country 측에 Movie Collection 에대한 inverse 속성값을 false 로설정하였으므로, #2 번코드에의해 Country 와 Movie 관계정보셋팅을수행하기위한 UPDATE 문이한번더실행된다. 즉, 다음과같이 3 개의쿼리문이수행된다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') update PUBLIC.MOVIE set COUNTRY_CODE='COUNTRY-0001' where MOVIE_ID='MV-00001' 4. inverse="true", cascade="true" public void addcountrymovie() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/unidirection/hibernate.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie country.getmovies().add(movie); // no effect code!! // 4. try to insert a country /* #2 */ // movie.setcountrycode(country.getcountrycode()); /* #1 */session.save(country); closesession(); 34

38 Persistence Mapping addcountrymovie() 메소드실행결과 #1 번코드와 cascade 속성값에의해신규 Country 정보와함께 Movie 정보가함께 INSERT 된다. 또한 inverse="true" 인경우 Move 측에서관련된 Country 정보와의 Relation 정보셋팅을해야하나 Country -> Movie 인단방향관계이므로이것도가능하지않다. 따라서 Country 와 Movie 사이의 Relation 정보누락이발생할수있다. 이러한경우에서는 #2 번코드에서와같이 Movie Mapping File 내에 COUNTRY_CODE 컬럼을위한별도속성정보를정의하고, Movie 등록시에 countrycode 를직접셋팅해줌으로써두객체사이의관계를유지시킬수있도록해야할것이다. 다음은 addcountrymovie() 메소드실행결과수행되는쿼리문이다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') 표에서언급한코드들을포함한전체테스트코드는 HibernateUnidirectionInverseCascade.java 를참고하도록한다. 양방향 1:m 관계 1. inverse="false", cascade="false" public void addcountrymoviewithoutinversecascade() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/bidirection/ hibernate-without-inversecascade.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie /* #3 */ country.getmovies().add(movie); // 3. try to insert a country, movie /* #1 */ session.save(country); /* #2 */ session.save(movie); closesession(); addcountrymoviewithoutinversecascade() 메소드실행결과 #1,#2 번코드에의해신규 Country 정보와 Movie 정보를등록하기위한 INSERT 문이실행된다. 그리고, Country 측에 Movie Collection 에대한 inverse 속성값을 false 로설정하였으므로, #3 번코드에의해 MOVIE 테이블의 COUNTRY_CODE 정보를 null 에서 'COUNTRY-0001' 로셋팅하기위한 UPDATE 쿼리가추가적으로실행된다. 즉, 다음과같이 3 개의쿼리문이수행된다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values (null, 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') update PUBLIC.MOVIE set COUNTRY_CODE='COUNTRY-0001' where MOVIE_ID='MV-00001' 2. inverse="true", cascade="false" public void addcountrymoviewithoutcascade() throws Exception { 35

39 Persistence Mapping // 1. make init data newsession( "anyframe/core/hibernate/inverse/bidirection/hibernate-without-cascade. cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between movie and country /* #4 */ // country.getmovies().add(movie); /* #3 */ movie.setcountry(country); // 3. try to insert a country, movie /* #1 */ session.save(country); /* #2 */ session.save(movie); closesession(); addcountrymoviewithoutcascade() 메소드실행결과 #1,#2 번코드에의해신규 Country 정보와 Movie 정보를등록하기위한 INSERT 문이실행된다. 그리고 inverse="true" 이고 Country <-> Movie 인양방향관계이므로, #3 번코드실행을통해 Movie INSERT 시점에 Country 와 Movie 의 Relation 을표현하는 CountryCode 정보가셋팅된다. 또한 cascade="false" 이므로 #4 번코드는불필요하다. 위의코드에서는단방향관계에서와달리 Movie INSERT 시점에이미 Country 와 Movie Relation 정보가셋팅되므로, Relation 정보누락이발생하지않는다. 또한 inverse="false" 인경우와달리별도 Relation 정보셋팅을위한별도 UPDATE 문실행을필요로하지않아성능면에서유리하다. 다음은 addcountrymoviewithoutcascade() 메소드실행결과수행되는쿼리문이다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001' insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) ('COUNTRY-0001', 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') 3. inverse="false", cascade="true" public void addcountrymoviewithoutinverse() throws Exception { // 1. make init data newsession( "anyframe/core/hibernate/inverse/bidirection/hibernate-withoutinverse.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie /* #2 */ country.getmovies().add(movie); /* #3 */ // movie.setcountry(country); // no effect code!! // 3. try to insert a country /* #1 */ session.save(country); closesession(); addcountrymoviewithoutinverse() 메소드실행결과 #1 번코드와 cascade 속성값에의해신규 Country 정보와함께 Movie 정보가함께 INSERT 된다. 그리고, Country 측에 Movie Collection 에대한 inverse 속성값을 false 로설정하였으므로, #2 번코드에의해 Country 와 Movie 관계정보셋팅 36

40 Persistence Mapping 을수행하기위한 UPDATE 문이한번더실행된다. 여기서 Relation 관계셋팅을위해 #2 번코드가영향을미치므로 #3 번코드는불필요하다. 즉, 다음과같이 3 개의쿼리문이수행된다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values (null, 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') update PUBLIC.MOVIE set COUNTRY_CODE='COUNTRY-0001' where MOVIE_ID='MV-00001' 4. inverse="true", cascade="true" public void addcountrymovie() throws Exception { // 1. make init data newsession("anyframe/core/hibernate/inverse/bidirection/ hibernate.cfg.xml"); Country country = makecountry(); Movie movie = makemovie(); // 2. try to make a relation between country and movie /* #2 */ country.getmovies().add(movie); // 3. try to make a relation between movie and country /* #3 */ movie.setcountry(country); // 4. try to insert a country /* #1 */ session.save(country); closesession(); addcountrymovie() 메소드실행결과 #1,#2 번코드와 cascade 속성값에의해신규 Country 정보와함께 Movie 정보가함께 INSERT 된다. 그리고 inverse="true" 이고 Country <-> Movie 인양방향관계이므로, #3 번코드실행을통해 Movie INSERT 시점에 Country 와 Movie 의 Relation 을표현하는 CountryCode 정보가셋팅된다. 위의코드에서는단방향관계에서와달리 Movie INSERT 시점에이미 Country 와 Movie Relation 정보가셋팅되므로, Relation 정보누락이발생하지않는다. 또한 inverse="false" 인경우와달리별도 Relation 정보셋팅을위한별도 UPDATE 문실행을필요로하지않아성능면에서유리하다. 다음은 addcountrymovie() 메소드실행결과수행되는쿼리문이다. insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('COUNTRY-0001', 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') 표에서언급한코드들을포함한전체테스트코드는 HibernateBidirectionInverseCascade.java 를참고하도록한다. 37

41 Persistence Mapping Many to Many Mapping 두클래스사이의관계가 m:n 일경우각각의 Foreign Key 를가진 Association 테이블을정의함으로써매핑한다. 왼쪽그림은클래스다이어그램으로 User : Role = m:n 이며, 단방향참조관계를표현하고있다. 이것은오른쪽그림상단의 ERD 와같이각각 TBL_USER, TBL_ROLE 로매핑될수있으며, 각테이블의 Primary Key 를 Foreign Key 로가지는 Association 테이블인 TBL_USER_ROLE 이필요하다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림하단의내용과같다. 그림내용에대해설명하자면, User, Role 각각의클래스및속성정보를 class 태그를이용하여정의하고, User 측에서 Role 클래스에대해 set 태그를이용하여 Collection 형태를표현하고연관된테이블로는 Association 테이블인 TBL_USER_ROLE 로정의한다. 또한 set 태그내에서는 many-to-many 태그를이용하여두객체사이의관계를명시하면서, key 태그를통해 Foreign Key 컬럼을명시하고있다. 단방향 m:n 관계에대한 Hibernate Mapping XML 정의방법은 Category : Movie = m:n 양방향관계를표현한 Category.hbm.xml 과 Movie.hbm.xml 를참고하도록한다. 양방향의 m-n 관계설정을위해서는양쪽모두 <class> 에 <manyto-many> 를사용하되, 반드시 Relation 의책임을지는한쪽에는 "inverse=true" 를지정하여매핑관리를한쪽에서처리할수있도록하는것이좋다. 양방향 m:n 관계에대한 Hibernate Mapping XML 정의방법은 Category : Movie = m:n 양방향관계를표현한 Category.hbm.xml 과 Movie.hbm.xml 를참고하도록한다. 4.2.Persistence Mapping - Inheritance 본페이지에서는상속관계에참여하는각클래스에대한여러매핑방법에대해자세히살펴보도록하자 Table per Class Hierarchy 상속관계에참여하는모든 Parent, Child 클래스들을모두한개의테이블로매핑하고, Child 클래스의유형을구분하기위해별도 Discriminator 칼럼을추가로정의하는매핑방법이다. 38

42 Persistence Mapping 왼쪽상단그림은클래스다이어그램으로 User 클래스를상속받은 Guest, Member, Staff 클래스들이존재한다. 그리고왼쪽하단그림은 ERD 로 User, Guest, Member, Staff 클래스를 TBL_USER 라는하나의테이블로매핑하고있다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림의내용과같다. 그림내용에대해설명하자면, User 클래스정보를 class 태그를이용하여정의하고, 하위에 discriminator 태그를이용하여 Child 클래스의유형을구분하기위해별도로필요한 Discriminator 칼럼이추가정의되어야한다. 또한하위에 subclass 태그를이용하여 User 클래스를상속하는하위클래스와속성들에대해정의하는데이때각 subclass 에대한 Discriminator 값정의가필요하다. Table per Class Hierarchy 매핑의장, 단점에대해살펴보면다음과같다. [ 장점 ] 별도 Join 처리가필요하지않아쿼리문작성이용이 상속관계제어를위한 overhead 가최소화 [ 단점 ] 특정테이블을기준으로 NOT NULL constraints 를정의할수없음 하위클래스가추가될테이블구조변경불가피 관리대상이되는칼럼과 NULL 값을가진칼럼들의개수증가 해당 Domain 의성격과무관하게하위클래스의타입을구분하기위한별도칼럼정의필요 별도 Discriminator 칼럼을만들지않고자하는경우에는다음과같이 formula 라는속성을이용할수있다. 특정칼럼의값에대한연산을통해 Discriminator 값을정의하는경우로아래의예에서는 DEPT_ID 의값이 NOT NULL 인경우 Discriminator 값은 'STAFF' 이므로해당되는객체는 Staff 가될것이다. <discriminator formula="case WHEN DEPT_ID IS NOT NULL THEN 'STAFF' " type="string"/> Table per Subclass 상속관계에참여하는모든 Parent, Child 클래스들을각각의테이블로매핑시키되, 모든하위테이블들이상위클래스와동일한 Primary Key 를공유하는형태이다. 39

43 Persistence Mapping 왼쪽상단그림은클래스다이어그램으로 User 클래스를상속받은 Guest, Member, Staff 클래스들이존재한다. 그리고왼쪽하단그림은 ERD 로상속관계에참여하는모든클래스를 TBL_USER, TBL_GUEST, TBL_MEMBER, TBL_STAFF 라는테이블로매핑하고있다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림의내용과같다. 그림내용에대해설명하자면, User 클래스정보를 class 태그를이용하여정의하고, 하위에 joined-subclass 태그를이용하여 User 클래스를상속하는하위클래스와속성들에대해정의하고있다. Table per Subclass 매핑의장, 단점에대해살펴보면다음과같다. [ 장점 ] 객체지향에가장근접한 Mapping 이고하위클래스가많은속성정보를가진경우가장자연스러운 Mapping 기법 특정테이블을기준으로 NOT NULL Constraints 지정가능 Hibernate 을사용할경우, 하위클래스유형을구분하기위한별도 Discriminator 칼럼불필요 [ 단점 ] 테이블조회시각테이블간의 Join 이필요하여계층관계가복잡할수록성능이슈유발가능 Hibernate 을이용하지않고외부에서직접데이터가추가될경우데이터의정합성이깨질우려가있음 조회하고자하는특정 Child 클래스를명시하지않고 Parent 클래스를통해조회를요청할경우 ( 즉, Parent 클래스를이용하여 Query 를수행시키는경우 ), Hibernate 은실제조회대상클래스를알수없어해당클래스의유형을찾기위해상속관계에참여하는모든테이블들에대해 Outer JOIN 이수행되므로성능저하를유발할수있음에유의해야한다. (* 특정 Child 클래스를조회대상으로명시하였을경우에는 Inner JOIN 이수행된다.) Table per Concrete Class 상속관계에참여하는모든 Concrete 클래스들을각각한개의테이블로매핑하는방법으로, 매핑되는모든테이블에상위클래스의속성정보가반복정의되어야한다. Parent 클래스가추상클래스일경우별도테이블정의는필요하지않으며, abstract 를 true 로정의해야한다. 40

44 Persistence Mapping 왼쪽상단그림은클래스다이어그램으로 User 클래스를상속받은 Guest, Member, Staff 클래스들이존재한다. 그리고왼쪽하단그림은 ERD 로 TBL_GUEST, TBL_MEMBER, TBL_STAFF 라는테이블로매핑하고있다. 이와같은매핑관계를 Hibernate Mapping XML 파일에정의하는방법은오른쪽그림의내용과같다. 그림내용에대해설명하자면, User 클래스정보를 class 태그를이용하여정의하고 User 클래스의 abstract 속성을 true 로정의하고있다. 또한하위에 union-subclass 태그를이용하여각하위클래스들과속성들에대해정의하고있다. Table per Concrete Class 매핑의장, 단점에대해살펴보면다음과같다. [ 장점 ] 특정테이블을기준으로 NOT NULL Constraints 지정가능 Polymorphic Query 가필요하지않은경우에사용시유용함 (* Polymorphic Query : 조회대상이되는특정클래스 / 인터페이스를 extends 또는 implements 하는모든클래스에대해조회 ) [ 단점 ] 데이터조회시 UNION 을이용해야하나, UNION 은모든 DB 에서지원되는것은아니므로유의 상위클래스가가진공통정보가각테이블에중복됨 Hibernate 을이용하지않고외부에서직접데이터가추가될경우데이터의정합성이깨질우려가있음 41

45 5.Basic CRUD Hibernate 에서제공하는기본 API 를호출함으로써, Persistence 객체를이용하여특정 DB 에데이터를입력, 수정, 삭제, 조회하는방법에대해알아보도록한다 단건조회 get() 또는 load() 메소드를호출하여 DB 로부터단건의데이터를조회할수있다. get() 또는 load() 메소드호출시대상이되는 Persistence 클래스와 Primary Key 값에해당하는속성값을입력인자로전달해야한다. get(): 호출시점에 SELECT 쿼리실행 load(): 객체의값이실제로필요한시점에쿼리실행 Persistence 클래스인 Country 에대한매핑정보가다음과같이정의되어있다라고가정해보자. <class name="anyframe.sample.model.bidirection.country" table="country" lazy="true" schema="public"> <id name="countrycode"type="string"> <column name="country_code" length="12" /> <generator class="assigned" /> </id>... </class> Country 의식별자인 countrycode 의값을이용하여단건 Country 정보를조회하고자할경우에는 HibernateBasicCRUD 의 countryinfo(...) 메소드에서와같이호출하면된다. private void countryinfo(string countrycode, Country country) throws Exception { Country result = (Country) session.get(country.class, countrycode); load() 메소드의경우 SELECT 쿼리를실행하지않고, 전달된식별자에해당하는객체의 Proxy 를리턴한후, 해당객체를통해테이블에저장된식별자이외의값접근시 SELECT 문을실행하여결과값을 Proxy 객체에저장한다. 다음과같이 load() 메소드수행결과전달된객체의클래스명을출력해보면, Proxy 객체가전달되었음을알수있을것이다. User user = session.load(user.class, "test"); // expected to print : com.sds.emp User$$EnhancerByCGLIB$$... System.out.println(user.getClass().getName()); 5.2. 단건저장 save() 또는 persist() 메소드를호출하여 DB 에단건의데이터를추가할수있다. save() 또는 persist() 메소드호출시대상이되는 Persistence 객체를입력인자로전달해야한다. save() : 단건의데이터를추가한후, 해당객체의식별자를 return persist() : 단건의데이터추가. return 값이없음 신규 Country 정보를추가하고자할경우에는 HibernateBasicCRUD 의 addcountry() 메소드에서와같이호출하면된다. private Country addcountry() throws Exception { 42

46 Basic CRUD // 1. insert a new country information Country country = new Country(); String countrycode = "COUNTRY-0001"; country.setcountrycode(countrycode); country.setcountryid("kr"); country.setcountryname("korea"); session.save(country); Tip. A:B=1:m 인경우 A 에대한 save() A 객체에서 Collection B 에대한 cascade 속성을 true 로정의하고, Collection B 를포함한해당객체 A 에대해 save() 메소드를호출하는경우를가정해보자. 상위객체인 A 에대해서는예상하는바와동일하게동작하나, Collection B 에대해서는 saveorupdate() 와동일하게동작함을알수있다. 이를확인하기위해서 Country:Movie = 1:m 관계에대한 HibernateSaveOrUpdateParentChild 의각테스트메소드실행결과를중심으로확인해보도록하자. 1. DB 에추가되어있지않은 Country 정보에대해 save() 메소드호출하는경우 Transaction Commit 시신규생성한 Country 객체에대해 INSERT 문이실행된다. public void addcountrycallingsave() throws Exception { // 1. try to insert a country information without movies newsession(); Country country1 = makenewcountry(); session.save(country1); closesession(); * 콘솔 - 실행된 SQL 문 insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001' 2. DB 에추가되어있지않은 Country 정보에대해 saveorupdate() 메소드를호출하는경우 신규생성한 Country 객체가 DB 에존재하지않으므로 Transaction Commit 시해당객체에대해 INSERT 문이실행된다. public void addcountrycallingsaveorupdate() throws Exception { // 1. try to insert a country information without movies newsession(); Country country1 = makenewcountry(); session.saveorupdate(country1); closesession(); * 콘솔 - 실행된 SQL 문 insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001') 43

47 Basic CRUD 3. DB 에추가되어있지않은 Movie 정보를포함한 Country 에대해 update() 메소드를호출하였을경우 첫번째 Transaction 에서신규 Country 정보를추가하였고, 두번째 Transaction 에서앞서등록한 Country 객체에신규 Movie Collection 정보를셋팅한후 update() 메소드를호출한경우이다. 두번째 Transaction Commit 시 Country 객체에대해서는변경정보가있다면 UPDATE 문이실행되고, 신규 Movie Collection 정보에대해서는 INSERT 문이실행된다. public void addmoviescallingupdate() throws Exception { // 1. try to insert a country information without movies newsession(); Country country1 = makenewcountry(); session.save(country1); closesession(); // 2. try to insert a country information with movies. newsession(); Country country2 = makenewmovieset(country1.getcountrycode()); session.update(country2); closesession(); * 콘솔 - 실행된 SQL 문 // 첫번째 Transaction insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001')... // 두번째 Transaction insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('COUNTRY-0001', 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('COUNTRY-0001', 'My Little Bride', 'Hojun Kim', , 'MV-00002') DB 에추가되어있지않은 Country 정보를추가한후, Movie 정보에대해 save() 메소드를호출하였을경우 첫번째 Transaction 에서신규 Country 정보를추가하였고, 두번째 Transaction 에서앞서등록한 Country 객체에신규 Movie Collection 정보를셋팅한후 save() 메소드를호출한경우이다. 3 번의경우와동일하게동작한다. public void addmoviescallingsave() throws Exception { // 1. try to insert a country information without movies newsession(); Country country1 = makenewcountry(); session.save(country1); closesession(); // 2. try to insert a country information with movies. newsession(); Country country2 = makenewmovieset(country1.getcountrycode()); session.save(country2); closesession(); 44

48 Basic CRUD * 콘솔 - 실행된 SQL 문 // 첫번째 Transaction insert into PUBLIC.COUNTRY (COUNTRY_ID, COUNTRY_NAME, COUNTRY_CODE) values ('KR', 'Korea', 'COUNTRY-0001')... // 두번째 Transaction insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('COUNTRY-0001', 'My Sassy Girl', 'Jaeyong Gwak', , 'MV-00001') insert into PUBLIC.MOVIE (COUNTRY_CODE, TITLE, DIRECTOR, RELEASE_DATE, MOVIE_ID) values ('COUNTRY-0001', 'My Little Bride', 'Hojun Kim', , 'MV-00002') 단건수정 update() 메소드를호출하여 DB 의단건데이터를수정할수있다. update() 메소드호출시대상이되는 Persistence 객체를입력인자로전달해야한다. 입력인자로전달된객체에는모든값이설정되어있어야함에유의하도록한다. 속성값이설정되어있지않은경우해당속성값이 null 로저장된다. 기등록된 Country 정보를수정하고자할경우에는 HibernateBasicCRUD 의 updatecountry() 메소드에서와같이호출하면된다. public void updatecountry() throws Exception { // 1. insert a new country information Country country = addcountry(); // 2. update a country information country.setcountryname("republic of Korea"); session.update(country);... 특정객체가 Persistent 상태이고, 동일한 Session 내에서해당객체의속성값에변경이발생한경우 update() 메소드를직접적으로호출하지않아도트랜잭션종료시점에 Hibernate 에의해변경여부가체크되어변경사항이 DB 에반영된다. public void updatecountry() throws Exception { // start transaction Country country = addcountry(); country.setcountryname("republic of Korea"); // commit. successful update!!! 5.4. 단건저장또는수정 기등록된객체에대해 save() 메소드를호출한경우또는 DB 에존재하지않는객체에대해 update() 메소드를호출한경우 addcountrycallingupdate() 메소드에서처럼 Exception 이발생한다. 45

49 Basic CRUD public void addcountrycallingupdate() throws Exception { // 1. start a new session and transaction newsession(); // 2. try to insert a country information without movies Country country1 = makenewcountry(); session.update(country1); // 3. close session try { closesession(); fail("expected throw HibernateException"); catch (Exception e) {... 두메소드 (save(), update()) 의특징을포함한 saveorupdate() 메소드는해당객체가존재하는경우에는 update() 와같은역할을수행하고존재하지않을경우에는 save() 를수행한다. saveorupdate() 메소드호출시대상이되는 Persistence 객체를입력인자로전달해야한다. saveorupdate() 메소드는 HibernateSaveOrUpdateParentChild 의 addcountrycallingsaveorupdate() 메소드에서와같이호출하면된다. public void addcountrycallingsaveorupdate() throws Exception { // 1. try to insert a country information without movies newsession(); Country country1 = makenewcountry(); session.saveorupdate(country1); closesession(); 5.5. 단건삭제 delete() 메소드를호출하여 DB 의단건데이터를삭제할수있다. delete() 메소드호출시식별자값을포함하고있는 Persistence 객체를입력인자로전달해야한다. 기등록된 Country 정보를삭제하고자할경우에는 HibernateBasicCRUD 의 deletecountry() 메소드에서와같이호출하면된다. public void deletecountry() throws Exception { // 1. insert a new country information Country country = addcountry(); // 2. delete a country information session.delete(country); 5.6. 복수건저장 하나의트랜잭션내에서동일한 Persistence 클래스에대해복수건의데이터저장또는수정이발생할경우에는 loop 을수행하면서 save(), update() 메소드를호출해주도록한다. 단, 이때 1st Level Cache, 2nd Level Cache 에 Persistent 상태의객체들이 Caching 되면서 memory overflow 가발생할수있으므로로직구성에주의가필요하다. 46

50 Basic CRUD 2nd Level Cache Mode : 해당메소드수행시에는 2LC 를적용하지않도록 Cache Mode 를 IGNORE 로설정. Session Flush : memory size 를고려하여적절한수의 Persistence 객체에대한 save() 가이루어진후에 session.flush() 메소드를호출하여 DB 에반영할수있도록한다. 한번에 flush 할객체의수는 hibernate configuration file (hibernate.cfg.xml) 내에정의한 hibernate.jdbc.batch_size 와동일하게맞추는것이좋다. hibernate.jdbc.batch_size 속성에대해알고자하면, 여기를참조하도록한다. 1st Level Cache Clear : memory size 를고려하여적절한수의 Persistence 객체에대한 save() 가이루어진후에 1LC 에 Caching 된 Persistent 상태의객체들을지워주도록한다. 다음은하나의트랜잭션내에서복수건의데이터를저장하는 multisave() 를포함한 HibernateMultiDataSave 의일부이다. public void multisave() throws Exception { session.setcachemode(cachemode.ignore); // insert country for (int i = 0; i < 90; i++) { Country country = new Country(); String countrycode = "COUNTRY-000" + i; country.setcountrycode(countrycode); country.setcountryid("kr" + i); country.setcountryname("korea" + i); session.save(country); if (i!= 0 && i % 9 == 0) { session.flush(); session.clear(); 47

51 6.HQL(Hibernate Query Language) Hibernate 은별도 Query Language 를제공함으로써객체지향관점에서객체의속성또는 Relation 정보를기반으로특정객체에대한조회와 DB 유형에독립적인 Query 정의를가능하도록한다. HQL 의구성요소및작성방법은아래와같다 구성요소 [ 선택 ] SELECT 절 전달받고자하는조회결과값을구체적으로명시하고자할경우정의한다. SELECT [object 또는 property], 여러건의데이터를조회할경우조회결과값을 List, Map 또는사용자정의 Type 으로정의가능하다. (Default = Object[]) SELECT new List(prop1, prop2, ) Hibernate 에서제공하는다양한 aggregate function(sum, avg, min, max, count, count(distinct), count(all), arithmetic operator(+, -, ), concatenation 그리고일반 SQL 에서사용가능한 keyword(distinct, ) 들도정의가능하다. 이외에도 Hibernate 은문자열, 숫자, 날짜및시간처리를위한함수를제공하며자세한사항은아래와같다. 문자열처리를위한함수 함수명 UPPER(str) 대문자로변환한다. LOWER(str) 소문자로변환한다. SUBSTRING(str, length) 설명 idx, 문자열의지정한 idx 위치에서 length만큼의문자열을얻어낸다 CONCAT(str1, str2) 두개의문자열을연결한다. LENGTH(str) 문자열의전체길이를구한다. LENGTH(str, s, idx) TRIM([type] str) 숫자처리를위한함수 해당문자열 str 에서정의된문자열 s 가포함되어있는위치를구한다. 검색시작위치는 idx 이다. 문자열의앞뒤공백을삭제한다. (Type 이 BOTH 일경우앞뒤공백삭제, Type 이 LEADING 일경우앞공백삭제, Type 이 TRAILING 일경우뒤공백삭제 ) 함수명 설명 ABS(num) 숫자의절대값을구한다. SQRT(num) 숫자의제곱근을구한다. MOD(num1, num2) num2을 num2로나눈나머지값을구한다. BIT_LENGTH(str) 문자열의비트길이를구한다. 날짜및시간처리를위한함수 48

52 HQL(Hibernate Query Language) 함수명 설명 CURRENT_DATE() 현재날짜를구한다. CURRENT_TIME() 현재시간을구한다. CURRENT_TIMESTAMP() 현재날짜및시간을구한다. HOUR(date), MINUTE(date), SECOND(date) 시, 분, 초값을구한다. YEAR(date), MONTH(date), DAY(date) 년, 월, 일값을구한다 [ 필수 ] FROM 절 조회대상객체를정의하며, SELECT 절이생략되었을경우 FROM 절에정의된객체가전달대상이된다. FROM [object] ((as) alias), [ 선택 ] WHERE 절 조회결과영역을보다상세히구분하고자할경우정의한다. WHERE [condition], Mapping XML 파일에정의한특정객체의식별자값을추출하기위해 "id" 를사용할수있다. (Hibernate 이상부터해당클래스의식별자필드가아닌다른필드명이 id 일경우 id 라는이름을가진필드의값을전달한다 ) WHERE user.id = 'test' 또한 Discriminator 값에접근하기위해서는아래와같이 "class" 를사용할수있다. 이외에도 Hibernate 에서제공하는다양한 expression 을활용하여 WHERE 절정의가가능하다. WHERE user.class = 'MEMBER' HQL WHERE 절에서사용가능한 Operation 은다음과같은것들이있다. 수학연산자 : +, -, *, / 비교연산자 : <>, <, >, <=, =>,! 논리연산자 : and, or, not Grouping : in, not in, between, is null, is not null, is empty, is not empty, member of, not member of Case : case when then else end 문자열 concatenation :, concat (, ) 날짜처리 : current_date(), current_time(), current_timestamp(), second(...), minute( ), hour( ), day( ), month( ), year( ) str() : 주어진값을문자열로변환 SELECT 또는 WHERE 절에서괄호사이에 Sub Query 형태의또다른 HQL 을정의할수있다 [ 선택 ] ORDER BY 절 조회결과의정렬방법을정의한다. 49

53 HQL(Hibernate Query Language) ORDER BY [condition] (ASC 또는 DESC), [ 선택 ] GROUP BY 절 조회결과를특정기준으로그룹핑하고자할경우정의한다. GROUP BY [condition], Order By, Group By 절에수식정의는불가하며, 일반 SQL 처럼 Having 절을추가하는것은가능하다 기본적인사용방법 HQL 을이용한기본적인 CRUD 방법과 Join 방법은다음과같다 Case 1. Basic HQL 을통해하나의테이블을대상으로조회작업을수행할수있다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("from Country country "); hqlbuf.append("where country.countryname like :condition "); hqlbuf.append("order BY country.countryname"); Query hqlquery = session.createquery(hqlbuf.tostring()); hqlquery.setparameter("condition", "%%"); List countrylist = hqlquery.list(); 위와같이정의된 HQL 문을통해조회조건에맞는 Country 객체의 List 가리턴된다. WHERE 절의조회조건은객체명.Attribute 명 (country.countryname) 으로정의할수있으며 ':' 을사용하여정의된속성과값을전달하여조회조건을완성할수있다. 조회조건의값은 org.hibernate.query 의 setparameter() 메소드를통해지정해주고있다 Case 2. Join HQL 을이용하여테이블간의 JOIN 을수행하고자할경우 Explicit Join, Implicit Join 으로처리가능하다. Hibernate 에서는 (inner) join, left (outer) join, right (outer) join, full join 을지원하며, Explicit Join 은 FROM 절에 join 키워드를명시적으로정의하여사용하는방법이다. Implicit Join 은 join 키워드를별도로사용하지않고 "." 을이용하여 HQL 어느절에서나정의할수있으며, Inner Join 으로처리된다. 다음은 Relation 관계에놓여있는두개의테이블을대상으로 Inner Join 을수행한조회작업의예이다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select movie "); hqlbuf.append("from Movie movie join movie.categories category "); hqlbuf.append("where category.categoryname =?"); Query query = session.createquery(hqlbuf.tostring()); query.setparameter(0, "Romantic");... 위의코드와같이 'join' 을이용해 relation 관계에놓여있는 MOVIE 테이블과 CATEGORY 테이블을 Inner Join 할수있으며기본적인 HQL 사용때와마찬가지로검색조건을정의할수있다. 또한 Relation 관계에놓여있는두개의테이블을대상으로 Right Outer Join 을수행할수있다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select distinct category "); hqlbuf.append("from Movie movie right join movie.categories category "); 50

54 HQL(Hibernate Query Language) hqlbuf.append("order BY category.categoryname ASC ");... Inner Join 과마찬가지로 'right join' 또는 'left join' 을사용할수있으며위의예는 right join 을사용하였다. 두테이블간의 Relation 관계가정의되어있지않을시 ',' 를통해두테이블을 Join 할수있으며 WEHER 절에 'movie.country.countrycode = country.countrycode' 와같이 join 을위한조건문을정의하여사용한다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select distinct movie "); hqlbuf.append("from Movie movie, Country country "); hqlbuf.append("where movie.country.countrycode = country.countrycode "); hqlbuf.append("and country.countryid = :condition1 "); hqlbuf.append("and movie.title like :condition2 "); Query query = session.createquery(hqlbuf.tostring()); query.setparameter("condition1", "KR"); query.setparameter("condition2", "%%");... 위에서설명된코드를포함하는 HQL 을이용한기본적인조회방법에대한예제는 HibernateBasicHQL.java 에서확인할수있다 원하는객체형태로전달 HQL 을통해조회작업을수행한후, 조회작업의결과를원하는객체형태로전달받을수있다. 이는여러테이블을 Join 할경우한테이블에매핑되는 Persistence 클래스가아닌 composite 클래스로리턴받고자할때사용할수있다 Case 1. 특정객체형태로전달 Relation 관계에놓여있는두개의테이블을대상으로 HQL(Inner Join) 을이용한조회결과를특정객체 ( 예에선 Movie 객체 ) 형태로전달받는다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select new Movie(movie.movieId as movieid, "); hqlbuf.append("movie.title as title, movie.director as director, "); hqlbuf.append("category.categoryname as categoryname, "); hqlbuf.append("movie.country.countryname as countryname) "); hqlbuf.append("from Movie movie join movie.categories category ");... 위와같이정의할경우 Movie 라는객체의형태로결과값이리턴되는데정의된클래스에해당 Constructor 가존재해야함에유의하도록한다. 다음은 Movie.java 의 Constructor 정의부분의일부이다. public Movie(String movieid, String title, String director, String categoryname, String countryname) { this.movieid = movieid; this.title = title; this.director = director; this.categoryname = categoryname; this.countryname = countryname; 또한리턴된결과값에서각각의 attribute 에해당하는값을꺼낼때에는 List 에서각 Movie 객체를꺼낸다음 getter 메소드를사용하도록한다. 51

55 HQL(Hibernate Query Language) List movielist = query.list(); Movie movie1 = (Movie) movielist.get(0); movie1.gettitle(); Movie movie2 = (Movie) movielist.get(1); movie2.gettitle(); Case 2. Map 형태로전달 Relation 관계에놓여있는두개의테이블을대상으로 HQL(Inner Join) 을이용한조회결과를 Map 형태로전달받는다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select new Map(movie.movieId as movieid, "); hqlbuf.append("movie.title as title, movie.director as director, "); hqlbuf.append("category.categoryname as categoryname, "); hqlbuf.append("movie.country.countryname as countryname) "); hqlbuf.append("from Movie movie join movie.categories category ");... 위와같이정의할경우조회결과는 Map 의 List 형태가된다. 이때 alias 로정의한 movieid, title, director, categoryname, countryname 이 Map 의 Key 값이된다. 따라서다음과같이 Map 으로정의된 Key 값을통해결과값을조회할수있다. List movielist = query.list(); Map movie1 = (Map) movielist.get(0); movie1.get("title"); movie1.get("director"); Map movie2 = (Map) movielist.get(1); movie2.get("title"); movie2.get("director"); Case 3. List 형태로전달 Relation 관계에놓여있는두개의테이블을대상으로 HQL(Inner Join) 을이용한조회결과를 List 형태로전달받을수있다. hqlbuf.append("select new List(movie.movieId as movieid, "); hqlbuf.append("movie.title as title, movie.director as director, "); hqlbuf.append("category.categoryname as categoryname, "); hqlbuf.append("movie.country.countryname as countryname) "); hqlbuf.append("from Movie movie join movie.categories category "); 위와같이정의할경우조회결과는 List 의 List 형태가된다. List 에서결과값을꺼낼때에는정의된순서에따르면된다. List movielist = query.list(); List movie1 = (List) movielist.get(0); movie1.get(1); //title movie1.get(2); //director List movie2 = (List) movielist.get(1); movie2.get(1); //title movie2.get(2); //director 위에서설명된 HQL 을이용하여결과값을특정객체로전달받는전체테스트코드는 HibernateHQLWithDefinedResult.java 에서확인할수있다. 52

56 HQL(Hibernate Query Language) 6.4.XML 에 HQL 정의하여사용 HQL 을별도 Hibernate Mapping XML 파일내에정의하고정의된 HQL 문의 name 을입력하여실행시킬수있다. 이는 HQL 이변경될경우소스코드변경없이 XML 문에정의된 HQL 만변경함으로써소스코드재컴파일이불필요하며 HQL 문만을따로관리할수있도록한다. Query hqlquery = session.getnamedquery("findcountrylist"); hqlquery.setparameter("condition", "%%"); List countrylist = hqlquery.list(); 위와같이 org.hibernate.session 의 getnamedquery() 메소드에 query name 을넘겨주면 Hibernate 은이이름에맞는 HQL 문을 XML 에서찾아서실행하게된다. 다음은 HQL 이정의되어있는 Country.hbm.xml 의일부이다. <query name="findcountrylist"> FROM Country country WHERE country.countryname like :condition ORDER BY country.countryname </query> HQL 의작성방법은앞서설명한방법과동일하며위에서설명한테스트코드는 HibernateNamedHQL.java 에서확인할수있다. 6.5.Pagination Pagination 은한페이지에보여줘야할조회목록에제한을둠으로써 DB 또는어플리케이션메모리의부하를감소시키고자하는데목적이있다. HQL 수행시페이징처리된조회결과를얻기위한방법에대해알아보도록한다. 특정테이블을대상으로 ( 예에서는 MOVIE 테이블 ) HQL 을이용한조회작업을수행한다. 이때, 조회를시작해야하는 Row 의 Number(FirstResult) 와조회목록의개수 (MaxResult) 를정의함으로써, 페이징처리가가능해진다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("from Movie movie "); Query hqlquery = session.createquery(hqlbuf.tostring()); // 첫번째로조회해야할항목의번호 hqlquery.setfirstresult(1); // 조회항목의전체개수 hqlquery.setmaxresults(2); List movielist = hqlquery.list(); 위와같이정의할경우 HQL 에서는 Hibernate Configuration 파일 (hibernate.cfg.xml) 에정의된 hibernate.dialect 속성에따라각각의 DB 에맞는 SQL 을생성한다. 이는 Pagination 을할때모든데이터를읽은후해당페이지에속한데이터갯수를결과값으로전달하는것이아니라조회해야할데이터즉, 해당페이지에속한갯수만큼의데이터만읽어오게된다. 다음은 hibernate. dialect 를 HSQL DB 로정의하였을때페이징처리가되어수행된쿼리문이다. select limit 1 2 movie0_.movie_id as MOVIE1_3_, movie0_.country_code as COUNTRY2_3_, movie0_.title as TITLE3_, movie0_.director as DIRECTOR3_, movie0_.release_date as RELEASE5_3_ from PUBLIC.MOVIE movie0_ 위의코드에서정의한것처럼첫번째로조회해야할항목의번호를 1, 조회항목의전체개수를 2 로정의하였으므로 Hibernate 에서는 HSQL DB 의특성에맞게 'limit 1 2' 가추가된 SQL 을실행하여페이징처리를수행하였다. 또한아래의코드와같이 ResultSet 내에서앞, 뒤로이동할수있는 ScrollableResults 를얻어코드내에서직접페이징처리를수행하는것도가능하다. ( 단, 해당 JDBC 드라이버가 Scroll 가능한 ResultSet 을지원하는경우에만가능 ) 53

57 HQL(Hibernate Query Language) Query query = session.createquery( from Users as user ); ScrollableResults userlist = query.scroll(); 위에서사용된 org.hibernate.query 클래스는데이터조회를위한 3 가지메소드를제공한다. list() : DB 테이블로부터모든데이터를한번에로딩한다. iterate() : 식별자값만을로딩한뒤, 데이터가실제로필요한시점에데이터를로딩한다. 이는캐쉬를사용하기위함으로 iterator() 메소드가전달한 Iterator 객체의 next() 메소드는캐쉬에동일한식별값을갖는객체가존재하는지체크하여해당객체가존재하면객체를, 존재하지않으면 Proxy 객체를리턴한다. scroll() : Cursor 를이용하여데이터를로딩한다. 위와같이 HQL 을이용한 Page 처리방법에대한코드는 HibernateHQLPaging.java 파일을참고한다. 6.6.HQL 을이용한 CUD 기본적으로 Hibernate 을이용한 CUD(Create, Update, Delete) 를할때에는 Hibernate 에서제공하는기본 API 를사용하게된다. (Hibernate Basic CRUD 참고 ) 그러나특이한경우 HQL 을통해기본 CUD 를수행해야하는경우가발생할수있다. (ex> 특정한컬럼에대한 Update) 이를위해 HQL 을이용한기본적인 CUD 방법에대해알아보도록하자 등록 (Insert) 다음은 HQL 을사용한 Insert 문의예이다. StringBuffer hql = new StringBuffer(); hql.append("insert INTO Country (countrycode,countryid,countryname) "); hql.append("select CONCAT(countryCode,'UPD'), CONCAT(countryId,'UPD'), countryname "); hql.append("from Country country "); hql.append("where countrycode = :countrycode"); Query query = session.createquery(hql.tostring()); query.setparameter("countrycode", "COUNTRY-0001"); query.executeupdate(); closesession(); 위와같이작성할경우 HQL 을이용하여신규 Country 정보를등록할수있다. 단, Hibernate 에서는 INSERT INTO... VALUES 형태의 INSERT 문은지원되지않으며, INSERT INTO... SELECT 형태의 INSERT 문만지원됨에유의하도록한다 수정 (Update) 다음은 HQL 을사용한 Update 문의예이다. newsession(); StringBuffer hql = new StringBuffer(); hql.append("update Country country "); hql.append("set country.countryname = :countryname "); hql.append("where country.countrycode = :countrycode and country.countryid = :countryid "); Query query = session.createquery(hql.tostring()); query.setparameter("countryname", "Republic of Korea"); query.setparameter("countrycode", "COUNTRY-0001"); query.setparameter("countryid", "KR"); 54

58 HQL(Hibernate Query Language) query.executeupdate(); closesession(); 위의예는 HQL 을사용하여 Country 정보를수정한것이며 Query 의 setparameter() 메소드를통해인자값을셋팅하고있다 삭제 (Delete) 다음은 HQL 을사용한 Delete 문의예이다. newsession(); StringBuffer hql = new StringBuffer(); hql.append("delete Country country "); hql.append("where country.countrycode = :countrycode "); Query query = session.createquery(hql.tostring()); query.setparameter("countrycode", "COUNTRY-0001"); query.executeupdate(); closesession(); 또한위에서언급된 HQL 을이용한 CUD 를위한코드는 HibernateCUDHQL.java 에서확인할수있다. 55

59 7.Criteria Queries Hibernate 에서는 HQL 에익숙하지못하거나 HQL 작성시발생할수있는오타로인한오류를최소화하기위해 org.hibernate. Criteria API 를사용할수있도록한다. Criteria API 호출을통해특정객체에대한조회가가능하고 org.hibernate. criterion.restrictions API 호출을통해 WHERE 문에해당하는기본조회조건을정의할수있다 기본적인사용방법 Hibernate Criteria 를이용하여특정객체정보에대해조회할수있다 Case 1. Basic 다음은하나의테이블을대상으로 Criteria 를이용하여조회를수행하는예이다. Criteria criteria = session.createcriteria(country.class); criteria.add(restrictions.like("countryname", "", MatchMode.ANYWHERE)); criteria.addorder(order.asc("countryname")); List countrylist = criteria.list(); 대상이되는테이블과매핑되는클래스로 Criteria 를생성하고 Restriction API 를호출해 WHERE 조건에해당하는조건절을정의할수있다. 위와같이정의한경우 WHERE Country.countryNamelike '%%' 와같은조건절이생성된다. 또한 addorder () 를통해 order by 절을정의할수있다. 이와같이 Criteria API 를이용할경우메소드를통해검색조건을정의하기때문에오타로인한오류를최소화할수있게된다. 조회조건을정의하기위한 org.hibernate.criterion.restrictions 는 eq, gt, ge, isnull 등을비롯하여다양한 API 를제공하고있다. 보다자세한내용을알기위해서는여기 [ US/JBoss_Hibernate/3.2.4.sp01.cp03/html-single/Reference_Guide/index.html#Criteria_Queries] 를참고하도록한다 Case 2. Join Relation 관계에놓여있는두개의테이블을대상으로 Hibernate Criteria(Inner Join) 를이용한조회작업을수행할수있다. Criteria moviecriteria = session.createcriteria(movie.class); Criteria categorycriteria = moviecriteria.createcriteria("categories"); categorycriteria.add(restrictions.eq("categoryname", "Romantic")); List movielist = moviecriteria.list(); 위코드에서는 Movie 클래스와 Relation 관계에놓인 Category 를 Join 하기위해각 Movie 객체에해당하는 Criteria 에 Category 객체에해당하는 Criteria 를생성하고있다. 여기서는 Restrictions API 를사용하여 categoryname = 'Romantic' 인결과값을찾게될것이다. 또한, Relation 관계에놓여있는두개의테이블을대상으로 Hibernate Criteria(Left Outer Join) 을이용한조회작업을수행할수있다. Criteria categorycriteria = session.createcriteria(category.class); Criteria moviecriteria = categorycriteria.createcriteria("movies", CriteriaSpecification.LEFT_JOIN); categorycriteria.addorder(order.asc("categoryname")); categorycriteria.setresulttransformer(criteria.distinct_root_entity); List categorylist = categorycriteria.list(); 56

60 Criteria Queries Relation 관계에있는테이블의 Criteria 를생성할때 CriteriaSpecification 을통해 LEFT_JOIN, RIGHT_JOIN 등을명시할수있다. 또한 Criteria.DISTINCT_ROOT_ENTITY 를사용하면 List 에중복포함된루트개체를제거할수있다. 위에서설명된코드들은 HibernateBasicCriteria.java 에서확인할수있다 원하는객체형태로전달 Criteria 의 setresulttransformer 메소드를사용하여 Criteria 를이용한조회결과를별도정의한객체형태로전달받을수있다 Case 1. 특정객체형태로전달 Relation 관계에놓여있는두개의테이블을대상으로 Criteria 를이용한조회결과를특정객체인 Movie 객체형태로전달받을수있다. Criteria moviecriteria = session.createcriteria(movie.class); ProjectionList projectionlist = Projections.projectionList(); projectionlist.add(projections.id().as("movieid")); projectionlist.add(projections.property("title").as("title")); projectionlist.add(projections.property("director").as("director")); moviecriteria.setprojection(projectionlist); moviecriteria.setresulttransformer(new AliasToBeanResultTransformer(Movie.class)); Criteria categorycriteria = moviecriteria.createcriteria("categories", "category"); Criteria countrycriteria = moviecriteria.createcriteria("country", "country"); categorycriteria.add(restrictions.eq("categoryname", "Romantic")); countrycriteria.add(restrictions.like("countryname", "", MatchMode.ANYWHERE)); List movielist = moviecriteria.list(); ProjectionList 에 SELECT 절을구성할조회대상 attribute 들을추가시키고 as() 메소드를이용하여각각의 attribute 에대한 alias 를정의할수있다. AliasToBeanResultTransformer 클래스를사용하여조회결과의형태를 Movie 클래스로지정해준다. 따라서위에서정의한 Criteria 수행결과는 Movie 객체의 List 형태가될것이다. Movie movie1 = (Movie) movielist.get(0); movie1.gettitle(); movie1.getdirector(); Case 2. Map 형태로전달 Relation 관계에놓여있는두개의테이블을대상으로 Criteria 를이용한조회결과를 Map 형태로전달받을수있다. Criteria moviecriteria = session.createcriteria(movie.class); ProjectionList projectionlist = Projections.projectionList(); projectionlist.add(projections.id().as("movieid")); projectionlist.add(projections.property("title").as("title")); projectionlist.add(projections.property("director").as("director")); moviecriteria.setprojection(projectionlist); moviecriteria.setresulttransformer(criteria.alias_to_entity_map); Criteria categorycriteria = moviecriteria.createcriteria("categories","category"); Criteria countrycriteria = moviecriteria.createcriteria("country","country"); categorycriteria.add(restrictions.eq("categoryname", "Romantic")); countrycriteria.add(restrictions.like("countryname", "",MatchMode.ANYWHERE)); 57

61 Criteria Queries List movielist = moviecriteria.list(); 위에서생성한 Criteria 의 resulttransformer 를 ALIAS_TO_ENTITY_MAP 으로지정하여 Map 형태의결과값으로전달받을수있다. 이때조회결과는 Map 의 List 형태이며, alias 로정의한 movieid, title, director 등이 Map 의 Key 값이된다. 따라서다음과같이 Map 의 Key 값을통해다음과같이결과값을알아낼수있다. Map movie1 = (Map) movielist.get(0); movie1.get("title"); movie1.get("director"); 위에서언급된코드는 HibernateCriteriaWithDefinedResult.java 에서확인할수있다. 7.3.Pagination Criteria 를이용하여객체조회시페이징처리된결과를얻기위한방법에대해알아본다. HQL 을사용한 Pagination 과마찬가지로시작해야하는 Row 의 Number(FirstResult) 와조회목록의개수 (MaxResult) 를정의함으로써, 페이징처리를할수있다. 사용예는다음과같다. Criteria criteria = session.createcriteria(movie.class); criteria.setfirstresult(1); criteria.setmaxresults(2); List movielist = criteria.list(); 위와같이정의할경우 Hibernate Configuration 파일 (hibernate.cfg.xml) 에정의된 hibernate.dialect 속성에따라각각의 DB 에맞는 SQL 을생성한다. 이는 Pagination 을할때모든데이터를읽은후해당페이지에속한데이터갯수를결과값으로전달하는것이아니라조회해야할데이터즉, 해당페이지에속한갯수만큼의데이터만읽어오게된다. 다음은 hibernate.dialect 를 HSQL DB 로정의하였을때페이징처리가되어수행된쿼리문이다. select limit 1 2 this_.movie_id as MOVIE1_3_0_, this_.country_code as COUNTRY2_3_0_, this_.title as TITLE3_0_, this_.director as DIRECTOR3_0_, this_.release_date as RELEASE5_3_0_ from PUBLIC.MOVIE this_ 위의코드에서정의한것처럼첫번째로조회해야할항목의번호를 1, 조회항목의전체개수를 2 로정의하였으므로 Hibernate 에서는 HSQL DB 의특성에맞게 'limit 1 2' 가추가된 SQL 을실행하여페이징처리를수행하였다. 위의코드는 HibernateCriteriaPaging.java 에서확인할수있다. 58

62 8.Native SQL Hibernate 에서는기본적으로 CRUD 작업을할때 Hibernate 기본 API 를사용하거나 Criteria 를사용하여수행한다. 그러나특정 DBMS 에서제공하는기능을사용할수있도록하기위해 Hibernate 은 Native SQL 사용을지원한다 기본적인사용방법 session.createsqlquery() 메소드를이용하여 Native SQL 을실행할수있다 Case 1. Basic 하나의테이블을대상으로 Native SQL 을이용한조회작업을수행할수있다. hqlbuf = new StringBuffer(); hqlbuf.append("select * "); hqlbuf.append("from COUNTRY "); hqlbuf.append("where COUNTRY_NAME like :condition "); hqlbuf.append("order BY COUNTRY_NAME"); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity(country.class); query.setparameter("condition", "%%"); List countrylist = query.list(); session.createsqlquery() 를사용하여정의된 SQL 문을실행한다. 또한, 조회결과값을특정 Persistence 객체로전달받고자하는경우 SQLQuery.addEntity() 를통해특정타입의객체를정의하여사용한다 Case 2. Join Relation 관계에놓여있는두개의테이블을대상으로 Native SQL(Inner Join) 을이용한조회작업을수행할수있다. hqlbuf.append("select movie.* "); hqlbuf.append("from MOVIE movie "); hqlbuf.append("join MOVIE_CATEGORY moviecategory on movie.movie_id = moviecategory.movie_id "); hqlbuf.append("join CATEGORY category on moviecategory.category_id = category.category_id "); hqlbuf.append("where category.category_name =?"); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity(movie.class); query.setparameter(0, "Romantic"); List movielist = query.list(); 위의코드와같이 join 키워드를사용하여 Inner Join 을수행할수있다. 또한, Relation 관계에놓여있는두개의테이블을대상으로 Native SQL(Right Outer Join) 을이용한조회작업을수행할수있다. 작성방법은아래와같다. hqlbuf.append("select distinct category.* "); hqlbuf.append("from MOVIE movie "); hqlbuf.append("right join MOVIE_CATEGORY moviecategory on movie.movie_id=moviecategory.movie_id "); hqlbuf.append("right join CATEGORY category on moviecategory.category_id=category.category_id "); 59

63 Native SQL hqlbuf.append("order BY category.category_name ASC "); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity(category.class); List categorylist = query.list(); 또한 Join 하여조회한결과를각각의 Join 된객체의값으로 select 하기위해서는 addjoin 메소드를사용한다. hqlbuf.append("select distinct movie.*, country.* "); hqlbuf.append("from MOVIE movie, COUNTRY country "); hqlbuf.append("where movie.country_code = country.country_code "); hqlbuf.append("and country.country_id = :condition1 "); hqlbuf.append("and movie.title like :condition2 "); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity("movie", Movie.class); query.addjoin("country", "movie.country"); query.setparameter("condition1", "KR"); query.setparameter("condition2", "%%"); List movielist = query.list(); Movie 와 Country 정보를한꺼번에조회하기위해위 Select 문의 Movie 객체의 alias 와같은 'movie' 를이용하여 Movie 클래스를 addentity() 의입력인자로정의한다음 Join 대상이되는 Country 또한 addjoin() 메소드에정의해주어야한다. 위의코드에서는 Country 객체의 alias 인 'country' 와이객체의값인 movie.country 를입력인자로지정해주었다. (movie.country 의 movie 는 addentity() 메소드를통해정의된 Entity 의 Key 값이다.) 이때리턴되는 List 는 Object Array 배열이되며 Object Array 에는아래와같이 movie 와 country 가차례대로저장되게된다. language="java">object[] results1 = (Object[]) movielist.get(0); Movie movie1 = (Movie)results1[0]; Country country1 = (Country)results1[1]; Case 3. 검색조건명시 두개의테이블을대상으로검색조건을별도명시한 Native SQL 을이용하여조회작업을수행할수있다. hqlbuf.append("select distinct movie.* "); hqlbuf.append("from MOVIE movie, COUNTRY country "); hqlbuf.append("where movie.country_code = country.country_code "); hqlbuf.append("and country.country_id = :condition1 "); hqlbuf.append("and movie.title like :condition2 "); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity(movie.class); query.setparameter("condition1", "KR"); query.setparameter("condition2", "%%"); List movielist = query.list(); ":"(Named Parameter 형태 ) 으로조건을명시할수있으며해당조건의값은 setparameter() 를통해셋팅해줄수있다. 위에서설명한기본적인 Native SQL 사용코드는 HibernateNativeSQL.java 에서확인할수있다. 8.2.XML 에 Native SQL 정의하여사용 Native SQL 을별도 Hibernate Mapping XML 파일내에정의하고정의된 Native SQL 문의 name 을입력하여실행시킬수있다. 이는 Native SQL 이변경될경우소스코드변경없이 XML 문에정의된 HQL 을변경함 60

64 Native SQL 으로써재컴파일이불필요하며 Native SQL 문만을따로관리할수있도록한다. org.hibernate.session 의 getnamedquery() 메소드를사용하면 Native SQL 문의 name 으로정의된 Native SQL 을수행한다. Query query = session.getnamedquery("nativefindcountrylist"); query.setparameter("condition", "%%"); List countrylist = query.list(); 다음은 Native SQL 이정의되어있는 Country.hbm.xml 의일부이다. <sql-query name="nativefindcountrylist"> <return alias="country" class="anyframe.sample.model.bidirection.country"/> SELECT * FROM COUNTRY country WHERE country.country_name like :condition ORDER BY country.country_name </sql-query> Native SQL 작성을위해해당 XML 에는 <sql-query> 태그를사용하여작성한다. 위에서설명한테스트코드는 HibernateNamedNativeSQL.java 에서확인할수있다. 8.3.Pagination Pagination 은한페이지에보여줘야할조회목록에제한을둠으로써 DB 또는어플리케이션메모리의부하를감소시키고자하는데목적이있다. Native SQL 수행시페이징처리된조회결과를얻기위한방법에대해알아보도록한다. 특정테이블을대상으로 ( 예에서는 MOVIE 테이블 ) Native SQL 을이용한조회작업을수행한다. 이때, 조회를시작해야하는 Row 의 Number (FirstResult) 와조회목록의개수 (MaxResult) 를정의함으로써, 페이징처리가가능해진다. hqlbuf.append("select * "); hqlbuf.append("from MOVIE "); SQLQuery query = session.createsqlquery(hqlbuf.tostring()); query.addentity(movie.class); query.setfirstresult(1); query.setmaxresults(2); List movielist = query.list(); 위와같이정의할경우 Hibernate Configuration 파일에정의된 hibernate.dialect 속성에따라각각의 DB 에맞게변경된 SQL 이수행한다. 이는 Pagination 을할때모든데이터를읽은후해당페이지에속한데이터갯수를결과값으로전달하는것이아니라조회해야할데이터즉, 해당페이지에속한갯수만큼의데이터만읽어오게된다. 다음은 hibernate.dialect 를 HSQL DB 로정의하였을때페이징처리가되어수행된쿼리문이다. SELECT limit 1 2 * FROM MOVIE 위의코드에서정의한것처럼첫번째로조회해야할항목의번호를 1, 조회항목의전체개수를 2 로정의하였으므로 Hibernate 에서는 HSQL DB 의특성에맞게 'limit 1 2' 가추가된 SQL 을실행하여페이징처리를수행하였다. 위의코드는 HibernateNativeSQLPaging.java 에서확인할수있다. 8.4.Callable Statement Hibernate 를이용하여 DB 에기등록된 Procedure 또는 Function 을실행시킬수있다 Case 1. XML 에정의한 Procedure 호출 Mapping XML 파일에정의한 Procedure 를호출하여결과값을확인할수있다. 61

65 Native SQL Query query = session.getnamedquery("callfindcategorylist"); query.setparameter("condition", "%%"); List categorylist = query.list(); 위코드에서는 session.getnamequery() 를호출하여 Mapping XML 에정의된 'callfindcategorylist' 라는이름의 query 를찾는다. 다음은 'callfindcategorylist' 가정의되어있는 Category.hbm.xml 파일의일부이다. <sql-query name="callfindcategorylist" callable="true"> <return alias="category" class="anyframe.sample.model.bidirection.category"/> { call FIND_CATEGORY_LIST (?, :condition) </sql-query> 위의코드에서는해당 DB 에기정의되어있는 FIND_CATEGORY_LIST 라는 Procedure 를호출하게된다 Case 2. Function 을이용한 HQL 실행 해당 DB 에생성한 Function 을이용하여 HQL 을실행하고결과를확인할수있다. hqlbuf.append("from Movie movie "); hqlbuf.append("where movie.releasedate > FIND_MOVIE(:condition)"); Query query = session.createquery(hqlbuf.tostring()); query.setparameter("condition", "MV-00002"); List movielist = query.list(); 위코드에서는 'FIND_MOVIE' 라는 Function 의호출결과를이용하여 HQL 을수행하고있다. 보다자세한코드는 HibernateProcedure.java 에서확인한다. 62

66 9.Performance Strategy Hibnernate 은성능개선을위해 Cache 와 Fetch 등의 Performance Strategy 를제공한다. 크게 Cache 는 1 Level Cache 와 2 Level Cache 등으로구분되며이는매번 DB 에접근없이해당 Cache 를이용하여객체를조회또는보관할수있도록한다. 또한여러가지 Fetch 전략을적절히적용함으로써 Lazy Loading 으로발생할수있는 N+1 SELECT 이슈를처리할수있다. 9.1.Cache Hibernate 을사용하면입력인자로전달된객체를정의된테이블로매핑시켜데이터액세스처리를수행해야하는데 Hibernate 에서는이로인해발생가능한성능이슈를개선하기위해 Cache 를활용한다. 특히, 어플리케이션의조회기능이전체실행시간의많은비중을차지하는경우매번 DB 에접근하지않고 Cache 에저장된객체를사용함으로써성능을향상시킬수있게되는것이다 LC (1 Level Cache) Hibernate Session 내부에정의된 Cache 로, Session 의시작과종료사이에서사용되며한 Session 내에서 Hibernate 을통해읽혀진객체들을보관하는역할을수행한다. Hibernate 은하나의 Session 내에서동일한객체를한번이상 Loading 할경우 2 번째부터는 1LC 로부터해당객체를추출하고또한, 한 Session 범위내에서객체의속성변경시변경사항은 Session 종료시에자동적으로 DB 에반영하도록한다. 즉, 하나의 Hibernate Session 내에서동일한객체에대한재조회가이루어지는경우 1LC 를이용함으로써 DB 접근횟수를줄여주기때문에어플리케이션성능향상에도움이되는것이다. 1LC 는 Hibernate 에서기본적으로제공하는 Cache 이므로별도의설정없이도적용된다. public void findmovie() throws Exception { newsession(); // Add data to DB SetUpInitData.initializeData(session); // 2. find a movie without accessing DB (using 1LC) /* #1 */ Movie movie = (Movie) session.get(movie.class, "MV-00001"); Set categories = movie.getcategories(); categories.iterator(); // 3. find a movie again without accessing DB (using 1LC) movie = (Movie) session.get(movie.class, "MV-00001"); categories = movie.getcategories(); categories.iterator(); closesession(); 위와같이작성할경우동일한 Session 내에서 SetUpInitData.initializeData(session) 를통해 save 된 Persistence 객체는 1LC 에저장되므로다음에 #1 번코드에서처럼동일한 Persistence 객체조회시 DB 에재접근하지않고도, Cache 를통해조회된다. findmovie() 메소드를포함한 HibernateFirstLevelCache.java 테스트소스를 DEBUG 모드로실행시켜서실행되는쿼리를콘솔창을통해확인해보면이를확인할수있을것이다. SetUpInitData.java 에대한내용은여기에서확인할수있다 LC (2 Level Cache) 2LC 는어플리케이션단위의 Cache 로, 어플리케이션관점에서의 Cache 기능을지원한다. 이는여러트랜잭션들을통해 Load 된 Persistence 객체를 Session Factory 레벨에서저장하는방법으로처리된다. 63

67 Performance Strategy hibernate.cache.use_second_level_cache, hibernate.cache.provider_class 등을정의하고, 2LC 에저장되어야할 Persistence Class 매핑파일의 <cache> 속성을정의하면해당어플리케이션을구성하는특정 Persistence 객체들에대해 2LC 를적용할수있다. 다음은 2LC 에대한속성이정의되어있는 hibernate.cfg.xml 파일의일부이다. <property name="hibernate.cache.provider_class">org.hibernate.cache.ehcacheprovider </property> <property name="hibernate.cache.use_second_level_cache]">true </property> 다음은 cache 속성이 read-write 로설정되어있는 Persistence Class 매핑파일 Country.hbm.xml 의일부이다. <class name="anyframe.sample.model.bidirection.country" table="country" lazy="true" schema="public"> <cache usage="read-write"/> <id name="countrycode" type="string"> <column name="country_code" length="12" /> <generator class="assigned" /> </id> <property name="countryid" type="string"> <column name="country_id" length="2" not-null="true" /> </property>... </class> cache 의속성은위에서언급한 read-write 외에도다음과같은속성값으로정의할수있다. read-only : Persistence 객체가변경되지않는경우에사용가능하다. 수정이없으므로분산환경에서도안전하게사용가능하며가장빠른성능을제공한다. read-write : Persistence 객체가변경되는경우에사용가능하다. DBMS 의 read-committed 와동일하게동시접근을관리한다. nonstrict-read-write : 트랜잭션격리를엄격히적용할필요가없는경우사용가능하다. transactional : 완전한트랜잭션을보장하나가장느린성능을제공한다. JTA 환경내에서만사용된다. 위와같은설정을기반으로 HibernateSecondLevelCache.java findcountry() 메소드를실행해보면다음의 #1 번코드에의해새로운 Session 이시작되었음에도 #2 번코드에서 DB 에접근하지않고이전 Session 에서 Cache 에저장한값을가지고사용한다는것을확인할수있다. public void findcountry() throws Exception { newsession(); SetUpInitData.initializeData(session); closesession(); // 2. find a movie without accessing DB (using 2LC) /* #1 */ newsession(); /* #2 */ Country country = (Country) session.get(country.class, "COUNTRY-0001"); Set movies = country.getmovies(); movies.iterator(); closesession(); // 3. find a movie again without accessing DB (using 2LC) newsession(); country = (Country) session.get(country.class, "COUNTRY-0001"); movies = country.getmovies(); 64

68 Performance Strategy movies.iterator(); closesession(); DEBUG 모드에서테스트케이스를실행시켜보면서 DB 에접근하지않고도 2LC 를통해객체가조회되는것을살펴볼것을권장한다. HibernateSecondLevelCache.java 의 findmovie() 는 2LC 사용하지않는 Persistence Class 인 Movie 에대한테스트로써앞서언급한 findcountry() 와달리 Session 이다를경우매번 DB 에접근하여해당 Persistence 객체를조회해오는것을알수있다. 단, 2LC 를적용하고자할경우해당어플리케이션을통하지않고, 외부에서직접적으로 DB 정보가수정될가능성이있다면데이터의동기화를위해세밀한 Cache 속성제어가필요함에유의하도록한다 분산 Cache 하나의어플리케이션을대상으로하는경우앞서언급한 2LC 를사용하는데문제가없으나, 일반적인 Clustered 환경에서실행된여러개의어플리케이션에속한 2LC 사이의데이터동기화는중요한사항이될것이다. 이를위해 Hibernate 는분산 Cache 를지원하는구현체를통해분산어플리케이션에대한 Cache 기능을지원한다. 다음에서는분산 Cache 를지원하는구현체별로설정방법및실행결과에대해살펴보기로하자 OSCacheProvider 이용 OSCache 2.0 부터분산 Cache 를지원한다. 현재 OSCache 는분산된 Cache 들이 Caching 하고있는데이터동기화를위해 JavaGroups 또는 JMS 를통해 Event 를처리할수있도록구현체를제공한다. 단, 분산 Cache 사이에서 flush Event 발생시 (Caching 된객체를 Cache 에서지울때 ) 에만 Message 를 broadcast 하는기능이지원된다. 본페이지에서는 OSCacheProvider 와 JMS 기능을제공하는오픈소스 ActiveMQ 를사용하여분산 Cache 를관리하는방법에대해알아볼것이다. 다음은 Hibernate Configuration 파일로, hibernate.cache. provider_class 속성값으로 OSCacheProvider 를지정하고있음을알수있다. <session-factory> <property name="hibernate.format_sql">true</property> <property name="hbm2ddl.auto">create</property> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.provider_class"> com.opensymphony.oscache.hibernate.oscacheprovider</property> <property name="hibernate.cache.region_prefix"> hibernate.cache</property> <property name="com.opensymphony.oscache.configurationresourcename"> oscache-hibernate.properties</property> </session-factory> 또한, Hibernate Cache 영역에대해 hibernate.cache.region_prefix 를별도로지정하였다. (hibernate.cache.region_prefix 가위와같이정의된경우, Persistence Class 인 anyframe. sample.model.bidirection.country 는해당 2LC 의 hibernate.cache. anyframe.sample.model.bidirection.country 영역에객체가 Caching 된다.) 끝으로, com.opensymphony. oscache.configurationresourcename 속성에 OSCacheProvider 가분산 Cache 들사이의데이터동기화를위해필요로하는모든속성정보를정의해주어야한다. 위에서 com.opensymphony.oscache.configurationresourcename 의속성값으로정의한 oscachehibernate.properties 파일내용은다음과같다. cache.event.listeners=anyframe.core.cache.impl.jmsbroadcastinglistener 65

69 Performance Strategy cache.cluster.jndi.config=jndi.properties cache.cluster.jms.topic.factory=topicconnectionfactory cache.cluster.jms.topic.name=dynamictopics/topic cache.cluster.jms.node.name=node1 각속성은다음과같은의미를지닌다. cache.event.listeners : 한 Cache 에변경사항이발생한경우분산 Cache 간동기화를위해 Event 처리가필요하며, OSCache 에서는 JMS 를통해 Event 를처리하기위해기본적으로 com.opensymphony.oscache.plugins. clustersupport.jmsbroadcastinglistener 를제공한다. 그러나이것은앞서언급했듯이 flush Event 발생시에만 Message 를 broadcast 하는기능만지원되므로 Caching 된객체에대해수정이발생한경우에는 Message Broadcasting 되지않는취약점이있다. 따라서, Anyframe 에서는이를보완한별도 Cache Event Listener 클래스 (anyframe.core.cache.impl.jmsbroadcastinglistener) 를제공하고있다. Anyframe 의 JMSBroadcastingListener 는특정어플리케이션을통해 Caching 된객체에수정이발생한경우 Clustering 된모든어플리케이션의 Cache 에서해당객체를지우도록 Event 를보낸다. cache.cluster.jndi.config : Cache Event Listener 에서 JMS Server 에접근하기위해필요한환경정보를정의하기위한파일이다. JMS Server 의 InitialContextFactory 클래스를정의하기위한 java. naming.factory.initial 와 Provider URL 정의를위한 java.naming. provider.url 를정의해준다. 다음은 jndi.properties 파일내용이다. java.naming.factory.initial=org.apache.activemq.jndi.activemqinitialcontextfactory java.naming.provider.url=tcp://localhost:61616 cache.cluster.jms.topic.factory : JMS topic connection factory 에접근하기위한 JNDI 명을정의한다. ActiveMQ 의경우, TopicConnectionFactory 와같이정의하면 Topic 을사용하여 Messaging 처리를수행하게된다. cache.cluster.jms.topic.name : OSCache 에서 Message 를보내기위해사용할 Topic 의 JNDI 명을정의한다. ActiveMQ 의경우, dynamictopics/ 다음에 ActiveMQ 에생성한 Topic 명을정의해주는데만일정의한이름을가진 Topic 이존재하지않으면, 해당 Topic 이신규로생성된다. cache.cluster.jms.node.name : 분산환경을구성하는여러어플리케이션중해당어플리케이션을식별하기위한식별자를정의한다. 분산환경을구성하고있는각어플리케이션들은모두다른 node 명을갖도록지정해야한다. Cache Event 가발생할때해당어플리케이션을포함하여분산환경을구성하고있는모든어플리케이션의 Cache 에해당 Event 가 Send 되는데, Cache Event 가발생한해당어플리케이션에서는 Event 를받더라도아무런 Action 을취할필요가없다. 따라서, cache.cluster.jms.node.name 는 Cache Event 가어느어플리케이션에서발생했는지알수있는정보로활용된다. 위와같은설정이모두완료되었다면, 동일한어플리케이션 2 개를각기다른 WAS 를통해시작시킨후다음과같은유형의요청수행시 Cache 가제대로동작하는지확인해보자. 이때, 사용하는 JMS 서버라이브러리와함께 jms spec., j2ee management spec. 라이브러리를각어플리케이션에배포하여구동시켜줘야한다. 이예제에서는 JMS 서버로 ActiveMQ 를사용하므로, 각어플리케이션의 WEB-INF/lib 폴더에 activemq-core-x.x.x.jar 와 jms spec jar, j2ee management spec jar 파일을배포하여테스트하였다. 어플리케이션 A 에서특정데이터조회후, 어플리케이션 B 에서동일한데이터조회시별도쿼리문수행없이해당데이터가조회되는지확인한다. 즉, 어플리케이션 B 는 DB 에접근하지않고 Cache 를통해데이터를조회하는지확인한다. 어플리케이션 A 에서특정데이터수정후, Event 가 Send 되고어플케이션 B 에서해당 Event 를 Receive 하는지확인한다. 66

70 Performance Strategy 또한어플리케이션 B 에서어플리케이션 A 를통해수정한데이터조회시해당객체는 Cache Event Listener 에의해 Cache 로부터지워졌으므로, 기존에 Caching 된객체를그대로읽지않고, DB 에접근하여변경된데이터를읽어오는지확인한다. (* WAS 가 Tomcat 일경우 spring-tomcat-weaver.jar 파일을다운로드하여 Tomcat 설치폴더 \server\lib 에복사해야한다.) 9.2.Fetch Strategy Lazy Loading 이란 Hibernate 에서기본적으로객체가실제로필요하기전까지 SQL 을실행하지않고 Proxy 객체로리턴하는것을말한다. 이러한 Lazy Loading 을통해불필요한 DB 접근을줄이고 Session 내에존재하는 Persistence 객체의개수를감소시킬수있다. 하지만이러한 Lazy Loading 을처리하기위해다음과같은 N+1 SELECT 이슈가발생하게된다. 다음은 Lazy Loading 으로발생할수있는 N+1 SELECT 문제를테스트할수있는 HibernateFetchWithDefaultLazyLoading.java 파일의일부이다. hqlbuf.append("from Category category "); hqlbuf.append("order BY category.categoryname ASC"); Query query = session.createquery(hqlbuf.tostring()); /*1 번의쿼리수행 : select category0_.category_id as CATEGORY1_0_, category0_.category_name as CATEGORY2_0_, category0_.category_desc as CATEGORY3_0_ from PUBLIC.CATEGORY category0_ order by category0_.category_name ASC */ List categorylist = query.list(); for (int i = 0; i < categorylist.size(); i++) { Category category = (Category) categorylist.get(i); if (i == 0) { Set movies = category.getmovies(); /* n 번의쿼리수행 : select movies0_.category_id as CATEGORY1_1_, movies0_.movie_id as MOVIE2_1_, movie1_.movie_id as MOVIE1_3_0_, movie1_.country_code as COUNTRY2_3_0_, movie1_.title as TITLE3_0_, movie1_.director as DIRECTOR3_0_, movie1_.release_date as RELEASE5_3_0_ from MOVIE_CATEGORY movies0_ left outer join PUBLIC.MOVIE movie1_ on movies0_.movie_id=movie1_.movie_id where movies0_.category_id=? */ else if (i == 1) { Set movies = category.getmovies();... Category 에대한조회작업을수행하며특정 Category 에속한 Movie Set 조회시 Movie 정보조회를위한 SELECT 문이수행된다. 이를해결하기위해 Fetch 방식에대한제어가필요하며그예는다음과같다 Batch 를이용하여데이터조회 Hibernate Mapping XML 파일내에특정객체에대한 batch-size 를지정할경우지정한개수만큼해당객체를로딩하는방식으로쿼리실행회수가 n/batch size + 1 로감소한다. 다음은 batch-size 설정예인 Country.hbm.xml 파일의일부이다. 67

71 Performance Strategy <hibernate-mapping> <class name="anyframe.sample.model.bidirection.country" table="country" lazy="true" schema="public"> <id name="countrycode" type="string">.. </id> <property name="countryid" type="string"> <column name="country_id" length="2" not-null="true" /> </property>.. <set name="movies" inverse="true" cascade="save-update" batch-size="2"> <key> <column name="country_code" length="12" /> </key> <one-to-many class="anyframe.sample.model.bidirection.movie" /> </set> </class> </hibernate-mapping> 위와같이정의할경우 Country:Movie 관계에서 Movie Set 에대한 Fetch Strategy 를 Batch Fetching 한다.( 여기서는 batch-size="2" 로정의함.) 특정 Country 에속한 Movie Set 을조회하고자할때 batch-size 를기반으로 SELECT 문이수행된다. hqlbuf.append("from Country"); Query query = session.createquery(hqlbuf.tostring()); List countrylist = query.list(); // 3. check result - country for (int i = 0; i < countrylist.size(); i++) { Country country = (Country) countrylist.get(i); if (i == 0) { Set movies = country.getmovies(); /* batch-size 가 2 이므로 2 개씩조회 select movies0_.country_code as COUNTRY2_1_, movies0_.movie_id as MOVIE1_1_, movies0_.movie_id as MOVIE1_3_0_, movies0_.country_code as COUNTRY2_3_0_, movies0_.title as TITLE3_0_, movies0_.director as DIRECTOR3_0_, movies0_.release_date as RELEASE5_3_0_ from PUBLIC.MOVIE movies0_ where movies0_.country_code in ('COUNTRY-0001', 'COUNTRY-0003')'*/ else if (i == 1) { Set movies = country.getmovies(); // 쿼리수행안함. 위에대한테스트코드는 HibernateFetchWithBatchSize.java 를참고한다 Sub-Query 를이용하여데이터조회 또다른 fetch 전략으로 subselect 속성을주는방법이있다. subselect 속성정의방법은 Mapping XML 파일인 Movie.hbm.xml 에서다음과같이확인할수있다. <hibernate-mapping> <class name="anyframe.sample.model.bidirection.movie" table="movie" lazy="true"..> <id name="movieid" type="string"> <column name="movie_id" /> <generator class="assigned" /> </id> <property name="title" type="string"> 68

72 Performance Strategy <column name="title" length="100" not-null="true" /> </property>... <set name="categories" inverse="false" table="movie_category" fetch="subselect"> <key> <column name="movie_id" length="8" not-null="true" /> </key>.. </set> </class> </hibernate-mapping> 위와같이 Movie 클래스내의 categories set 에대해 fetch 속성의값을 subselect 로정의할경우해당데이터를불러올때 Sub Query 형태의 SELECT 문이수행되며한번에모두로딩하게된다. for (int i = 0; i < movielist.size(); i++) { Movie movie = (Movie) movielist.get(i); if (i == 0) {.. Set categories = movie.getcategories(); /* categories 에대한 Sub Query 형태의 SELECT 문이발생한다. select categories0_.movie_id as MOVIE2_1_, categories0_.category_id as CATEGORY1_1_, category1_.category_id as CATEGORY1_0_0_, category1_.category_name as CATEGORY2_0_0_, category1_.category_desc as CATEGORY3_0_0_ from MOVIE_CATEGORY categories0_ left outer join PUBLIC.CATEGORY category1_ on categories0_.category_id=category1_.category_id where categories0_.movie_id in (select movie0_.movie_id from PUBLIC.MOVIE movie0_) */ else if (i == 1) {.. Set categories = movie.getcategories(); // 쿼리수행안함.... 하지만최초로필요한순간에모든데이터를로딩하므로동시에많은데이터요청이있을경우메모리사용량이급격히증가할수있음에유의한다. 위의테스트코드는 HibernateFetchWithSubselect.java 에서확인할수있다 join fetch 를이용하여데이터한꺼번에조회 특정 HQL 문에 "join fetch" 절을사용하게되면해당 Join 객체에대해서 Lazy Loading 과다른방식으로한번에필요한데이터를모두로딩하게된다. 다음은 join fetch 가적용된 HibernateFetchWithoutLazyLoading.java 파일의일부이다. StringBuffer hqlbuf = new StringBuffer(); hqlbuf.append("select movie "); hqlbuf.append("from Movie movie join fetch movie.categories category "); hqlbuf.append("where category.categoryname =?"); Query query = session.createquery(hqlbuf.tostring()); query.setparameter(0, "Romantic"); /* fetch join 된 categories 의데이터도한꺼번에모두로드시킨다. (Lazy Loading 이아님 ) select movie0_.movie_id as MOVIE1_3_0_, category2_.category_id as CATEGORY1_0_1_, movie0_.country_code as COUNTRY2_3_0_, movie0_.title as TITLE3_0_, movie0_.director as DIRECTOR3_0_, movie0_.release_date as RELEASE5_3_0_, 69

73 Performance Strategy category2_.category_name as CATEGORY2_0_1_, category2_.category_desc as CATEGORY3_0_1_, categories1_.movie_id as MOVIE2_0, categories1_.category_id as CATEGORY1_0 from PUBLIC.MOVIE movie0_ inner join MOVIE_CATEGORY categories1_ on movie0_.movie_id=categories1_.movie_id inner join PUBLIC.CATEGORY category2_ on categories1_.category_id=category2_.category_id where category2_.category_name='romantic' */ List movielist = query.list(); // 3. check result - movie for (int i = 0; i < movielist.size(); i++) { Movie movie = (Movie) movielist.get(i); if (i == 0) {.. Set categories = movie.getcategories(); // 쿼리수행안함. else if (i == 1) {.. Set categories = movie.getcategories(); // 쿼리수행안함.... 이는 categories 에대한 fetch 속성을 "join" 으로준것과같이동작하게된다. 하지만 Mapping XML 에정의할경우 Movie 를조회할때마다 (Category 목록이필요하지않은경우에도 ) 모든 Category 목록도함께초기화되어메모리에올라오게되므로위와같이 HQL 문에 join fetch 를사용하여필요한경우에만적용되도록하는것이효율적이다. 70

74 10.Concurrency Hibernate 에서는동시에동일한데이터에접근할때에데이터에대한접근을제어하기위해 Optimistic Locking 또는 Pessimistic Locking 기법등을제공한다 Optimistic Locking public void updatemoviewithoutoptimisticlocking() throws Exception { // 1. insert a new country, movies information newsession(); // 첫번째트랜잭션 addcountrymovieatonce(); closesession(); // 2. select a country newsession(); // 두번째트랜잭션 /* #1 */ Movie fstmovie = (Movie) session.get(movie.class, "MV-00001"); /* #2 */ Movie scdmovie = (Movie) session.get(movie.class, "MV-00001"); closesession(); // 3. set country name /* #3 */ fstmovie.settitle("first : My Sassy Girl"); // 4. select a country again with same id and update country name newsession(); // 세번째트랜잭션 /* #4 */ scdmovie.settitle("second : My Sassy Girl"); closesession(); // 5. try to update with detached object newsession(); // 네번째트랜잭션 /* #5 */ session.update(fstmovie); closesession(); 위에서제시한 updatemoviewithoutoptimisticlocking() 의로직에대해자세히살펴보자. 1. #1, #2 번코드에의해각각동일한식별자를이용하여같은데이터조회 2. 두번째트랜잭션이종료된후, #3 번코드에서는 Detached 상태의 fstmovie 객체의 title 변경 3. 세번째트랜잭션내의 #4 번코드에서는 scdmovie 객체의 title 변경, 세번째트랜잭션종료시변경사항이 DB 에반영 4. 네번째트랜잭션내에서 #3 번코드를통해변경된 fstmovie 객체에대해 update 수행 5. fstmovie 에대한수정작업또한성공적으로처리 결론적으로보면, MOVIE_ID 가 "MV-00001" 인 Movie 의 Title 은 "First : My Sassy Girl" 이되어앞서 scdmovie 에서요청했던수정작업은무시된것이다. 이러한현상을 Lost Update 라고하며, 이를해결하기위한방법은 3 가지가있다. 1. Last Commit Wins : Optimistic Locking 을수행하지않게되면기본적으로수행되는유형으로 2 개의트랜잭션모두성공적으로 commit 된다. 그러므로두번째 commit 은첫번째 commit 내용을덮어쓸수있다. 2. First Commit Wins : Optimistic Locking 을적용한유형으로첫번째 commit 만이성공적으로이루어지며, 두번째 commit 시에는 Error 를얻게된다. 71

75 Concurrency 3. Merge : 첫번째 commit 만이성공적으로이루어지며, 두번째 commit 시에는 Error 를얻게된다. 그러나 First Commit Wins 와는달리두번째 commit 을위한작업을처음부터다시하지않고개발자의선택에의해선택적으로변경될수있도록한다. 가장좋은전략이나변경사항을 merge 할수있는화면이나방법을직접제공해줄수있어야한다.( 추가구현필요함 ) Hibernate 에서는 Versioning 기반의 Automatic Optimistic Locking 을통해 First Commit Wins 전략을취할수있도록지원한다. Hibernate 에서 Optimistic Locking 을수행하기위해서는해당테이블에 Version 또는 Timestamp 컬럼을추가해야한다. 그러한경우해당테이블과매핑된객체를로드할때 Version 또는 Timestamp 정보도함께로드되고객체수정시테이블의현재값과비교하여처리여부를결정하게된다. 다음은 Version 을이용하여 Optimistic Locking 을수행하는예제이다. Optimistic Locking 의대상이되는 Persistence Class 에 Version 관리를위한 int 유형의속성을정의하고, Hibernate Mapping XML 파일내의 <id> 태그다음에 <version> 을이용하여 Version 에대한매핑정보를정의하고있다. 1. Country.java public class Country implements java.io.serializable { private int version; private String countrycode; private String countryid; private String countryname; private Set movies = new HashSet(0); // Country.hbm.xml <class name="anyframe.sample.model.bidirection.concurrency.optimistic.country" table="country" lazy="true" schema="public"> <id name="countrycode" type="string"> <column name="country_code" length="12" /> <generator class="assigned" /> </id> <version name="version" access="field" column="country_version"/> </class> 이와같이정의된경우다음의 updatecountrywithoptimisticlocking() 메소드를수행하였을때첫번째수정작업은성공적으로이루어지나두번째수정작업에대해서는 #6 번코드에서처럼 StaleObjectStateException 이 throw 될것이다. 1. HibernateOptimisticLocking.java public void updatecountrywithoptimisticlocking() throws Exception { // 1. insert a new country, movies information newsession(); addcountrymovieatonce(); closesession(); // 2. select a country newsession(); /* #1 */ Country fstcountry = (Country) session.get(country.class, "COUNTRY-0001"); /* #2 */ Country scdcountry = (Country) session.get(country.class, 72

76 Concurrency "COUNTRY-0001"); closesession(); // 3. set country name /* #3 */ fstcountry.setcountryname("first : Republic of Korea."); // 4. select a country again with same id and update country name newsession(); /* #4 */ scdcountry.setcountryname("second : Republic of Korea."); closesession(); // 5. try to update with detached object newsession(); try { /* #5 */ session.update(fstcountry); closesession(); catch (Exception e) { e.printstacktrace(); Timestamp 사용은 Version 에비해안전하지않다. 일반적으로 JVM 이 Millisecond 단위의정확도를가지지않으므로 Timestamp 값으로동시제어를위한구분이어려울수있다. 이러한문제를해결하기위해 <timestamp> 내에해당컬럼에대한속성을 source="db" 와같이정의함으로써 Timestamp 값을 DB 에서가져오도록설정할수있으나이또한 Timestamp 값을얻어낼때마다 DB 에접속해야하는추가비용이발생하게된다. 이러한이유로 Hibernate 에서는 Timestamp 보다 Version 사용을권장한다. 이외에도 <class> 내에 optimistic-lock 속성의값을 "all" 또는 "dirtry" 로정의하면별도 Version 또는 Timestamp 컬럼에대한추가정의없이도 Optimistic Locking 이가능해진다. 그러나이또한성능, 복잡성과같은이유로권장하는방법은아니다. optimistic-lock="all" : 해당되는객체조회당시와비교하여변경되지않은속성들을해당객체를조회하기위한조건 (WHERE 절 ) 으로명시하여변경작업을시도함으로써 Optimistic Locking 적용. optimistic-lock="dirty" : 두트랜잭션에서동일한속성의값에대해변경을수행하였을경우에대해 Optimistic Locking 적용. 따라서, 두트랜잭션이서로다른속성의값을변경한경우에는해당되지않는다 Pessimistic Locking 동시접근제어를위해어플리케이션전체의 isolation level 을 read committed 이상으로높이는것은어플리케이션의확장성을고려할때그리추천하지않는다. 특정작업에대해 isolation 을보다잘보장해주는것이바람직하다. Hibernate 기반의 Pessimistic Locking 은다음과같은 Locking Mode 중, 개발자가정의한 Locking Mode 를이용하여특정트랜잭션에대해 Locking 을정의하는방식으로수행된다. LockMode.NONE : 기본값으로 Locking 이수행되지않으며캐쉬에객체가존재하면캐쉬내의객체를사용한다. LockMode.READ : Cache 가아닌현재트랜잭션에포함되어있는 DB 로부터데이터를읽어와서메모리상의객체와동일한것인지확인한다. LockMode.UPGRADE : 조회시 SELECT.. FOR UPDATE 와같은쿼리가수행되므로다른쓰레드에서동일한객체에접근하려고할때행단위로 Locking 한다. SELECT.. FOR UPDATE 기능을제공하는 DBMS 에한해지원된다. SELECT.. FOR UPDATE 문을지원하지않는 DB 를사용할때는 LockMode.READ 로전환된다. LockMode.UPGRADE_NOWAIT : 조회시오라클의 SELECT.. FOR UPDATE NO WAIT 와같은쿼리가수행되므로행단위로 Locking 을걸며, 다른쓰레드에서동일한객체에접근하려고할때 Blocking 73

77 Concurrency 되지않고바로 Exception 을발생시킨다. SELECT.. FOR UPDATE NO WAIT 를지원하지않으면 LockMode.UPGRADE 로전환된다. LockMode.FORCE : 현재트랜잭션에의해객체가수정되었음을인식할수있게하기위해 DB 내의객체버전을강제로증가시킨다. LockMode.WRITE : Hibernate 에의해현재트랜잭션에서행을추가했을때자동으로얻어진다. (Hibernate 내부에서사용하는 mode 로개발자가어플리케이션에서명시적으로사용하지않도록한다.) 위의그림을살펴보면, 클라이언트 1 과 2 는동일한데이터에접근하고있으며, 이때클라이언트 1 에서먼저 lock() 을걸었으므로그이후다른 Client 에서는클라이언트 1 의 lock 이해제될때까지해당데이터에접근할수없게된다. 즉, 클라이언트 1 의트랜잭션이종료되고난이후에야 lock 이해제되어다른 Client 에서해당데이터에접근할수있게되는것이다. 강력한 Locking 기법인 Pessimistic Locking 은데이터에대한접근이먼저이루어졌다하더라도수정작업을먼저반영하지않으면 Exception 이발생하는 Optimistic Locking 기법과는달리 lock 을보유한트랜잭션이종료될때까지다른트랜잭션의해당데이터에대한접근을막기때문에안전한데이터수정이가능해진다. 다음에서는 Pessimistic Locking 수행을테스트하기위한예제코드 HibernatePessimisticLocking 를이용하여, LockMode.NONE, LockMode.UPGRADE, LockMode.UPGRADE_NOWAIT 에대해상세히비교해보고자한다. 하나의객체에대한동시접근을실현하기위해다음과같은 Thread 가구현되었으며모든테스트메소드에서는두번째 Thread 에 sleeptime 을줌으로써, 첫번째 Thread 를명시적으로먼저 start 시켜하나의객체에대해첫번째 Thread 에서먼저접근할수있도록강제하고있다. 또한첫번째 Thread 의변경사항을 DB 에반영하기전에는 sleep 시켜첫번째 Thread 에의한변경사항반영을지연시킨다. public class CountryThread extends Thread { public void run() { try { Session session = initialsessionfactory.opensession(); session.begintransaction(); Country country = (Country) session.get(country.class, "COUNTRY-0001", this.lockmode); this.beforecountryname = country.getcountryname(); country.setcountryname(id + " : Republic of Korea"); this.sleep(sleeptime); session.flush(); country = (Country) session.get(country.class, "COUNTRY-0001"); 74

78 Concurrency this.aftercountryname = country.getcountryname(); session.gettransaction().commit(); session.close(); catch (Exception e) { if (this.lockmode == LockMode.UPGRADE_NOWAIT && id.equals("second")) { e instanceof LockAcquisitionException); //... LockMode.NONE 인경우 : 첫번째 Thread 를통해먼저 select... 문이수행되나 LockMode.NONE 이므로, Lock 이걸리지는않는다. 그리고첫번째 Thread 에서는 session.flush() 를수행하기전에주어진시간만큼 sleep() 하게되므로, 뒤이어시작한두번째 Thread 에서 select 를수행한후, 바로수정작업을 commit 한다. 첫번째 Thread 에서는주어진시간만큼 sleep() 한후, 두번째 Thread 의변경내용을무시하고수정작업을 commit 하게된다. 즉, LockMode.NONE 일경우에는 Pessimistic Locking 이수행되지않음을알수있다. LockMode.UPGRADE 인경우 : 첫번째 Thread 를통해먼저 select... for update 문이수행되면서해당 Row 에 Lock 이생긴다. 그리고첫번째 Thread 에서는 session.flush() 를수행하기전에주어진시간만큼 sleep() 하게되므로뒤이은두번째 Thread 에서는첫번째 Thread 의 update 작업이완료될때까지 blocking 되어있다가첫번째 Thread 에서변경한값을기반으로하여수정작업을 commit 한다. LockMode.UPGRADE_NOWAIT 인경우 : 첫번째 Thread 를통해먼저 select... for update nowait 문이수행되면서해당 Row 에 Lock 이생긴다. 그리고첫번째 Thread 에서는 session.flush() 를수행하기전에주어진시간만큼 sleep() 하게되며, 뒤이은두번째 Thread 에서 select... for update nowait 를시도하면 blocking 없이바로 LockAcquisitionException 이 throw 되면서두번째 Thread 를통한수정작업은이루어지지않게된다 Offline Locking 지금까지는한트랜잭션내에서의동시접근처리기법에대해알아보았다. Offline Locking 에서는여러개의트랜잭션을통해하나의작업이이루어져야하는경우에서의동시접근처리기법에대해살펴보기로하자. 웹어플리케이션의일반적인화면구성을가정해보자. 상영중인영화목록을제공하는웹어플리케이션에서특정영화정보를수정하는작업을수행하기위해서는먼저선택된영화정보조회가이루어지고, 수정작업이뒤따라야한다. 즉, 2 개의트랜잭션수행을통해원하는작업을수행할수있게되는것이다. 동시사용자가이러한작업을수행한다고했을때, 동시제어가제대로이루어지지않으면어느한사용자의작업정보는손실될가능성이존재하게된다. 이와같이여러트랜잭션을통해이루어지는작업에서동시접근제어를수행하기위해서는다음과같은작업이필요하다. Offline Optimistic Locking : Optimistic Locking 과동일하게 Version 을사용하는방법이다. 첫번째트랜잭션을통해얻어온 Detached 상태의객체 (version 정보포함하고있음.) 를 HTTP 세션에저장해둔다. 사용자가수정작업반영을요청하면 HTTP 세션에저장된 Detached 객체를꺼내수정된정보로셋팅하고두번째트랜잭션에서 session.update() 메소드호출시입력인자로전달한다. 이렇게하면 Optimistic Locking 과유사하게 Version 정보를기반으로동시접근을제어할수있게된다. Offline Pessimistic Locking : Pessimistic Locking 과동일한동작원리를가지면서 DB 레벨이아닌어플리케이션레벨에서 Locking 을관리할수있는별도의 LockManager 구현이필요하다. 75

79 11.Transaction Management Hibernate 에서지원하는 Transaction 관리방법에는크게 JDBC, JTA, CMT 세가지가있다. 본페이지에서는일반적으로가장많이사용하는 JDBC, JTA 기반의 Transaction 관리방법에대해서설명하겠다 JDBC - HibernateTransactionManager HibernateTransactionManager 는 DataSource 를사용하여 Local Transaction 과 Hibernate Session 을관리한다. 따라서 HibernateTransactionManager 는 LocalSessionFactory Bean 에의존성을가지고있으므로반드시 LocalSessionFactory 와함께사용되어야한다. Configuration 다음은 Spring Framework 의 org.springframework.orm.hibernate3.hibernatetransactionmanager 를이용하여 Hibernate 기반에서 Transaction 을관리하기위한 context-transaction.xml 파일의일부이다. <bean id="transactionmanager" class="org.springframework.orm.hibernate3.hibernatetransactionmanager"> <property name="sessionfactory" ref="sessionfactory" /> </bean> Spring 의 TransactionManager 설정방법에대해서는본매뉴얼 >> Foundation Plugin >> Spring >> Transaction Management [ reference/htmlsingle/foundation.html#foundation_spring_transaction] 를참고한다. Test Case 다음은 org.springframework.orm.hibernate3.hibernatetransactionmanager 를이용하여 Transaction 관리기능을테스트하기위한 HibernateJDBCTransactionManager.java 의일부이다. public class HibernateJDBCTransactionManager { <!-- 중략 --> /** * [Flow #-1] HibernateTransactionManager Rollback 을이용하여, * 초기화데이터의입력작업을취소시킨후, 데이터가제대로 Rollback 되었는지검증한다. * Exception * throws exception which is from hibernate */ public void rollback() throws Exception { // 1. insert init data Session session = sessionfactory.getcurrentsession(); SetUpInitData.initializeData(session); // 2. rollback transaction isrollback(); endtransaction(); // 3. begin a new transaction startnewtransaction(); // 4. check if insertion is rollbacked Movie movie = (Movie) sessionfactory.getcurrentsession().get( Movie.class, "MV-00001"); 76

80 Transaction Management /** * [Flow #-2] HibernateTransactionManager Commit 을이용하여, 초기화 * 데이터의입력작업을 DB 에반영시킨후, 데이터가제대로 Commit 되었는지검증한다. * Exception * throws exception which is from hibernate */ public void commit() throws Exception { // 1. insert init data Session session = sessionfactory.getcurrentsession(); SetUpInitData.initializeData(session); // 2. commit transaction setcomplete(); endtransaction(); // 3. begin a new transaction startnewtransaction(); // 4. check if insertion is successful Movie movie = (Movie) sessionfactory.getcurrentsession().get( Movie.class, "MV-00001"); 11.2.JTA - JTATransactionManager JTATransactionManager 서비스는 JTA 를사용한 Global Transaction 관리부분을추상화하여해당서비스가 JTA,JNDI 등에종속적이지않게구현가능하도록도와준다. Configuration 아래는 JTATransactionManager 의속성을정의한 context-transaction.xml 파일의일부이다. <bean id="transactionmanager" class="org.springframework.transaction.jta.weblogicjtatransactionmanager"/> 위에서볼수있듯이 Hibernate 기반에서 JTA Transaction 관리는 SpringJDBC 를사용할때와다르지않다. 상세한속성정의방법에대해서는 JTA Transaction Service [ reference/htmlsingle/foundation.html#foundation_spring_transaction] 를참고한다. Test Case 다음은 WebLogicJtaTransactionManager 를이용해 Transaction 관리기능을테스트하는 HibernateJTATransactionManager. java 의일부이다. public class HibernateJTATransactionManager { /** * [Flow #-1] WebLogicJtaTransactionManager Rollback 을이용하여, * 초기화데이터의입력작업을취소시킨후, 데이터가제대로 Rollback 되었는지검증한다. * Exception * throws exception which is from hibernate */ public void rollback() throws Exception { // 1. insert init data 77

81 Transaction Management Session session = sessionfactory.getcurrentsession(); SetUpInitData.initializeData(session); // 2. rollback transaction isrollback(); endtransaction(); // 3. begin a new transaction startnewtransaction(); // 4. check if insertion is rollbacked Movie movie = (Movie) sessionfactory.getcurrentsession().get( Movie.class, "MV-00001"); /** * [Flow #-2] WebLogicJtaTransactionManager Commit 을이용하여, * 초기화데이터의입력작업을 DB 에반영시킨후, 데이터가제대로 Commit 되었는지검증한다. * Exception * throws exception which is from hibernate */ public void commit() throws Exception { // 1. insert init data Session session = sessionfactory.getcurrentsession(); SetUpInitData.initializeData(session); // 2. commit transaction setcomplete(); endtransaction(); // 3. begin a new transaction startnewtransaction(); // 4. check if insertion is successful Movie movie = (Movie) sessionfactory.getcurrentsession().get( Movie.class, "MV-00001"); 78

82 12.Spring Integration Spring 에서는 Hibernate 기반에서 DAO 클래스를쉽게구현할수있도록하기위해 HibernateTemplate 을제공하고있다. ( Spring 2.5 부터는 Hibernate 3 버전을지원한다.) 또한, Anyframe 에서는 Veloticy 문법을이용하여 Dynamic HQL, Dynamic Native SQL 문을처리하기위해서 DynamicHibernateService 를제공한다. Hibernate 을이용하여데이터액세스처리를수행하는경우하나의비즈니스서비스를구성하는요소들은일반적으로다음과같이구성될수있다. Spring 기반에서 Hibernate 을통해데이터액세스처리를수행하기위해서는다음과같은절차에따라비즈니스서비스를개발할수있다 Hibernate 속성정의파일작성 Hibernate 을 Spring 과연계하기위해서는 SessionFactory 설정이필요하다. 또한, Dynamic HQL, Dynamic Native SQL 실행을위해서는 Anyframe 에서제공하는 DynamicHibernateService 에대한설정도필요하다 Session Factory 속성정의 Spring 에서제공하는 HibernateDaoSupport 는내부적으로 Hibernate 연계를위해 HibernateTemplate 을생성하는데이클래스는 SessionFactory 를필요로한다. 이를위해 HibernateDaoSupport 를상속받은클래스들은 SessionFactory 를필요로하며, SessionFactory 는다음과같은속성정보를가질수있다. 다음은 SessionFactory 의속성을정의한 context-hibernate.xml 파일의일부이다. <bean id="sessionfactory" class="org.springframework.orm.hibernate3.localsessionfactorybean"> <!-- SessionFactory 에서사용할 datasource 정의 --> 79

- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean" p:persistenceunitname=

- JPA를사용하는경우의스프링설정파일에다음을기술한다. <bean id=entitymanagerfactory class=org.springframework.orm.jpa.localentitymanagerfactorybean p:persistenceunitname= JPA 와 Hibernate - 스프링의 JDBC 대신에 JPA를이용한 DB 데이터검색작업 - JPA(Java Persistence API) 는자바의 O/R 매핑에대한표준지침이며, 이지침에따라설계된소프트웨어를 O/R 매핑프레임워크 라고한다. - O/R 매핑 : 객체지향개념인자바와관계개념인 DB 테이블간에상호대응을시켜준다. 즉, 객체지향언어의인스턴스와관계데이터베이스의레코드를상호대응시킨다.

More information

Spring Boot/JDBC JdbcTemplate/CRUD 예제

Spring Boot/JDBC JdbcTemplate/CRUD 예제 Spring Boot/JDBC JdbcTemplate/CRUD 예제 오라클자바커뮤니티 (ojc.asia, ojcedu.com) Spring Boot, Gradle 과오픈소스인 MariaDB 를이용해서 EMP 테이블을만들고 JdbcTemplate, SimpleJdbcTemplate 을이용하여 CRUD 기능을구현해보자. 마리아 DB 설치는다음 URL 에서확인하자.

More information

@OneToOne(cascade = = "addr_id") private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a

@OneToOne(cascade = = addr_id) private Addr addr; public Emp(String ename, Addr addr) { this.ename = ename; this.a 1 대 1 단방향, 주테이블에외래키실습 http://ojcedu.com, http://ojc.asia STS -> Spring Stater Project name : onetoone-1 SQL : JPA, MySQL 선택 http://ojc.asia/bbs/board.php?bo_table=lecspring&wr_id=524 ( 마리아 DB 설치는위 URL

More information

Spring Data JPA Many To Many 양방향 관계 예제

Spring Data JPA Many To Many 양방향 관계 예제 Spring Data JPA Many To Many 양방향관계예제 오라클자바커뮤니티 (ojc.asia, ojcedu.com) 엔티티매핑 (Entity Mapping) M : N 연관관계 사원 (Sawon), 취미 (Hobby) 는다 : 다관계이다. 사원은여러취미를가질수있고, 하나의취미역시여러사원에할당될수있기때문이다. 보통관계형 DB 에서는다 : 다관계는 1

More information

강의 개요

강의 개요 DDL TABLE 을만들자 웹데이터베이스 TABLE 자료가저장되는공간 문자자료의경우 DB 생성시지정한 Character Set 대로저장 Table 생성시 Table 의구조를결정짓는열속성지정 열 (Clumn, Attribute) 은이름과자료형을갖는다. 자료형 : http://dev.mysql.cm/dc/refman/5.1/en/data-types.html TABLE

More information

10.ppt

10.ppt : SQL. SQL Plus. JDBC. SQL >> SQL create table : CREATE TABLE ( ( ), ( ),.. ) SQL >> SQL create table : id username dept birth email id username dept birth email CREATE TABLE member ( id NUMBER NOT NULL

More information

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4

목차 BUG DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4 ALTIBASE HDB 6.5.1.5.10 Patch Notes 목차 BUG-46183 DEQUEUE 의 WAIT TIME 이 1 초미만인경우, 설정한시간만큼대기하지않는문제가있습니다... 3 BUG-46249 [qp-select-pvo] group by 표현식에있는컬럼을참조하는집합연산이존재하지않으면결괏값오류가발생할수있습니다... 4 BUG-46266 [sm]

More information

1

1 1 1....6 1.1...6 2. Java Architecture...7 2.1 2SDK(Software Development Kit)...8 2.2 JRE(Java Runtime Environment)...9 2.3 (Java Virtual Machine, JVM)...10 2.4 JVM...11 2.5 (runtime)jvm...12 2.5.1 2.5.2

More information

교육2 ? 그림

교육2 ? 그림 Interstage 5 Apworks EJB Application Internet Revision History Edition Date Author Reviewed by Remarks 1 2002/10/11 2 2003/05/19 3 2003/06/18 EJB 4 2003/09/25 Apworks5.1 [ Stateless Session Bean ] ApworksJava,

More information

쉽게 풀어쓴 C 프로그래밊

쉽게 풀어쓴 C 프로그래밊 Power Java 제 27 장데이터베이스 프로그래밍 이번장에서학습할내용 자바와데이터베이스 데이터베이스의기초 SQL JDBC 를이용한프로그래밍 변경가능한결과집합 자바를통하여데이터베이스를사용하는방법을학습합니다. 자바와데이터베이스 JDBC(Java Database Connectivity) 는자바 API 의하나로서데이터베이스에연결하여서데이터베이스안의데이터에대하여검색하고데이터를변경할수있게한다.

More information

PowerPoint Presentation

PowerPoint Presentation Package Class 1 Heeseung Jo 목차 section 1 패키지개요와패키지의사용 section 2 java.lang 패키지의개요 section 3 Object 클래스 section 4 포장 (Wrapper) 클래스 section 5 문자열의개요 section 6 String 클래스 section 7 StringBuffer 클래스 section

More information

PowerPoint Presentation

PowerPoint Presentation Class - Property Jo, Heeseung 목차 section 1 클래스의일반구조 section 2 클래스선언 section 3 객체의생성 section 4 멤버변수 4-1 객체변수 4-2 클래스변수 4-3 종단 (final) 변수 4-4 멤버변수접근방법 section 5 멤버변수접근한정자 5-1 public 5-2 private 5-3 한정자없음

More information

MySQL-.. 1

MySQL-.. 1 MySQL- 기초 1 Jinseog Kim Dongguk University jinseog.kim@gmail.com 2017-08-25 Jinseog Kim Dongguk University jinseog.kim@gmail.com MySQL-기초 1 2017-08-25 1 / 18 SQL의 기초 SQL은 아래의 용도로 구성됨 데이터정의 언어(Data definition

More information

DBMS & SQL Server Installation Database Laboratory

DBMS & SQL Server Installation Database Laboratory DBMS & 조교 _ 최윤영 } 데이터베이스연구실 (1314 호 ) } 문의사항은 cyy@hallym.ac.kr } 과제제출은 dbcyy1@gmail.com } 수업공지사항및자료는모두홈페이지에서확인 } dblab.hallym.ac.kr } 홈페이지 ID: 학번 } 홈페이지 PW:s123 2 차례 } } 설치전점검사항 } 설치단계별설명 3 Hallym Univ.

More information

교육자료

교육자료 THE SYS4U DODUMENT Java Reflection & Introspection 2012.08.21 김진아사원 2012 SYS4U I&C All rights reserved. 목차 I. 개념 1. Reflection 이란? 2. Introspection 이란? 3. Reflection 과 Introspection 의차이점 II. 실제사용예 1. Instance의생성

More information

슬라이드 1

슬라이드 1 Tadpole for DB 1. 도구개요 2. 설치및실행 4. 활용예제 1. 도구개요 도구명 소개 Tadpole for DB Tools (sites.google.com/site/tadpolefordb/) 웹기반의데이터베이스를관리하는도구 Database 스키마및데이터관리 라이선스 LGPL (Lesser General Public License) 특징 주요기능

More information

No Slide Title

No Slide Title J2EE J2EE(Java 2 Enterprise Edition) (Web Services) :,, SOAP: Simple Object Access Protocol WSDL: Web Service Description Language UDDI: Universal Discovery, Description & Integration 4. (XML Protocol

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 @ Lesson 2... ( ). ( ). @ vs. logic data method variable behavior attribute method field Flow (Type), ( ) member @ () : C program Method A ( ) Method B ( ) Method C () program : Java, C++, C# data @ Program

More information

InsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins

InsertColumnNonNullableError(#colName) 에해당하는메시지출력 존재하지않는컬럼에값을삽입하려고할경우, InsertColumnExistenceError(#colName) 에해당하는메시지출력 실행결과가 primary key 제약에위배된다면, Ins Project 1-3: Implementing DML Due: 2015/11/11 (Wed), 11:59 PM 이번프로젝트의목표는프로젝트 1-1 및프로젝트 1-2에서구현한프로그램에기능을추가하여간단한 DML을처리할수있도록하는것이다. 구현한프로그램은 3개의 DML 구문 (insert, delete, select) 을처리할수있어야한다. 테이블데이터는파일에저장되어프로그램이종료되어도사라지지않아야한다.

More information

C# Programming Guide - Types

C# Programming Guide - Types C# Programming Guide - Types 최도경 lifeisforu@wemade.com 이문서는 MSDN 의 Types 를요약하고보충한것입니다. http://msdn.microsoft.com/enus/library/ms173104(v=vs.100).aspx Types, Variables, and Values C# 은 type 에민감한언어이다. 모든

More information

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET

Connection 8 22 UniSQLConnection / / 9 3 UniSQL OID SET 135-080 679-4 13 02-3430-1200 1 2 11 2 12 2 2 8 21 Connection 8 22 UniSQLConnection 8 23 8 24 / / 9 3 UniSQL 11 31 OID 11 311 11 312 14 313 16 314 17 32 SET 19 321 20 322 23 323 24 33 GLO 26 331 GLO 26

More information

목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE

목차 BUG 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG ROLLUP/CUBE 절을포함하는질의는 SUBQUE ALTIBASE HDB 6.3.1.10.1 Patch Notes 목차 BUG-45710 문법에맞지않는질의문수행시, 에러메시지에질의문의일부만보여주는문제를수정합니다... 3 BUG-45730 ROUND, TRUNC 함수에서 DATE 포맷 IW 를추가지원합니다... 5 BUG-45760 ROLLUP/CUBE 절을포함하는질의는 SUBQUERY REMOVAL 변환을수행하지않도록수정합니다....

More information

Spring Boot

Spring Boot 스프링부트 (Spring Boot) 1. 스프링부트 (Spring Boot)... 2 1-1. Spring Boot 소개... 2 1-2. Spring Boot & Maven... 2 1-3. Spring Boot & Gradle... 3 1-4. Writing the code(spring Boot main)... 4 1-5. Writing the code(commandlinerunner)...

More information

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f

* Factory class for query and DML clause creation * tiwe * */ public class JPAQueryFactory implements JPQLQueryFactory private f JPA 에서 QueryDSL 사용하기위해 JPAQuery 인스턴스생성방법 http://ojc.asia, http://ojcedu.com 1. JPAQuery 를직접생성하기 JPAQuery 인스턴스생성하기 QueryDSL의 JPAQuery API를사용하려면 JPAQuery 인스턴스를생성하면된다. // entitymanager는 JPA의 EntityManage

More information

untitled

untitled (shared) (integrated) (stored) (operational) (data) : (DBMS) :, (database) :DBMS File & Database - : - : ( : ) - : - : - :, - DB - - -DBMScatalog meta-data -DBMS -DBMS - -DBMS concurrency control E-R,

More information

07 자바의 다양한 클래스.key

07 자바의 다양한 클래스.key [ 07 ] . java.lang Object, Math, String, StringBuffer Byte, Short, Integer, Long, Float, Double, Boolean, Character. java.util Random, StringTokenizer Calendar, GregorianCalendar, Date. Collection, List,

More information

02 C h a p t e r Java

02 C h a p t e r Java 02 C h a p t e r Java Bioinformatics in J a va,, 2 1,,,, C++, Python, (Java),,, (http://wwwbiojavaorg),, 13, 3D GUI,,, (Java programming language) (Sun Microsystems) 1995 1990 (green project) TV 22 CHAPTER

More information

ALTIBASE 사용자가이드 Templete

ALTIBASE 사용자가이드 Templete Real Alternative DBMS ALTIBASE, Since 1999 Hibernate 연동가이드 2014.01 Copyright c 2000~2010 ALTIBASE Corporation. All Rights Reserved. Document Control Change Record Date Author Change Reference 2010-11 snkim

More information

JAVA PROGRAMMING 실습 08.다형성

JAVA PROGRAMMING 실습 08.다형성 2015 학년도 2 학기 1. 추상메소드 선언은되어있으나코드구현되어있지않은메소드 abstract 키워드사용 메소드타입, 이름, 매개변수리스트만선언 public abstract String getname(); public abstract void setname(string s); 2. 추상클래스 abstract 키워드로선언한클래스 종류 추상메소드를포함하는클래스

More information

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인

표준프레임워크로 구성된 컨텐츠를 솔루션에 적용하는 것에 문제가 없는지 확인 표준프레임워크로구성된컨텐츠를솔루션에적용하는것에문제가없는지확인 ( S next -> generate example -> finish). 2. 표준프레임워크개발환경에솔루션프로젝트추가. ( File -> Import -> Existring Projects into

More information

Data Sync Manager(DSM) Example Guide Data Sync Manager (DSM) Example Guide DSM Copyright 2003 Ari System, Inc. All Rights reserved. Data Sync Manager

Data Sync Manager(DSM) Example Guide Data Sync Manager (DSM) Example Guide DSM Copyright 2003 Ari System, Inc. All Rights reserved. Data Sync Manager Data Sync Manager (DSM) Example Guide DSM Copyright 2003 Ari System, Inc. All Rights reserved. Data Sync Manager are trademarks or registered trademarks of Ari System, Inc. 1 Table of Contents Chapter1

More information

thesis

thesis ( Design and Implementation of a Generalized Management Information Repository Service for Network and System Management ) ssp@nile nile.postech.ac..ac.kr DPE Lab. 1997 12 16 GMIRS GMIRS GMIRS prototype

More information

01-OOPConcepts(2).PDF

01-OOPConcepts(2).PDF Object-Oriented Programming Concepts Tel: 02-824-5768 E-mail: hhcho@selabsoongsilackr? OOP (Object) (Encapsulation) (Message) (Class) (Inheritance) (Polymorphism) (Abstract Class) (Interface) 2 1 + = (Dependency)

More information

JVM 메모리구조

JVM 메모리구조 조명이정도면괜찮조! 주제 JVM 메모리구조 설미라자료조사, 자료작성, PPT 작성, 보고서작성. 발표. 조장. 최지성자료조사, 자료작성, PPT 작성, 보고서작성. 발표. 조원 이용열자료조사, 자료작성, PPT 작성, 보고서작성. 이윤경 자료조사, 자료작성, PPT작성, 보고서작성. 이수은 자료조사, 자료작성, PPT작성, 보고서작성. 발표일 2013. 05.

More information

WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역

WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역 WINDOW FUNCTION 의이해와활용방법 엑셈컨설팅본부 / DB 컨설팅팀정동기 개요 Window Function 이란행과행간의관계를쉽게정의할수있도록만든함수이다. 윈도우함수를활용하면복잡한 SQL 들을하나의 SQL 문장으로변경할수있으며반복적으로 ACCESS 하는비효율역시쉽게해결할수있다. 이번화이트페이퍼에서는 Window Function 중순위 RANK, ROW_NUMBER,

More information

untitled

untitled PowerBuilder 連 Microsoft SQL Server database PB10.0 PB9.0 若 Microsoft SQL Server 料 database Profile MSS 料 (Microsoft SQL Server database interface) 行了 PB10.0 了 Sybase 不 Microsoft 料 了 SQL Server 料 PB10.0

More information

Intro to Servlet, EJB, JSP, WS

Intro to Servlet, EJB, JSP, WS ! Introduction to J2EE (2) - EJB, Web Services J2EE iseminar.. 1544-3355 ( ) iseminar Chat. 1 Who Are We? Business Solutions Consultant Oracle Application Server 10g Business Solutions Consultant Oracle10g

More information

adfasdfasfdasfasfadf

adfasdfasfdasfasfadf C 4.5 Source code Pt.3 ISL / 강한솔 2019-04-10 Index Tree structure Build.h Tree.h St-thresh.h 2 Tree structure *Concpets : Node, Branch, Leaf, Subtree, Attribute, Attribute Value, Class Play, Don't Play.

More information

JUNIT 실습및발표

JUNIT 실습및발표 JUNIT 실습및발표 JUNIT 접속 www.junit.org DownLoad JUnit JavaDoc API Document 를참조 JUNIT 4.8.1 다운로드 설치파일 (jar 파일 ) 을다운로드 CLASSPATH 를설정 환경변수에서설정 실행할클래스에서 import JUnit 설치하기 테스트실행주석 @Test Test 를실행할 method 앞에붙임 expected

More information

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일

Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 11 년 10 월 26 일수요일 Eclipse 와 Firefox 를이용한 Javascript 개발 발표자 : 문경대 Introduce Me!!! Job Jeju National University Student Ubuntu Korean Jeju Community Owner E-Mail: ned3y2k@hanmail.net Blog: http://ned3y2k.wo.tc Facebook: http://www.facebook.com/gyeongdae

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 @ Lesson 1,..... @ 1 Green Project 1991 Oak Java 1995. 5 December '90 by Patrick Naughton, Mike Sheridan and James Gosling Embedded in various consumer electronic device 1992. 9. 3 Star 7 1993 www portability

More information

윈도우시스템프로그래밍

윈도우시스템프로그래밍 데이터베이스및설계 MySQL 을위한 MFC 를사용한 ODBC 프로그래밍 2012.05.10. 오병우 컴퓨터공학과금오공과대학교 http://www.apmsetup.com 또는 http://www.mysql.com APM Setup 설치발표자료참조 Department of Computer Engineering 2 DB 에속한테이블보기 show tables; 에러발생

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 System Software Experiment 1 Lecture 5 - Array Spring 2019 Hwansoo Han (hhan@skku.edu) Advanced Research on Compilers and Systems, ARCS LAB Sungkyunkwan University http://arcs.skku.edu/ 1 배열 (Array) 동일한타입의데이터가여러개저장되어있는저장장소

More information

Microsoft PowerPoint - 10Àå.ppt

Microsoft PowerPoint - 10Àå.ppt 10 장. DB 서버구축및운영 DBMS 의개념과용어를익힌다. 간단한 SQL 문법을학습한다. MySQL 서버를설치 / 운영한다. 관련용어 데이터 : 자료 테이블 : 데이터를표형식으로표현 레코드 : 테이블의행 필드또는컬럼 : 테이블의열 필드명 : 각필드의이름 데이터타입 : 각필드에입력할값의형식 학번이름주소연락처 관련용어 DB : 테이블의집합 DBMS : DB 들을관리하는소프트웨어

More information

I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r

I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r I T C o t e n s P r o v i d e r h t t p : / / w w w. h a n b i t b o o k. c o. k r Jakarta is a Project of the Apache

More information

Microsoft Word - src.doc

Microsoft Word - src.doc IPTV 서비스탐색및콘텐츠가이드 RI 시스템운용매뉴얼 목차 1. 서버설정방법... 5 1.1. 서비스탐색서버설정... 5 1.2. 컨텐츠가이드서버설정... 6 2. 서버운용방법... 7 2.1. 서비스탐색서버운용... 7 2.1.1. 서비스가이드서버실행... 7 2.1.2. 서비스가이드정보확인... 8 2.1.3. 서비스가이드정보추가... 9 2.1.4. 서비스가이드정보삭제...

More information

PowerPoint Template

PowerPoint Template JavaScript 회원정보 입력양식만들기 HTML & JavaScript Contents 1. Form 객체 2. 일반적인입력양식 3. 선택입력양식 4. 회원정보입력양식만들기 2 Form 객체 Form 객체 입력양식의틀이되는 태그에접근할수있도록지원 Document 객체의하위에위치 속성들은모두 태그의속성들의정보에관련된것

More information

<session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.oracledriver</property> <property name="hibernate.connection.u

<session-factory> <property name=hibernate.connection.driver_class>oracle.jdbc.driver.oracledriver</property> <property name=hibernate.connection.u JBoss Hibernate Tools 를이용한 Entity 코드생성하기 OOP 개발교육의중심오라클자바커뮤니티 http://ojc.asia DDL 코드가작성되어있거나운영중인서비스를업그레이드하는경우에는 ORM 개발이라고하더라도 Top-down 방식의 개발방법론만을고집하지말고때에따라서는전통적인방식의접근이편리할것이다. 데이터베이스의이미존재하는테이블을바탕으로리버스엔지니어링을통해

More information

DocsPin_Korean.pages

DocsPin_Korean.pages Unity Localize Script Service, Page 1 Unity Localize Script Service Introduction Application Game. Unity. Google Drive Unity.. Application Game. -? ( ) -? -?.. 준비사항 Google Drive. Google Drive.,.. - Google

More information

문서 템플릿

문서 템플릿 HDSI 툴분석 [sql injection 기술명세서 ] Sql injection 기술명세서 Ver. 0.01 이문서는 sql injection 기술명세가범위입니다. Copyrights Copyright 2009 by CanvasTeam@SpeeDroot( 장경칩 ) All Rights Reserved. 장경칩의사전승인없이본내용의전부또는일부에대한복사, 전재,

More information

PowerPoint Presentation

PowerPoint Presentation public class SumTest { public static void main(string a1[]) { int a, b, sum; a = Integer.parseInt(a1[0]); b = Integer.parseInt(a1[1]); sum = a + b ; // 두수를더하는부분입니다 System.out.println(" 두수의합은 " + sum +

More information

제11장 프로세스와 쓰레드

제11장 프로세스와 쓰레드 제9장자바쓰레드 9.1 Thread 기초 (1/5) 프로그램 명령어들의연속 (a sequence of instruction) 프로세스 / Thread 실행중인프로그램 (program in execution) 프로세스생성과실행을위한함수들 자바 Thread 2 9.1 Thread 기초 (2/5) 프로세스단위작업의문제점 프로세스생성시오버헤드 컨텍스트스위치오버헤드

More information

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate

목차 BUG offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate ALTIBASE HDB 6.1.1.5.6 Patch Notes 목차 BUG-39240 offline replicator 에서유효하지않은로그를읽을경우비정상종료할수있다... 3 BUG-41443 각 partition 이서로다른 tablespace 를가지고, column type 이 CLOB 이며, 해당 table 을 truncate 한뒤, hash partition

More information

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O

ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE (Online Upgrade) ORANGE CONFIGURATION ADMIN O Orange for ORACLE V4.0 Installation Guide ORANGE FOR ORACLE V4.0 INSTALLATION GUIDE...1 1....2 1.1...2 1.2...2 1.2.1...2 1.2.2 (Online Upgrade)...11 1.3 ORANGE CONFIGURATION ADMIN...12 1.3.1 Orange Configuration

More information

Chap7.PDF

Chap7.PDF Chapter 7 The SUN Intranet Data Warehouse: Architecture and Tools All rights reserved 1 Intranet Data Warehouse : Distributed Networking Computing Peer-to-peer Peer-to-peer:,. C/S Microsoft ActiveX DCOM(Distributed

More information

FileMaker 15 ODBC 및 JDBC 설명서

FileMaker 15 ODBC 및 JDBC 설명서 FileMaker 15 ODBC JDBC 2004-2016 FileMaker, Inc.. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker FileMaker Go FileMaker, Inc.. FileMaker WebDirect FileMaker, Inc... FileMaker.

More information

개발문서 Oracle - Clob

개발문서 Oracle - Clob 개발문서 ORACLE CLOB 2008.6.9 ( 주 ) 아이캔매니지먼트 개발팀황순규 0. clob개요 1. lob과 long의비교와 clob와 blob 2. 테이블생성쿼리 ( 차이점-추가사항 ) 3. select 쿼리 4. insert 쿼리및 jdbc프로그래밍 5. update 쿼리및 jdbc프로그래밍 (4, 5). putclobdata() 클래스 6. select

More information

Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Cras

Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Cras Analytics > Log & Crash Search > Unity ios SDK [Deprecated] Log & Crash Unity ios SDK. TOAST SDK. Log & Crash Unity SDK Log & Crash Search. Log & Crash Unity SDK... Log & Crash Search. - Unity3D v4.0 ios

More information

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp");

다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) <% RequestDispatcher dispatcher = request.getrequestdispatcher( 실행할페이지.jsp); 다른 JSP 페이지호출 forward() 메서드 - 하나의 JSP 페이지실행이끝나고다른 JSP 페이지를호출할때사용한다. 예 ) RequestDispatcher dispatcher = request.getrequestdispatcher(" 실행할페이지.jsp"); dispatcher.forward(request, response); - 위의예에서와같이 RequestDispatcher

More information

FileMaker ODBC 및 JDBC 가이드

FileMaker ODBC 및 JDBC 가이드 FileMaker ODBC JDBC 2004-2019 FileMaker, Inc.. FileMaker, Inc. 5201 Patrick Henry Drive Santa Clara, California 95054 FileMaker, FileMaker Cloud, FileMaker Go FileMaker, Inc.. FileMaker WebDirect FileMaker,

More information

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2

q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2 객체지향프로그래밍 IT CookBook, 자바로배우는쉬운자료구조 q 이장에서다룰내용 1 객체지향프로그래밍의이해 2 객체지향언어 : 자바 2 q 객체지향프로그래밍의이해 v 프로그래밍기법의발달 A 군의사업발전 1 단계 구조적프로그래밍방식 3 q 객체지향프로그래밍의이해 A 군의사업발전 2 단계 객체지향프로그래밍방식 4 q 객체지향프로그래밍의이해 v 객체란무엇인가

More information

ALTIBASE HDB Patch Notes

ALTIBASE HDB Patch Notes ALTIBASE HDB 6.5.1.5.6 Patch Notes 목차 BUG-45643 암호화컬럼의경우, 이중화환경에서 DDL 수행시 Replication HandShake 가실패하는문제가있어수정하였습니다... 4 BUG-45652 이중화에서 Active Server 와 Standby Server 의 List Partition 테이블의범위조건이다른경우에 Handshake

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 @ Lesson 3 if, if else, if else if, switch case for, while, do while break, continue : System.in, args, JOptionPane for (,, ) @ vs. logic data method variable Data Data Flow (Type), ( ) @ Member field

More information

6장. SQL

6장. SQL 학습목표 SQL이 무엇인지 개념을 설명 테이블을 생성, 변경, 제거할 할 수 있다. 수 있다. 데이터를 검색, 갱신, 삽입, 삭 제할 수 있다. 뷰, 시스템 카탈로그, 저장 프 로시저, 트리거에 대한 개념 을 설명할 수 있다. 2 목차 SECTION 01 SQL의 개요 11 SQL의 역사 12 SQL의 유형별 종류 SECTION 0 21 스키마 22 테이블

More information

gnu-lee-oop-kor-lec06-3-chap7

gnu-lee-oop-kor-lec06-3-chap7 어서와 Java 는처음이지! 제 7 장상속 Super 키워드 상속과생성자 상속과다형성 서브클래스의객체가생성될때, 서브클래스의생성자만호출될까? 아니면수퍼클래스의생성자도호출되는가? class Base{ public Base(String msg) { System.out.println("Base() 생성자 "); ; class Derived extends Base

More information

13주-14주proc.PDF

13주-14주proc.PDF 12 : Pro*C/C++ 1 2 Embeded SQL 3 PRO *C 31 C/C++ PRO *C NOT! NOT AND && AND OR OR EQUAL == = SQL,,, Embeded SQL SQL 32 Pro*C C SQL Pro*C C, C Pro*C, C C 321, C char : char[n] : n int, short, long : float

More information

Hibernate############# Version: 2.1.6

Hibernate############# Version: 2.1.6 Hibernate############# Version: 2.1.6 eg/ lib/ etc/hibernate.properties ant eg build eg webapps/quickstart TOMCAT/common/lib webapps/quickstart/web-inf/lib webapps/quickstart/web-inf/classes pg73jdbc3.jar

More information

untitled

untitled Push... 2 Push... 4 Push... 5 Push... 13 Push... 15 1 FORCS Co., LTD A Leader of Enterprise e-business Solution Push (Daemon ), Push Push Observer. Push., Observer. Session. Thread Thread. Observer ID.

More information

Interstage5 SOAP서비스 설정 가이드

Interstage5 SOAP서비스 설정 가이드 Interstage 5 Application Server ( Solaris ) SOAP Service Internet Sample Test SOAP Server Application SOAP Client Application CORBA/SOAP Server Gateway CORBA/SOAP Gateway Client INTERSTAGE SOAP Service

More information

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx

Microsoft PowerPoint - chap02-C프로그램시작하기.pptx #include int main(void) { int num; printf( Please enter an integer "); scanf("%d", &num); if ( num < 0 ) printf("is negative.\n"); printf("num = %d\n", num); return 0; } 1 학습목표 을 작성하면서 C 프로그램의

More information

작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\)

작성자 : 김성박\(삼성 SDS 멀티캠퍼스 전임강사\) Session 을이용한현재로그인한사용자의 숫자구하기 작성자 : 김성박 ( 삼성 SDS 멀티캠퍼스전임강사 ) email : urstory@nownuri.net homepage : http://sunny.sarang.net - 본문서는http://sunny.sarang.net JAVA강좌란 혹은 http://www.javastudy.co.kr 의 칼럼 란에서만배포합니다.

More information

JDBC 소개및설치 Database Laboratory

JDBC 소개및설치 Database Laboratory JDBC 소개및설치 JDBC } What is the JDBC? } JAVA Database Connectivity 의약어 } 자바프로그램안에서 SQL 을실행하기위해데이터베이스를연결해주는응용프로그램인터페이스 } 연결된데이터베이스의종류와상관없이동일한방법으로자바가데이터베이스내에서발생하는트랜잭션을제어할수있도록하는환경을제공 2 JDBC Driver Manager }

More information

Business Agility () Dynamic ebusiness, RTE (Real-Time Enterprise) IT Web Services c c WE-SDS (Web Services Enabled SDS) SDS SDS Service-riented Architecture Web Services ( ) ( ) ( ) / c IT / Service- Service-

More information

I. Introduction... 1 II. Jdbc Support 구현배경 사용자요구사항 p6spy Architecture Architecture InjectionPa

I. Introduction... 1 II. Jdbc Support 구현배경 사용자요구사항 p6spy Architecture Architecture InjectionPa Anyframe Jdbc Support Plugin Version 1.1.0 저작권 2007-2014 삼성 SDS 본문서의저작권은삼성 SDS 에있으며 Anyframe 오픈소스커뮤니티활동의목적하에서자유로운이용이가능합니다. 본문서를복제, 배포할경우에는저작권자를명시하여주시기바라며본문서를변경하실경우에는원문과변경된내용을표시하여주시기바랍니다. 원문과변경된문서에대한상업적용도의활용은허용되지않습니다.

More information

Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터

Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터 Bind Peeking 한계에따른 Adaptive Cursor Sharing 등장 엑셈컨설팅본부 /DB 컨설팅팀김철환 Bind Peeking 의한계 SQL 이최초실행되면 3 단계의과정을거치게되는데 Parsing 단계를거쳐 Execute 하고 Fetch 의과정을통해데이터를사용자에게전송하게되며 Parsing 단계에서실행계획이생성된다. Bind 변수를사용하는 SQL

More information

PowerPoint Presentation

PowerPoint Presentation Package Class 3 Heeseung Jo 목차 section 1 패키지개요와패키지의사용 section 2 java.lang 패키지의개요 section 3 Object 클래스 section 4 포장 (Wrapper) 클래스 section 5 문자열의개요 section 6 String 클래스 section 7 StringBuffer 클래스 section

More information

슬라이드 1

슬라이드 1 Pairwise Tool & Pairwise Test NuSRS 200511305 김성규 200511306 김성훈 200614164 김효석 200611124 유성배 200518036 곡진화 2 PICT Pairwise Tool - PICT Microsoft 의 Command-line 기반의 Free Software www.pairwise.org 에서다운로드후설치

More information

소프트웨어공학 Tutorial #2: StarUML Eun Man Choi

소프트웨어공학 Tutorial #2: StarUML Eun Man Choi 소프트웨어공학 Tutorial #2: StarUML Eun Man Choi emchoi@dgu.ac.kr Contents l StarUML 개요 l StarUML 소개및특징 l 주요기능 l StarUML 화면소개 l StarUML 설치 l StarUML 다운 & 설치하기 l 연습 l 사용사례다이어그램그리기 l 클래스다이어그램그리기 l 순서다이어그램그리기 2

More information

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum

API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Docum API STORE 키발급및 API 사용가이드 Document Information 문서명 : API STORE 언어별 Client 사용가이드작성자 : 작성일 : 2012.11.23 업무영역 : 버전 : 1 st Draft. 서브시스템 : 문서번호 : 단계 : Document Distribution Copy Number Name(Role, Title) Date

More information

Web Application을 구성하는 패턴과 Spring ROO의 사례

Web Application을 구성하는 패턴과 Spring ROO의 사례 Spring Roo 와함께하는 쾌속웹개발 정상혁, KSUG (www.ksug.org) 목차 1. Tool 2. Demo 3. Application 1. Tool 1.1 개요 1.2 Command line shell 1.3 Round-trip 1.4 익숙한도우미들 1.1 개요 Text Based RAD Tool for Java Real Object Oriented의첫글자들

More information

USER GUIDE

USER GUIDE Solution Package Volume II DATABASE MIGRATION 2010. 1. 9. U.Tu System 1 U.Tu System SeeMAGMA SYSTEM 차 례 1. INPUT & OUTPUT DATABASE LAYOUT...2 2. IPO 중 VB DATA DEFINE 자동작성...4 3. DATABASE UNLOAD...6 4.

More information

Microsoft PowerPoint - 04-UDP Programming.ppt

Microsoft PowerPoint - 04-UDP Programming.ppt Chapter 4. UDP Dongwon Jeong djeong@kunsan.ac.kr http://ist.kunsan.ac.kr/ Dept. of Informatics & Statistics 목차 UDP 1 1 UDP 개념 자바 UDP 프로그램작성 클라이언트와서버모두 DatagramSocket 클래스로생성 상호간통신은 DatagramPacket 클래스를이용하여

More information

Microsoft PowerPoint - lec2.ppt

Microsoft PowerPoint - lec2.ppt 2008 학년도 1 학기 상지대학교컴퓨터정보공학부 고광만 강의내용 어휘구조 토큰 주석 자료형기본자료형 참조형배열, 열거형 2 어휘 (lexicon) 어휘구조와자료형 프로그램을구성하는최소기본단위토큰 (token) 이라부름문법적으로의미있는최소의단위컴파일과정의어휘분석단계에서처리 자료형 자료객체가갖는형 구조, 개념, 값, 연산자를정의 3 토큰 (token) 정의문법적으로의미있는최소의단위예,

More information

TITLE

TITLE CSED421 Database Systems Lab MySQL Basic Syntax SQL DML & DDL Data Manipulation Language SELECT UPDATE DELETE INSERT INTO Data Definition Language CREATE DATABASE ALTER DATABASE CREATE TABLE ALTER TABLE

More information

목차 JEUS EJB Session Bean가이드 stateful session bean stateful sample 가이드 sample source 결과확인 http session에

목차 JEUS EJB Session Bean가이드 stateful session bean stateful sample 가이드 sample source 결과확인 http session에 개념정리및샘플예제 EJB stateful sample 문서 2016. 01. 14 목차 JEUS EJB Session Bean가이드... 3 1. stateful session bean... 3 1.1 stateful sample 가이드... 3 1.1.1 sample source... 3 1.1.2 결과확인... 6 1.2 http session에서사용하기...

More information

J2EE Concepts

J2EE Concepts ! Introduction to J2EE (1) - J2EE Servlet/JSP/JDBC iseminar.. 1544-3355 ( ) iseminar Chat. 1 Who Are We? Business Solutions Consultant Oracle Application Server 10g Business Solutions Consultant Oracle10g

More information

PowerPoint Presentation

PowerPoint Presentation FORENSICINSIGHT SEMINAR SQLite Recovery zurum herosdfrc@google.co.kr Contents 1. SQLite! 2. SQLite 구조 3. 레코드의삭제 4. 삭제된영역추적 5. 레코드복원기법 forensicinsight.org Page 2 / 22 SQLite! - What is.. - and why? forensicinsight.org

More information

PowerPoint Presentation

PowerPoint Presentation FORENSIC INSIGHT; DIGITAL FORENSICS COMMUNITY IN KOREA SQL Server Forensic AhnLab A-FIRST Rea10ne unused6@gmail.com Choi Jinwon Contents 1. SQL Server Forensic 2. SQL Server Artifacts 3. Database Files

More information

MS-SQL SERVER 대비 기능

MS-SQL SERVER 대비 기능 Business! ORACLE MS - SQL ORACLE MS - SQL Clustering A-Z A-F G-L M-R S-Z T-Z Microsoft EE : Works for benchmarks only CREATE VIEW Customers AS SELECT * FROM Server1.TableOwner.Customers_33 UNION ALL SELECT

More information

MasoJava4_Dongbin.PDF

MasoJava4_Dongbin.PDF JSTORM http://wwwjstormpekr Issued by: < > Revision: Document Information Document title: Document file name: MasoJava4_Dongbindoc Revision number: Issued by: < > SI, dbin@handysoftcokr

More information

JEUS

JEUS JEUS JPA 안내서 JEUS v7.0 Fix#1 Copyright 2013 TmaxSoft Co., Ltd. All Rights Reserved. Copyright Notice Copyright 2013 TmaxSoft Co., Ltd. All Rights Reserved. 대한민국경기도성남시분당구서현동 272-6 우 ) 463-824 Restricted

More information

기술자료

기술자료 1 쪽중 1 쪽 WebLogic Server 8.1 Tutorials 03 - 리소스 (JDBC, JMS 등 ) 설정 본문서에서는 MedRec 애플리케이션을디플로이하고서비스하기위해서필요한 WebLogic Server 의리소스들을설정하는방법에대하여설명할것이다. 1. JDBC(Java Database Connectivity) Connection Pool 과 Data

More information

Cloud Friendly System Architecture

Cloud Friendly System Architecture -Service Clients Administrator 1. -Service 구성도 : ( 좌측참고 ) LB(LoadBlancer) 2. -Service 개요 ucloud Virtual Router F/W Monitoring 개념 특징 적용가능분야 Server, WAS, DB 로구성되어 web service 를클라우드환경에서제공하기위한 service architecture

More information

Tablespace On-Offline 테이블스페이스 온라인/오프라인

Tablespace On-Offline 테이블스페이스 온라인/오프라인 2018/11/10 12:06 1/2 Tablespace On-Offline 테이블스페이스온라인 / 오프라인 목차 Tablespace On-Offline 테이블스페이스온라인 / 오프라인... 1 일반테이블스페이스 (TABLESPACE)... 1 일반테이블스페이스생성하기... 1 테이블스페이스조회하기... 1 테이블스페이스에데이터파일 (DATA FILE) 추가

More information

Windows 8에서 BioStar 1 설치하기

Windows 8에서 BioStar 1 설치하기 / 콘텐츠 테이블... PC에 BioStar 1 설치 방법... Microsoft SQL Server 2012 Express 설치하기... Running SQL 2012 Express Studio... DBSetup.exe 설정하기... BioStar 서버와 클라이언트 시작하기... 1 1 2 2 6 7 1/11 BioStar 1, Windows 8 BioStar

More information

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc

Microsoft Word - ntasFrameBuilderInstallGuide2.5.doc NTAS and FRAME BUILDER Install Guide NTAS and FRAME BUILDER Version 2.5 Copyright 2003 Ari System, Inc. All Rights reserved. NTAS and FRAME BUILDER are trademarks or registered trademarks of Ari System,

More information

untitled

untitled A Leader of Enterprise e-business Solution FORCS Co., LTD 1 OZ Application Getting Started (ver 5.1) 2 FORCS Co., LTD A Leader of Enterprise e-business Solution FORCS Co., LTD 3 OZ Application Getting

More information

PowerPoint 프레젠테이션

PowerPoint 프레젠테이션 MySQL - 명령어 1. 데이터베이스관련명령 2. 데이터베이스테이블관련명령 3. SQL 명령의일괄실행 4. 레코드관련명령 5. 데이터베이스백업및복원명령 1. 데이터베이스관련명령 데이터베이스접속명령 데이터베이스접속명령 mysql -u계정 -p비밀번호데이터베이스명 C: > mysql -ukdhong p1234 kdhong_db 데이터베이스생성명령 데이터베이스생성명령

More information

1217 WebTrafMon II

1217 WebTrafMon II (1/28) (2/28) (10 Mbps ) Video, Audio. (3/28) 10 ~ 15 ( : telnet, ftp ),, (4/28) UDP/TCP (5/28) centralized environment packet header information analysis network traffic data, capture presentation network

More information