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

  1. 2010.06.25 개체 타입의 컬렉션
  2. 2010.06.14 컴포넌트 타입의 컬렉션
  3. 2010.06.14 컬렉션 매핑과 1-n 관계
경매시스템에서 사용자는 한개이상의 경매 품목에 한번이상 입찰가능하다. -> 품목과 사용과 관계에는 1-n 관계가 성립.
또한 하나의 물품에 대한 한개 이상의 입찰이 들어올 수 있다. -> 품목과 입찰 사이에서도 1-n 관계가 성립.
Bid는 입찰로  User와 Item에 공유된다. -> User나 Item의 컴포넌트 타입이 아니라 하나의 독립된 개체 타입이 된다.
이런 개체타입간의  1-n관게를 매핑할때도 컬렉션 타입(Set, List, Map, Bag)을 사용.

< one-to-many> 태그를 사용한 1-n 관계 매핑
public class User {
private Set<Bid> bids = new HashSet<Bid>();
...
// getter / setter
}

<set>태그는 동일 <element> 태그 대신에 <one-to-many> 태그를 사용
<class name="User" table="USER">
..
<set name="bids" table="BID" inverse="true" cascade="all">
<key column="USERID" />
<one-to-many class="Bid" />
</set>
</class>
<class name="Bid" table="BID">
...
</class>
inverse 속성은 영속성 제어와 관련된 속성임.

Set 타입과 Bag타입
User클래스에서  Bid클래스로의 단방향 1-n관계인 경우 User객체에서만 Bid객체로 접근 할수 있고
반대로 Bid객체에서 User객체로 접근할수있는 참조는 없다.
public class User {
private Integer id;
private Set<Bid> bids = new HashSet<Bid>();

// getter / setter...
public void addBid(Bid bid) {
bids.add(bid);
}
}
public class Bid {
private Integer id;
...//User에 대한 참조가 없다
//Set타입에 들어가므로 equals() 메소드와 hashCode() 메소드를 구현
@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((id == null) ? : 0 : id.hashCode());
return result;
}
@override
public boolean equals(Obejct obj) {
if (this == obj) return true;
if (obj === null) return false;
if (getClass() != obj.getClass()) return false;
final Bid other = (Bid)obj;
if (id == null || other.getId() == nul) return false;
if (!id.equals(other.id)) return false;
retur true
}
}

<class name="User" table="USER">
...
<set name="bids" table="BID" cascade="save-update, delete">
<key column="USERID" />
<one-to-many class="Bid" />
</set>
</class>
<class name="Bid" table="BID" />
...
</class>
User객체 및 User.bids프로퍼티에 저장된 Bid객체를 저장할수 있음
User user = new User();
Bid bid = new Bid();
user.addBid(bid);
session.save(user);
위코드가 실행되면 다음의 세가지 쿼리가 실행됨
insert into USER values()
insert into BID values()
update BID set USERID=? where ID = ?
1.User 객체를 저장
2. cascade 속성의 값이 "save-update" 이므로 연관된 Bid객체를 저장한다.
3. User 매핑에서 <set>태그의 <key> 칼럼값을 수정한다.

Bag타입의 매핑
User.bids필드타입이 collection인 경우 <bag>태그를 사용하여 매핑
<class name="User" table="USER">
...
<bag name="bids" table="BID" cascade="save-update,delete">
<key column="USERID" />
<one-to-many class="Bid" />
</bag>
</class>

<class name="Bid" table="BID">
...
</class>

양방향 매핑 설정
User입장에서 Bid로의 관계가 1-n이기 때문에, 반대로 Bid에서 User로의 관계는 n-1이 된다.
n-1의 경우 <many-to-one>을 사용한다.

양방향 관계를 설정하기 위해, Bid객체에서 User객체로 접근할수있는 프로퍼티를 추가해야함
public class Bid {
private Integer id;
privaet User user;
..
..
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
User.addBid() 메소드에 User객체와 Bid객체를 연관시켜주는 코드를 추가
public class User {
...
public void addBid(Bid bid) {
bids.add(bid);
bid.setUser(this);
}
}

매핑 설정에 Bid에서 User로의 n-1관계 매핑을 추가.
<class name="Bid" table="BID">
<id name="id" column="ID">
<generator class="identity" />
</id>
<many-to-one name="table" column="USERID" class="User" />
</class>
위와 같이 설정후 Session.save()  로 User객체를 실행하면 다음 뤄기ㅏ 실행됨
insert into USER values()
insert into BID (UserID) values(?)
update BID set USERID = ? where ID = ?
User클래스 매핑의 <set>태그에서 지정한 <key>칼럼과 관련된 커뤼가 마지막에 update로 실행되기 때문.
불필요한 마지막 update쿼리를 방지하기 위해서 <set>태그의 inverse속성의 값을  true 로 지정해준다.
<class name="User" table="USER">
<set name="bids" table="BID" cascade="save-update,delete" inverse="true">
<key column="USERID" />
<one-to-many class="Bid" />
</set>
...
</class>
insert속성을 true로 하면 User측에서는 더이상 Bid객체 저장과 관련된 쿼리를 수행하지 않는다.

delete-orphan을 이용한 삭제
User user = (User)session.get(User.class, new Integer(3));
Set<Bid> bids = user.getBids();
Bid some = ........;
bids.remove(some);
Set.remove() 통해 객체를 삭제했으므로, 삭제된 객체와 매핑되는 테이블 데이터도 함께 삭제될거라고 에상할수있다.
하지만 실제로 객체와 매핑되는 테이블 데이터는 삭제되지 않는다.
대신 BID테이블의 USERID필드의 값이 null이 된다.
컬렉션에서 객체가 삭제되었을때, 테이블에서도 함께 삭제될길 원한다면 cascade 속성에 delete-orphan을 추가해야함.
<set name="bids" table="BID" cascade="all, delete-orphan" inverse="true">
<key column="USERID" />
<one-to-many class="Bid" />
</set>
casecade속성에 delete-orphan을 추가하면 Set.remove() 메소드로 객체를 Set에서 제거하면 DELETE 쿼리가 실행되어 테입르에서도 함께 삭제됨

cascade속성에 delete-orphan을 명시했을때 Set에 저장된 객체를 삭제하기 위해 새로운 Set객체를 할당할 경우 에러 발생.
User user = (User)session.get(User.class, 19);
user.setBids(new HashSet<Bid>()); //delete-orphan 인경우 예외가 발생.

cascade 속성에 delete-orphan이 명시되어 있는 경우에는 Set.clear()메소드를 호출하여 객체를 제거함으로 써
테이블 내에서도 관련 객체를 삭제할수 있다.
User user = (User)session.get(User.class, 19);
user.getBids().clear(); //delete-orphan인 경우 clear() 로 전체 삭제

List 타입
Set타입과 마찬가지로 <element>태그나 <composite-element>태그 대신 <one-to-many>태그를 사용함.
BID테이블에 List 인덱스 정보를 위해  POSITION칼럽 추가시, User와 Bid의 관계를 <list>를 사용해 지정할 수 있다.
<class name="User" table="USER">
<id name="id" column="ID">
<generator class="identity" />
</id>
<list name="bids" table="BID" cascade="all, delte-orphan">
<key column="USERID" />
<list-index column="POSITION" />
<one-to-many class="Bid" />
</list>
</class>

<class name="Bid" table="BID">
<id name="ID" column="ID">
<generator class="identity" />
</id>
<many-to-one name="user" column="USERID" class="USER" />
</class>
<set>과 다른점은 <list>태그에 insert="true"를 명시하지 않음.
inverse 속성을 true 로 지정할 경우 List에 새로운 객체를 추가하거나 기존 객체를 삭제할때 BID 테이블의 POSITION 칼럼에 인덱스 값이 오러바르게 반영되지 않기 때문

Map 타입
List타입과 마찬가지 이유로 inverse 속성을 명시하지 않고 매핑을 설정해 주어야 한다.
<class name="User" table="USER">
<id name=-"id" column="ID">
<generator class="identity" />
</id>
<map name="props" table="USER_PROPERTY" cascade="save-update, delete-orphan">
<key column="USERID" />
<map-key column="PROP_KEY" type="string" />
<one-to-many classes="UserProperty" />
</map>
...
</class>

<class name="UserProeprty" table="USER_PROPERTY">
<id name="id" coumn="ID">,,,</id>
<property name="key" column="PROP_KEY" insert="false" update="false" />
<property name="value" />
....
<many-to-one name="user" column="USERID" class="User" />
</class>




Posted by 영겁회귀

LOG_IMAGEFILE 테이블은 LIST타입과 매핑되는 컬렉션 테이블임.
매핑될 칼럼이 3(NAME, SIZEX, SIZEY)이므로 컴포넌트 타입을 사용해야 할것이다.
package pe.hibernate.chap04.model;

public class ImageFile {
private String name;
private int sizeX;
private int sizeY;

public ImageFile() {}

@Override
public int hashCode() {
final int PRIME = 31;
int result = 1;
result = PRIME * result + ((name== null) ? 0 : name.hashCode());
result = PRIME * result + sizeX;
result = PRIME * result + sizeY;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) resurn false;
if (getClass() != obj.getClass()) return false;
final ImageFile other = (ImageFile) obj;
if (name == null) {
if (other.anme != null) return false;
} else if (!name.equals(other.name)) {
return false;
}
if (sizeX != other.sizeX) return false;
if (sizeY != other.sizeY) return false;
return true;
}
}
모든 컴포넌트 타입의 클래스에서 equals()와 hashCode()를 구현할 필욘없다.
equals()와 hashCode() 는 set타입의 저장될 경우에 구현해야 한다.
public class Log {
private List<ImageFile> imageFiles = new ArrayList<ImageFile>();
...
}
컴포넌트 타입의 컬렉션 매핑을 설정하는 방법은 기본 데이터 타입의 컬렉션 매핑과 비슷.
<element>태그 대신 <composite-element> 태그를 사용.
<list name="imageFiles" table="LOG_IMAGEGFILE">
<key column="LOGID" />
<list-index column="POSITION" base="1" />
<composite-element class="ImageFile">
<property name="name" column="NAME" />
<property name="sizeX" column="sizeX" />
<property name="sizeY" column="sizeY" />
</composite-element>
</list>

sort 및 order-by 속성을 이용한 컴포넌트 타입의 정렬
SortedMap  컬렉션이나 SortedSet컬렉션에 저장될 컴포넌트 타입을 정렬할 때에도 sort 속성을 사용.
sort 속성의 값을 natural로 지정할 경우 컴포넌트 타입 클래스는 Comparable 인터페이스를 구현해주어야 한다.
package pe.hibernate.chap02.model;

public class ImageFile implements Comparable<ImageFile> {
private String name;
....
public int compareTo(ImageFile to) {
return this.getNames().compareTo(to.getName());
}
}
Comparable 인터페이스를 구현하지 않도록 하려면, 직접 구현해서 sort 속성에 명시해 주어야 한다.
 public class ImageFileComparator implements Comparator<ImageFile> {
public int compare(ImageFile 01, ImageFile 02) {
return 01.getName().compareTo(o2.getName());
}
}
order-by 속성을 사용할 경우 DBMS에서 정렬을 수행하므로 컴포넌트 타입 클래스가 Comparable인터페이스를 구현할 필요한 없으며, 또한 Comparator 구현체를 통해 제공할 필요도 없다.

부모 객체 참조하기
<parent>태그를 사용 부모 객체를 참조할수 있도록 함
<component name="korName" class="Name">
<parent name="employee" />
<property name="surname" column="KOR_SURNAME" />
...
</component>
<composite-element>태그를 사용할때에도 <component>태그를 사용할 때처럼 <parent>태그 사용가능
<set name="imageFiles" table="LOG_MANAGER">
<key column="LOGID" />
<composite-element class="ImageFile">
<parent name="log" />
<property name="name" column="NAME" />
<property name="sizeX" column="sizeX" />
<property name="sizeY" column="sizeY" />
</composite-element>
</sex>
Posted by 영겁회귀
1-n관계는 어떤 타입의 객체가 다른 타입의 객체를 여러개 포함한다는 것.
데이터 베이스를 설계 할때 이런 컬렉션 데이터는 별도의 테이블로 저장하는데, Collection Table이라고도 부른다.

컬렉션 인터페이스
private Set<String> filenames = new java.util.HashSet<String>();
... // get/set 메소드
하이버네이트가 지원하는 컬렉션 타입
 컬렉션타입 매핑태그
설 명
초기 클래스
 Set <set>
 순서가 없고 중복이 허용되지 않는 집합
 HashSet
 SortedSet <set>
 순서가 있고, 중복이 허용되지 않는 집합, sort속성을 사용하여 정렬 방식을 지정한다
 TreeSet
 List  <list>  순서가 없고, 중복이 허용되는 집합. 내부적으로 List를 사용하지만, 인덱스 값은 사용되지 않는다.
 ArrayList
 Collection  <bag>, <idbag>
 순서가 없고, 중복이 허용되는 집합. 내부적으로  List를 사용하지만, 인덱스 값은 사용되지 않는다.
 ArrayList
 Map  <map>  <키,값>쌍을 저장한다  HashMap
 Sortedmap  <map>  <키,값>쌍을 저장하며, sort속성을 통해 정렬방식을 지정한다.
 TreeMap
초기 클래스는 자바코드에서 해당 타입의 필드를 초기화 할때 사용할 클래스를 의미.
예) SortedMap 타입을 사용하고 싶다면, 다음과 같이 TreeMap클래스를 사용하여 초기화 해주어야 한다
private SortedMap<Integer, String> tags = new TreeMap<Integer, String>();

기본 데이터 타입의 컬렉션
Set 타입
LOG테이블은 TAG테이블과 1-n의 관계. n에 속하는 LOG_TAG 테이블을 외부 키를 사용하여 LOG테이블을 참조하고 있다.

public class Log {
private Set<String> tags = new HashSet<String>();
...
public void setTags(Set<String> tags) {
this.tags = tags;
}

public Set<String> getTags() {
return tags;
}
public void addTag(String tag) {
tags.add(tag);
}
}

<class name="Log" table="LOG">
<id name="id" column="ID" type="int">
<generator class="identity">
</id>
<set name="tags" table="LOG_TAG">
<key column="LOGID" />
<element type="string" column="TAG" />
</set>
</class>
<set> 태그의 table 속성에는 Set컬렉션 타입과 매핑될 컬렉션 테이블의이름을 명시한다.
<key> 태그는 컬렉션 테이블인 LOG_TAG 테이블이 LOG 테이블을 참조할때 사용되는 외부 키 칼럼의 이름을 명시한다.
<element> 태그는 Set에 저장될 값과 관련되 칼럼을 명시하게 된다.
Log log = new Log();
log.setTitle("자바 프로그래밍");
log.addTag("자바");
log.addTag("객체지향");
log.addTag("eclipse");
session.save(log);
Log는 LOG테이블에 매핑. Set타입에 저장한 String 타입값은 LOG_TAG 테이블에 저장된다.
새로 생성된 Log객체의 식별자값이 5인 경우 다음과 같이 테이블에 저장된다.
ID
 TITLE
 5  자바프로그래밍

 LOGID TAG
 5  자바
 5  객체지향
 5  eclipse
Set타입은 중복을 허용하지 않기 대문에, 동일한 데이타를 여러번 추가하더라도 테이블에는 한값만남는다.
(Set은 중복되는 값을 무시)
기존에 저장된 데이타를 삭제할 때는 트랜젝션 내에서 Set에 저장된 값을 삭제해 주면된다.
물론, 트랜잭션 내에서 새로운 값을 추가해 주면 INSERT 쿼리가 실행되어 테이블에 새로운 행이 추가된다.
//트랜젝션시작
...
Log log = (Log)session.get(Log.clss, new Integer(5));
Set<String> tags = log.getTags();
tags.add("객체"); //또는 log.getTags().add("객체");
tags.remove("자바"); // log.getTags().remove("자바");
...
//트랜잭션 커밋

Set에 저장된 모든 값을 삭제하고 싶을땐 Set.clear()호출하건, 새로운 HashSet을 항당해주거나,null을 할당.
Log log = (Log)session.get(Log.class, new Integer(5));
log.getTags().clear();
// log.setTags(new HashTable<String>());
// log.setTags(null);

List 타입
List는 인덱스를 갖고 있으므로, List 타입을 저장할 컬렉션 테이블은 인덱스 값을 저장할 칼럼이 추가로 필요하다.
LOG테이블에 첨부된 파일의 이름 목록을 List 타입으로 저장할 경우,
List객체의 인덱스값은 POSITION  칼럼에 저장된다.

public class Log {
..
private List<String> files = new ArrayList<String>();

public void setFiles(List<Strkng> files) {
this.files = files;

}
public List<String> getFiles() {
return files;
}
public void addFile(String filename) {
files.add(filename);
}
...
}

List 타입의 매핑은 <list>태그를 사용하여 표현.
<class name="Log" table="LOG">
..
<list name="files" table="LOG_FILE">
<key column="LOGID" />
<list-index column="POSTION" />
<element type="string" column="FILENAME" />
<list>
....
</class>

<set>과 비슷, <list-index>  태그로 List의 인덱스 값을 저장할 칼럼을 명시.
Log log = new Log();
List<String> files = log.getFiles();
files.add("분석.doc"); //또는 log.addFile("분석.doc");
files.add("분석1.doc");
fiels.add("분석3.doc");
session.save(log);

 ID TITLE
 6 분석자료

LOGID
POSITION
FILENAME
 6  0 분석1
 6  1 분석2
 6  2 분석3
LOG_FILE테이블에 List내에서의 인덱스 값이 저장된다.
Session.get()으로 로딩한후에 List.get(index) 메소드를 사용하여 접근.
Log log = (Log)session(Log.class, new Integer(6));
String file0 = log.getFiles().get(0);
String file1 = log.getFiles().get(1);
String file2 = log.getFiles().get(2);
새로운 객체를 추가하거나 삭제할때는 add(), remove(), clear()등 사용
//Transaction start
..
Log log = (Log)session(Log.class, new Integer(6));
log.getFiles().remove(0);
log.getFiles().add("신규.xls");
...
//Transaction commit
List를 컬렉션에 저장하면 위치값은 0부터 시작. 1부터 시작되길 원한다면 <list-index> 태그의 base 속성의 값을 '1'로 지정함
<list name="files" table="LOG_TABLE">
<key column="LOGID" />
<list-index column="POSITION" base="1" />
<element type="string" column="FILENAME" />
</list>
base 속성의 값을 1로 지정하면 LOG_TABLE 테이블에는 인덱스값이 1부터 시작
LOGID
POSITION
 FILENAME
6  1 Blog
6
 2 Cafe
 6  3 News

Map 타입
<키,값>쌍을 저장할때 사용되므로, 키를 저장할 칼럼을 필요로 함.

Map타입과 매핑될 컬렉션 테이블은 키 값을 저장할 칼럼이 필요

LOG_PROPERTY 테이블은 Map프로퍼티로 매핑될 수 있다.
public class Log {
....
private Map<String, String> prop = new Hashmap<String, String>();
....
public void setPorp(Map<String, String> prop) {
this.prop = prop;
}
public Map getProp() {
return prop;
}
public void addProperty(String key, String value) {
prop.put(key, value);
}
}
Map타입은 <map>타입을 사용하여 매핑한다.
<map name="prop" table="LOG_PROPERTY">
<key column="LOGID" />
<map-key column="PROP_KEY" type="string" />
<element type="string" column="PROP_NAME" />
</map>
다음과 같이 사용
Log log = new Log();
log.addProperty("key1", "value1");
log.addProperty("key2", "value2");
log.addProperty("key3", "value3");
log.addProperty("key4", "value4");\
session.save(log);

Log log2 = (Log)session.get(Log.class, 16);
Map prop = log2.getProp();
String value1 = prop.get("key1"); // log2.getProp().get("key1");
prop.put("key3", "newvalue");
prop.remove("key2");

Bag타입
Bag은 중복을 허용하는 집합. (자바는 X)
Bag구현이 필요한 경우 다음과 같이 사용
public class Log {
....
private Collection<String> tags = new Array<String>();
public Collection<String> getTags() {
return tags;
}
public void setTags(Collection<String> tags) {
this.tags = tags;
}
public void addTag(String tag) {
tags.add(tag);
}
}
Bag은 Set을 대체할 수 있으며, Set에서 사용했던 테이블을 Bag용으로 그대로 사용할수 있다.
Bag매핑할때는 <bag>태그를 사용
<class name="Log" table="LOG">
<id name="id" column="ID" type="int" />
<generator class="identity" />
</id>
<bag name="tags" table="LOG_TAG" />
<key column="LOGID" />
<element type="string" column="TAG" />
</bag>
....
</class>
<set>태그와 차이점은 <set>태그 대신에 <bag>태그를 사용한것 뿐. 중복된 값을 허용하기 때문에 중복된 값을 삽입할수있다.
Log log = new Log();
log.addTag("Kroea");
log.addTag("Korea");
log.addTag("Japan");
session.save(log);
테이블마다 주요키를 설정해 주는 겂이 좋은데 Bag과 매핑되는 LOG_TAG테이블의 경우 <LOGID, TAG>를 주요키로 설정할수 없다( TAG에 중복값이 허용되기 때문에). --> Bag과 매핑되는 테이블에 주요키를 추가하고 싶다면 별도의 주요키 칼럼이 추가되어야 한다.
 ID LOGID
TAG
 1  5  JAVA
 2  5  Object
 3  5  JAVA
이런 경우 <bag>대신에 <idbag> 태그를 사용하여 Bag타입을 매핑한다.
<class name="Log" table="LOG">
<id name="id" column="ID" type="int">
<generator class="identity" />
</id>
<idbag name="tags" table="LOG_TAG">
<collection-id type="int" column="ID" >
<generator class="identity" />
</collection-id>
<key column="LOGID" />
<element type="string" column="TAG" />
</idbag>
</class>
<idbag>을 사용할 경우, <collection-id> 태그를 사용하여, 컬렉션 테이블의 식별자 칼럼을 위한 설정을 추가.
<id>태그와 동일하게 사용되며, <generator>태그를 사용하여, 컬렉션 테이블의 식별자 생성기를 명시해주면된다.

SortedSet과 SortedMap
SortedSet 클래스와 SortedMap 클래스를 사용ㅇ하면 특정한 값을 기준으로 테이터를 정렬하여 읽어올수 있다.

먼저 정렬된 값을 저장ㅇ하기 위해서는 SortedSet타입이나 SortedMap을 사용해야함.
필드를 초기화 할때에는 각각 SortedSet 타입의 경우는 TreeSet클래스를,
SortedMap 타입의 경우에는 TreeMap 클래스를 사용한다.
public class Log {
private SortedSet<String> tags = new TreeSet<String>();
private SortedMap<String> prop = new TreeMap<String, String>();
...
}

<class name="Log" table="LOG">
....
<map name="prop" table="LOG_PROPERTY" sort="natrual">
<key column="LOGID" />
<map-key column="PROP_KEY" type="string" />
<element type="string" column="PROP_VALUE" />
</map>
<set name="tags" table="LOG_TAG" sort="natural">
<key column="LOGID" />
<element type="string" column="TAG" />
</set>
</class>
프로퍼티 타입을 SortedMap이나 SortedSet으로 지정하고 <map>태그나 <set> 태그의 sort속성값을 natural로 지정하면 데이터베이스로부터 데이터를 로딩한 다음 메모리에서 값을 정렬한다.
Log log = new Log();
log.addTag("Korea");
log.addTag("Spain");
log.addTag("Norway");
session.save(log);

Log log2 = (Log) session.get(Log.class, 29);
Iterator<String> iter = log2.getTags().iterator();
while(iter.hasNext()) {
System.out.println(iter.next());
}
실행결과는 오름차순으로 정렬된 Korea, Norway, Spain이 된다.

SortedMap 타입의 경우 <키,값> 쌍에서 키를 사용하여 정렬한다.
sort값을 natural로 지정하면, 기본적으로 오름차순으로 정렬.
내림차순으로 정렬하고 싶다면, Comparator 인터페이스를 구현한 클래스의 이름을 sort 속성에 명시해 주면된다.
package pe.hibernate.chap04.model;

import java.util.Comparator;

public class DescendingComparator implements Comparator<String> {
public iint compare(String str1, String str2) {
return str2.compareTo(str1);
}
}
내림차순으로 정렬할 때 사용될 Comparator구현체를 위와 같이 작성함.

 <set name="tags" table="LOG_TAG"
sort="pe.hibernate.chap04.model.DescendingComparator">
<key column="LOGID" />
<element type="string" column="TAG" />
</set>

order-by 속성을 사용한 정렬
sort속성은 데이타베이스에서 데이터를 로딩한 뒤, 메모리에서 정렬하는 반면,
order-by 속성은 데이터베이스가 제공하는 정렬 기능을 사용한다.
order-by 속성을 사용하려면 먼저 SortedSet 내지 SortedMap이 아닌 Setx타입과 Map타입을 사용해야 한다.
order-by 속성에는 SQL의 order by절에서 사용가능한 쿼리를 사용할수 있다.
<set name="tags" table="LOG_TAG"
order-by="TAG desc">
<key column="LOGID" />
<element type="string" column="TAG" />
</set>
order-by 속성에는 SQL함수도 가능
<set name="tags" table="LOG_TAG"
order-by="lower(TAG) asc">
<key column="LOGID" />
<element type="string" column="TAG" />
</set>
order-by 속성을 사용하면, 하이버네이트는 Map타입인 경우 내부적으로 LinkedHashMap 클래스를 사용하고,
Set타입은 경우 내부적으로 LinkedHashSet클래스를 사용하여 데이타를 저장한다.
(LinkedHashMap클래스와 LinkedHashSet 클래스는 자바 1.4버전 부터 제공됨)

Bag타입에도 order-by  속성 가능. Bag타입의 경우 내부적으로 ArrayList 클래스를 사용하여 데이타를 저장한다.
<bag name="tags" table="LOG_TAG" order-by="lower(TAG) acs">
<key column="LOGID" />
<element type="string" column="TAG" />
</bag>






Posted by 영겁회귀

티스토리 툴바