'웹개발(JSP&Servlet)/Hibernate'에 해당되는 글 14건

  1. 2010.06.01 Hibernate CRUD 기본 API
  2. 2010.05.31 하이버네이트 매핑 타입
  3. 2010.05.31 클래스 - 테이블 매핑
객체 저장 : save(), persist()
try {
  HibernateUtil.beginTransaction();
  Session session = HibernateUtil.gertCurrentSession();
  session.save(article);
  ..
  HbernateUtil.commitTransaction();
  ..
}
persist()도 객체를 저장할수 있는 방법, 사용법도 동일
차이점은
 void persist(Object object)
          Make a transient instance persistent.
 void persist(String entityName, Object object)
          Make a transient instance persistent.

 Serializable save(Object object)
          Persist the given transient instance, first assigning a generated identifier.
 Serializable save(String entityName, Object object)
          Persist the given transient instance, first assigning a generated identifie
API와 같이 리턴 값의 차이. save()가 리턴하는것은  객체의 식별자 값으로 다음과 같이 사용가능
Integer i d= (Integer) session.save(article);

객체로딩
다음 메소드들을 이용
 Object get(Class clazz, Serializable id)
          Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.
 Object get(Class clazz, Serializable id, LockMode lockMode)
          Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.
 Object get(String entityName, Serializable id)
          Return the persistent instance of the given named entity with the given identifier, or null if there is no such persistent instance.
 Object get(String entityName, Serializable id, LockMode lockMode)
          Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance.

 Object load(Class theClass, Serializable id)
          Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.
 Object load(Class theClass, Serializable id, LockMode lockMode)
          Return the persistent instance of the given entity class with the given identifier, obtaining the specified lock mode, assuming the instance exists.
 void load(Object object, Serializable id)
          Read the persistent state associated with the given identifier into the given transient instance.
 Object load(String entityName, Serializable id)
          Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.
 Object load(String entityName, Serializable id, LockMode lockMode)
          Return the persistent instance of the given entity class with the given identifier, obtaining the specified lock mode, assuming the instance exists.
theClass파라마터는 로딩할 자바 클래스를 의미, id 는 식별자의 값을 의미

다음과 같은 매핑정보가 있다고 할때
<class name="pe.lucene.hibernate.Article" table="ARTICLE">
  <id name="id" column="ARTICLE_ID" type="int">
    <generator .... />
  </id>
 ..
</class>

Article article = (Article) session.get(Article.class, new Integer(10));
와 같이 테이블로부터 데이타를 읽어와 객체를 생성.
매핑되는 테이블에 데이타가 존재하지 않으면 Session.get()은 null을 리턴한다.

load() 메소드의 차이점은
get()메소드는 호출되는 시점에서 SELECT쿼리가 실행되는 반면에,
load() 메소드는 실제로 객체의 값이 필요할 때 SELECT 쿼리가 실행된다.
Article article = (Article) session.load(Article.class, new Integer(10)); //프록시객체를 리턴

int id = article.getId(); //이미 값을 가지고 있으므로 SELECT 실행없음
if (article.getTitle().startWith("[Re")) { //실제로 데이가ㅏ 필요한 시점이 되어 쿼리 실행됨
  ..
}
load()로 로딩한 객체가 테이블에 존재하지 않는 경우, SELECT 쿼리가 실행되는 시점에 테이블에 해당 데이타가 존재하지 않는다면,

org.hibernate
Class ObjectNotFoundException 를 발생시켜 객체가 존재하지 않음을 알려준다.

void load(Object object, Serializable id)
          Read the persistent state associated with the given identifier into the given transient instance.
 id에 해당하는 데이터를 테이블에서 읽어와 object에 저장해 줌.
Article article = new Article();
session.load(article, new Long(10));
식별자 값을 갖는 데이타가 없다면 동일한 예외를 발생시킨다.

객체수정 : update()
HibernateUtil.beginTransaction();
Article article = (Article)HibernateUtil.getCurrentSession().get(Article.class, new Integer(10));
article.setTitle(updatedTitle);
..
HibernateUtil.commitTransaction();
트랜잭션내에서 Session.get(), Session.load() 메소드로 로딩한 객체의 값을 수정해 주기만 하면 된다.
트랜젝션이 종료될때 UPDATE 쿼리가 실행된다.

Session.update()를 호출하는 방법도 있음
Article article = new Article();
article.setId(new Integer(10));
article.setTitle(updatedTitle);
..
try {
  HiberanteUtil.beginTransaction();
  HibernateUtil.getCurrentSession().update(article);
  HibernateUtil.commitTransaction();
} finally {
  ..
}
변경하고자 하는 객체를 생성후, Session.upate() 메소드에 전달하게되면,
UPDATE 쿼리가 실행되어서 데이타베이스에 변경된 값이 반영된다.
데이타가 존재하지 않으면

org.hibernate
Class StaleStateException 를 발생.

Session.update()를 사용할때는 반드시 객체의 모든 값이 설정되어 있어야 한다. 
프로퍼티를 설정하지 않게 되면, UPDATE 쿼리에 전달되는 값이 null 로 설정된다.

객체삭제 - delete()
HibernateUtil.beginTransaction();
Article article = new Article();
article.setId(10L);
HibernateUtil.getCurrentSession().delete(article);
HibernateUtil.commitTransaction();
삭제할 데이타가 존재하지 않는다면,StaleStateException 이 발생함.
Session.delete()로도 삭제가 가능
Article article = (Article)session.laod(Article.class, new Integer(10));
session.delete(article);



Posted by 영겁회귀

댓글을 달아 주세요

<property name="title" COLUMN="TITLE" type="string" />
속성의 값은 string인데 자바 프로퍼티와 테이블 칼럼 사이의 매핑 타입이 'string'임을 명시한것.
하이버네이트는 이 매핑값을 사용하여 칼럼과 프로퍼티 값 사이의 변환을 알맞게 처리.

자바 기본 데이터 타입을 위한 매핑 타입

 매핑타입 자바 기본 데이타 타입
SQL타입

 int int
INTEGER

 long ong
BIGINT

 short short
SMALLINT

 float float
FLOAT

 double double
DOUBLE

 big_decimal java.math.BigDecimal
NUMERIC

 character java.lang.String CHAR(1)

 string java.lang.String
VARCHAR

 byte byte
TINYINT

 boolean boolean
BIT

 yes_no boolean
CHAR(1) true일경우 'Y', false일경우 'N'

 true_false boolean
CHAR(1) true일 경우'T', false일 경우 'F'

날짜와 시간을 위한 매핑 타입
 매핑타입 자바 타입
SQL 타입
 date java.util.Date / java.sql.Date
DATA
 time java.util.Date / java.sql.Time
TIME
 timestamp java.util.Date / java.sql.Timestamp
TIMESTAMP
 calendar java.util.Calendar
TIMESTAMP
 calendar_date java.util.Calendar
DATE

대용량 데이터를 위한 매핑 타입
 매핑타입 자바 타입
SQL 타입
 binary byte[] 
VARBINARY
 text java.lang.String
CLOB
clob java.sql.Clob
CLOB
blob
java.sql.Blob
BLOB
serializable
java.io.Serializable 인터페이스를 구현한 자바 클래스
VARBINARY
text, binary 매핑 타입을 사용하면 로딩하는 즉시 데이터를 읽어오게 된다.
용량이 큰 칼럼의 경우 java.sql.Clob, java.sql.Blob을 사용하여 필요할때만 로딩하도록 한다.
이들 LOB타입의 데이타를 위치를 가르치는 Locator이기 대문에 실제 값은 로딩되지 않는다.

Clob 타입이나 Blob타입은 실제 값에 접근할때에 값을 읽어오게 된다. But 트랜잭션 열려있는 동안에만 가능하다.
try {
  HibernateUtil.beginTransaction();
  ..
  // Transaction 범위 내에서만 LOB 타입 로딩 가능
  Blob fileContent = article.getAttachment().getFileContent();
  in = fileContent.getInputStream();
  ..
  HibernateUtil.commitTracnsaction();
}

LOB 타입의 프로퍼티에 값을 할때는 다음과 같이
Article article = new Article();
...
article.setContent( Hibernate.createClob(content));

다음 메소드가 제공됨
static Blob createBlob(byte[] bytes)
          Create a new Blob.
static Blob createBlob(InputStream stream)
          Create a new Blob.
static Blob createBlob(InputStream stream, int length)
          Create a new Blob.
static Clob createClob(Reader reader, int length)
          Create a new Clob.
static Clob createClob(String string)
          Create a new Clob.

Posted by 영겁회귀

댓글을 달아 주세요

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping schema="USR1" package="pe.lucene.hibernate">
  <class name="User" table="User">
    <id name="id" column="USER_ID">
      <generator name="identity" />
    </id>
    <property name="title" coulmn="TITLE" />
    ....
  </class>

  <class name="pelucene.hbernate.Hobby" table="Hobby">
  ...
  </class>
</hibernate-mapping>

<hibernate-mapping> 의 속성은 모두 선택 사항.
schema - 데이터베이스 스키마 이름
catalog - 데이터베이스 카탈로그 이름
package - <class> 태그에서 완전한 클래스 이름을 명시하지 않을때 사용

<hibernate-mapping> 는 1개이상의 <class>를 가질수 있다.
<class>의 주요 속성
name - 클래스이름
table - 테이터 베이스 테이블 이름
<hibernate-mapping schema="BBS0" package="...">
  <class name="Board" table="BOARD" schema="BBS1">
  ....
  </class>
</hibernate-mapping>
BBS0.BOARD가 아니라 BBS1.BOARD 사이의 매핑을 의미한다.

컬럼 수가 많아서 값이 존재하거나, 변경된 칼럼에 대해서만 쿼리를 생성하기 원할때 dynamic-insert, dynamic-upate속성을 true로.
<class name="Product"
  dynamic-insert="true"
  dynamic-update="true">
  ...
</class>
dynamic-insert가 true일때는 값이 null인 프로퍼티는 INSERT쿼리가 생성될대 포함되지 않는다.
dynamic-update가 true일 경우 값이 변경되지 않는 프로퍼티는 쿼리에 포함시키지 않는다.
따라서 객체의 값이 변경될 경우 변경된 프로퍼터에 대해서만 UPDATE쿼리를 수행하게 된다.

식별자 필드 매핑
<class name="Article" table="ARTICLE"
  <id name="id" column="ARTICLEID" type="long">
    <generator class="identity" />
  </id>
  ....
</class>
주요키(Primary Key) 컬람에 대한 매핑은 <id>를 사용
<id>를 <generator>와 함께 사용.
<id>의 name -> 프로퍼티 이름, column -> 데이블 주요키 컬럼 이름 , type -> 프로퍼티 타입 (하이버네이트에서 제공하는 타입)
 생성기이름 설명
 identity mysql, DB2, MS sql, Sybase, HypersonicSQL의 식별자 칼럼지원, 리턴타입은 int , long, short
 sequence  오라클,DB2, PostegeSQL에서 사용하는 시퀀스를 사용. 리턴 타입 long,short, int
 hilo  hi/lo 알고리즘을 사용하여 short,long,int 타입의 키를 생성.hi값은 지정한 테이블의 칼럼으로부터 가져온다
 native  하위 데이타 베이스가 제공하는 기능에 따라 indentity, sequence, hilo 생성기 중에서 한가지를 선택한다.
 assigned  자동으로 키 값을 생성하지 않고, 코드에서 직접 키 값을 지정한다.
 increment 하이버네이트가 1씩 증가된 키 값을 할당한다.
 guid  ms sql과 mysql에서 데이터베이스 생성한 guid 문자열을 키값으로 사용한다.
 uuid 128비트 UUID알고리즘을 사용 string타입의 키를 생성, 생성된 문자열은 32글자의 16진법으로 인코딩되어 표시된다
 seqhilo hilo생성기와 동일하다. 차이점은 주어진 데이터베이스 시퀀스로부터 hi값을 가져온다는 것
foreign 연관된 객체의 식별자를 사용, 일반적으로 <one-to-one> 주요 키 연관에서 사용된다.

identity 생성기 - mysql의 auto_increment 칼럼과 같이 DBMS가 제공하는 식별자 칼럼을 지원
create table ARTICLE (
  ARTICLEID int not null auto_increment,
  ..
)

<class name="Article" table="ARTICLE">
  <generator class="identity" />
  ...
</class>

Article article1 = new Article();
Article article2 = new Article();
...
session.save(article1);
session.save(article2);

session.getTransaction().commit();

//article1.getId() + 1 == article2.getId() : true

sequence 생성기
오라클의 시퀀스와 같은 것으로부터 읽어온 값을 식별자로 사용한다.
사용할 시퀀스의 이름을 파라미터로 받아온다
<class name="Article" table="ARTICLE">
  <id name="id" column="ARTICLE_ID" type="int">
    <generator class="sequence">
      <param name="sequence">SEQ_ARTICLE</param>
    </generator>
  </id>
  ..
</class>
객체를 테이블에 저장할 때, SEQ_ARTICLE 시퀀스로부터 값을 읽어와 id 프로퍼티의 값으로 사용하게 된다.

assigned 생성기
자동으로 키를 생성하지 않고, 객체를 저장하기 전에 코드에서 직접 키 값을 지정할때 사용된다.
<class name="Member" table="MEMBER">
  <id name="email" column="MEMBER_EMIAL" type="string">
    <generator class="assigened" />
  </id>
  ..
</class>

increment 생성기
키값을 하이버네이트가 1씩 증가시켜 준다.
최초에 값 생성이 필요할 때 다음과 같은 쿼리를 실행하여 테이블로부터 현재 저장된 키 값으리 최대값을 구한다.
select max(ID) from ARTICLE
최대 키 값을 읽어 오면, 이후부터는 메모리에서 값을 1씩 증가시킨다. 매번 데이타베이스 테이블을 조회하는 것이 아니기 때문에, 분산환경에서는 increment 생성기를 사용해서는 안된다.


일반 필드 매핑

property 태그를 사용
<class name='pe.lucene.haibernate.Article" table="ARTICLE" ..>
  ..
  <proeprty name="title" column="TITLE" type="string" />
  ..
</class>
프로퍼티의 이름이 칼럼이름과 동일하다면 column 속성을 사용하지 않아도 된다.
<property name="title" type="string" />
칼럼부분을 <column> 태그로 사용하여 명시할수 있다.
<property name="title" type="string">
  <column name="TITLE" />
</property>
type속성을 명시하지 않을 경우에는 하이버네이트가 자동으로 타입을 감지하여 알맞게 처리한다.
그러나 완벽하지 않으므로 매핑 타입을 지정해주는 것이 좋다.

insert, update - 쿼리 실행시 프로퍼티 포함여부
<property name="lastModified" column="LAST_MODIFIED"
  insert="false" update="true" generated="always" />
자동으로 값이 생성되는 칼럼으로 매핑퇴는 프로퍼티의 경우는 INSERT쿼리나 UPDATE에 포함시킬 필요가 없으니 false로 지정하여 목록에서 제외할수 있다.

데이터베이스가 값을 생성하는 컬럼의 명시
<property name="lastModified" ... generated="always" />
update되었다고 가정했을때 컬럼의 값을 바뀌었지만 자바 객체의 값은 바뀌지 않았으므로 올바른값을 유지 할수 없다.
generated 속성을 사용하여 하이버네이트로 하여금 해당 칼럼으로 부터 값을 읽어오게 할 수 있다.
INSERT나 UPDATE 쿼리를 실행한후 칼럼의 값을 테이블에서 읽어와 객체에 반영한다.
generted 값을 insert로 하면 INSERT 쿼리를 실행할때만 값을 읽어온다.

계산된 값 매핑
<property name="average" fomula="SUM / TOTAL_COUNT" />
칼럼의 값을 사용하여 계산된 결과를 프로퍼티에 저장.
TOAL_COUNT 칼럼과 SUM칼럼을 사용하여 구한 평균값을 프로퍼트에 저장
객체를 로딩할때마가 매번 실행됨. INSERT쿼리나 UPDATE쿼리가 실행될때에는 사용되지 않는다

프로퍼티 접근 모드 지정
<property name="title" />
기본적으로 자바 빈 스타일의 프로퍼티 사용
setTitle(), getTitle()이 정의되어 있어야 한다.

<property name="title" column="TITLE" access="field" />
field로 지정한 경우 자바 빈 스타일의 get,set메서드를 구현할 필요는 없으며, 다음과 같은 필드 정의만 필요 (private로 선언되어도 상관없음)
public class Article {
  private String title;
  ..
}
access의 기본값은 "property"로 자바 빈 스타일의 get/set 메소드가 필요한 방식이다.
acesss 속성을  지정해야될 칼럼이 많은 경우는 default-access 속성을 사용할수 있다.
<hibernate-mapping default-access="field" ...>
  <class ..>
    <property name="title" />
    <property name="name" />
    <property name="content" acess="property" />
    ....
  </class>
</hibernate-mapping>


Posted by 영겁회귀

댓글을 달아 주세요