'Sortedset'에 해당되는 글 1건

  1. 2010.06.14 컬렉션 매핑과 1-n 관계
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>






저작자 표시
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by 영겁회귀

티스토리 툴바