Whiteship's Note


Immutable Entity 만들기

Hibernate/Chapter 4 : 2008.01.20 13:22


특징

  • 변하지 않아야 할 Persistent 객체가 있을 수 있다.
  • 이런 Persistent 클래스에는 필드로 직접 접근하도록 설정하고, accessor 메소드들을 만들지 않으면 된다.

설정하기

immutable entity 설정하기
@Entity
@org.hibernate.annotations.Entity(mutable=false)
@org.hibernate.annotations.AccessType("field")
public class Bid {

}
  • @AccessType은 하이버네이트가 Pesistent 클래스에 접근하는 방법을 표시한다.
  • 클래스, 메소드, 필드 위에 붙여서 좀 더 세밀한 설정이 가능하다.

'Hibernate > Chapter 4' 카테고리의 다른 글

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


동적 SQL 생성

Hibernate/Chapter 4 : 2008.01.20 13:21


특징

  • 기본으로 하이버네이트가 시작할 때, 각각의 Persistent 클래스와 관련된 CRUD 쿼리를 생성한다.
  • UPDATE 문은 모든 필드를 수정하도록 작성되어 있다.
  • Sometimes you can avoid generating any UPDATE statement, if the persistent class is mapped immutable.

설정하기

동적으로 쿼리 생성하도록 설정
@Entity
@org.hibernate.annotations.Entity(dynamicInsert=true, dynamicUpdate=true)
public class Category {
...
}
  • 아래에 있는 하이버네이트의 Entity 애노테이션이 위에 있는 Entity를 확장한다.

'Hibernate > Chapter 4' 카테고리의 다른 글

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


주키 정하기

Hibernate/Chapter 4 : 2008.01.14 17:04


Natural key vs Surrgate key

  • 후보키candidate key는 다음과 같은 특징을 가진다.
    • NULL 값을 갖지 않는다.
    • 유일한 값을 갖는다.
    • 값이 절대로 변하지 않는다.
  • A natural key is a key with business meaning: an attribute or combination of attributes that is unique by virtue of its business semantics.
  • Natural key를 주키로 사용해 왔지만, 다음과 같은 문제가 있다.
    • 변하지 않고, 고유하면서, 필수인 값을 찾기가 어렵다. 주키 값을 변경하는 작업은 완전 빡쎄며, 인덱스로 사용하기도 적절하지 않다.
    • 주로 복합키로 구성되는데, 이 것들이 보통 쿼리 작성, 스키마 수정, 유지보수를 어렵게 한다.
  • 그래서 Surrogate key 사용을 추천한다.
    • Surrogate keys have no business meaning—they're unique values generated by the database or application.

key generator 선택하기

  • Hibernate has several built-in identifier-generation strategies.
Generator name JPA Generation Type Option 설명
native AUTO   사용하는 DB에 따라서 sequence, hilo, identity를 알아서 선택함. 설정의 이식성을 고려한다면, 이 설정을 사용할 것.
identity IDENTITY   DB2, MySQL, MS SQL Server, Sybase, HypersonicSQL에 있는 identity 컬럼을 지원한다. long, short, int 타입의 값을 반환함.
sequence SEQUENCE sequence, parameters DB2, PostgreSQL, Oracle, SAP DB, Mckoi에서 sequence를 생성한다. long, short, int 타입의 값을 반환함. sequence 옵션을 사용해서 시퀀스의 이름을 설정할 수 있고, DDL에 추가할 시퀀스를 만들 때 필요한 추가 세팅이 필요할 때 parameters를 사용함.
increment     하이버네이트가 동작하면서 테이블의 주키 컬럼 값 중에 최대값을 읽은 다음 새로운 레코드를 추가할 때, 그 값을 1씩 증가시킴. 단일 서버에서 DB에 독립적으로 접근하는 경우 외에는 사용하지 말아라.
hilo   table, column, max_lo A high/low algorithm is an efficient way to generate identifiers of type long, given a table and column as a source of high values.
seqhilo   sequence, parameters, max_lo named database sequence에서 high 값을 걷는 것을 빼고 hilo와 동일하다.
  TABLE table, catalog, schema, pkColumnName, valueColumnName, pkColumnValue, allocationSize TABLE relies on a database table that holds the lastgenerated integer primary key value, and each generator is mapped to one row in this table.
uuid.hex   separator This generator is a 128-bit UUID (an algorithm that generates identifiers of type string, unique within a network).
guid     This generator provides a database-generated globally unique identifier string on MySQL and SQL Server.
select   key This generator retrieves a primary key assigned by a database trigger by selecting the row by some unique key and retrieving the primary key value
하이버네이트 identity generator 사용하기
@Entity
@org.hibernate.annotations.GenericGenerator(name="hibernate-uuid", strategy="uuid")
@Table(name="CATEGORY")
public class Category {

@Id
@GeneratedValue(generator="hibernate-uuid")
@Column(name="CATEGORY_ID")
private Long id;

public Long getId() {
return id;
}

}
  • hibernate-uuid라는 이름으로 uuid 생성기를 사용하는 코드.
  • You aren't limited to the built-in strategies; you can create your own identifier generator by implementing Hibernate's IdentifierGenerator interface.

'Hibernate > Chapter 4' 카테고리의 다른 글

기본 속성 맵핑하기- 실습  (2) 2008.01.22
Hibernate VS JPA  (2) 2008.01.20
컴포넌트 맵핑하기  (0) 2008.01.20
기본 속성 맵핑하기  (2) 2008.01.20
작명 지침 사용하기  (0) 2008.01.20
SQL문에 따옴표 사용하기  (0) 2008.01.20
패키지 이름 설정하기  (0) 2008.01.20
쿼리에서 사용할 Entity 이름 설정하기  (0) 2008.01.20
Immutable Entity 만들기  (0) 2008.01.20
동적 SQL 생성  (0) 2008.01.20
주키 정하기  (0) 2008.01.14
top


XML 도메인 모델

Hibernate/Chapter 3 : 2008.01.13 12:40


특징

  • The XML data model is weak, its type system is complex and underpowered.
  • its data integrity is almost completely procedural.
  • it introduces hierarchical data structures that were outdated decades ago.
  • However, data in XML format is attractive to work with in Java; we have nice tools.

XML로 도메인 모델 뽑아내기

DOM4J로 도메인 모델 뽑아내기
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Element userXML =
(Element) dom4jSession.load(User.class, storedUserId);
  • Element 클래스는 Dom4J API
화면에 출력하기
try {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter( System.out, format);
writer.write( userXML );
} catch (IOException ex) {
throw new RuntimeException(ex);
}

맵핑할 때 node 속성 사용하기

  • <class> 나 <property> 맵핑에서의 node 속성(node="name")은 XML 엘리먼트의 이름을 정의한다.
  • <property> 맵핑에서 node 속성(node="@name")은 XML 엘리먼트의 속성을 정의한다.
  • <property> 맵핑에서의 node 속성(node="name/@attname")은 name이라는 자식 엘리먼트에 attname이라는 속성을 정의한다.
  • 위의 속성을 사용해서 맵핑하면, 도메인 모델을 표현할 XML을 원하는 형태로 정의할 수 있다.

'Hibernate > Chapter 3' 카테고리의 다른 글

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Map 도메인 모델

Hibernate/Chapter 3 : 2008.01.13 12:05


특징

  • A dynamic domain model is a model that is dynamically typed.
<hibernate-mapping>
<class entity-name="ItemEntity" table="ITEM_ENTITY">
<id name="id" type="long" column="ITEM_ID">
<generator class="native" />
</id>
<property name="initialPrice" type="big_decimal"
column="INIT_PRICE" />
<property name="description" type="string" column="DESCRIPTION" />
<many-to-one name="seller" entity-name="UserEntity"
column="USER_ID" />
</class>
<class entity-name="UserEntity" table="USER_ENTITY">
<id name="id" type="long" column="USER_ID">
<generator class="native" />
</id>
<property name="username" type="string" column="USERNAME" />
<bag name="itemsForSale" inverse="true" cascade="all">
<key column="USER_ID" />
<one-to-many entity-name="ItemEntity" />
</bag>
</class>
</hibernate-mapping>
  • 다수의 도메인 맵핑을 하나의 파일 안에 두고 있다. 자바 클래스를 맵핑하는 것이 아니기 때문에 메타데이터를 어떻게 구성하던 맘대로 하라.
  • <class name="..."> 대신에 <class entity-name="..."> 를 사용했으며, 정적인 도메인 모델과 구분하기 위해 Entity를 접미어로 사용했다.
  • <many-to-one> 와 <one-to-many> 에서 entity-name에 설정한 이름을 사용했다.

동적인 맵 사용하기

동적인 맵 사용 예제
Map user = new HashMap();
user.put("username", "johndoe");

Map item1 = new HashMap();
item1.put("description", "An item for auction");
item1.put("initialPrice", new BigDecimal(99));
item1.put("seller", user);

Map item2 = new HashMap();
item2.put("description", "Another item for auction");
item2.put("initialPrice", new BigDecimal(123));
item2.put("seller", user);

Collection itemsForSale = new ArrayList();
itemsForSale.add(item1);
itemsForSale.add(item2);
user.put("itemsForSale", itemsForSale);

session.save("UserEntity", user);
  • Entity 하나 당 HashMap 객체 하나에 대응한다.
  • ArrayList는 bag을 맵핑하려고 사용했다.
  • Session.save(entity-name, HashMap)를 사용해서 저장했다.
  • cascading에 의해서 user와 user와 연관을 맺고 있는 두 개의 Item 역시 DB에 저장됐다.
  • Set을 사용하면 안 된다. Map은 equals()를 할 때 키값을 가지고 비교하기 때문에, Set을 사용하면 여러 개의 Entity를 넣을 수 없다.

정적인 엔티티 모드와 동적인 엔티티 모드 혼용하기

  • 맵핑할 때, <class name="model.UserPojo" entity-name="UserEntity" table="USER_ENTITY"> 이런식으로 클래스이름과 논리적인 이름을 모두 설정해 준다.
  • Session을 사용할 때는 entity-name을 사용해야 한다.
  • Session의 결과로 받는 값은 기본으로 POJO 객체다.
  • 둘 모두 <property name="default_entity_mode">dynamic-map</property> 를 사용해서 Map을 사용하도록 설정할 수 있다.
  • 특정 세션만 Map을 사용하도록 설정할 수 있다. Session dynamicSession = session.getSession(EntityMode.MAP);
  • Note that you can't link a map with a POJO instance. 당근이지.

하나의 클래스 여러번 맵핑하기

  • 맵핑 할 때 entity-name에 다른 값을 주면, 같은 클래스를 사용해서 서로 다른 테이블로 맵핑할 수 있다.
<hibernate-mapping>
<class name="model.Item" entity-name="ItemAuction"
table="ITEM_AUCTION">
<id name="id" column="ITEM_AUCTION_ID">...</id>
<property name="description" column="DESCRIPTION" />
<property name="initialPrice" column="INIT_PRICE" />
</class>
<class name="model.Item" entity-name="ItemSale" table="ITEM_SALE">
<id name="id" column="ITEM_SALE_ID">...</id>
<property name="description" column="DESCRIPTION" />
<property name="salesPrice" column="SALES_PRICE" />
</class>
</hibernate-mapping>

'Hibernate > Chapter 3' 카테고리의 다른 글

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Entity 표현 대안

Hibernate/Chapter 3 : 2008.01.13 11:59



  • 꼭 POJO로 Entity를 표현하지 않아도 된다.
  • 자바의 HashMap을 사용하여 Entity를 표현할 수 있다.
  • Dom4J를 사용하여 Entity를 표현할 수 있다.

Map 도메인 모델

XML 도메인 모델

'Hibernate > Chapter 3' 카테고리의 다른 글

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Using placeholders

Hibernate/Chapter 3 : 2008.01.13 11:57


특징

  • you can call any native SQL function or keyword your database system supports.
  • The disadvantage of putting native SQL in your mapping metadata is lost database portability.
  • One way to deal with this issue is to use a placeholder in your XML file that is replaced during build when the mapping files are copied to the target directory.

Placeholder

<id name="id" column="CATEGORY_ID" type="long">
<generator class="&idgenerator;"/>
</id>
  • &idgenerator; 값을 Entity placeholder라고 부른다. 이 값을 XML 파일의 상단에 문서 타입 정의의 일부분으로 선언할 수 있다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
[
<!ENTITY idgenerator "auction.custom.MyOracleGenerator">
]>
  • 맵핑 파일을 읽어들일 때, XML 파서는 placeholder를 위에 선언한 값으로 대체한다.
  • 선언 부분을 별도의 DTD 파일로 한 단계 더 빼낼 수 있고, 원래 자리에는 dtd 파일을 참조하도록 global 옵션을 사용할 수 있다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping SYSTEM
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
[
<!ENTITY % globals SYSTEM "classpath://persistence/globals.dtd">
%globals;
]>
  • 모든 전역적인 옵션을 DTD 파일로 빼낼 수 있다.
  • 다수의 속성이 여러 클래스에 중복되서 나타나지만, 상속을 사용할 수 없을 때는 XML 덩어리를 별도의 파일로 빼내서 다른 XMl 파일들에 포함 시킬 수도 있다.

'Hibernate > Chapter 3' 카테고리의 다른 글

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Global annotation metadata

Hibernate/Chapter 3 : 2008.01.13 11:56


Package Metadata

  • it's enabled with a file named package-info.java in a particular package directory
애노테이션 글로벌 설정
@org.hibernate.annotations.TypeDefs( {
@org.hibernate.annotations.TypeDef(name = "monetary_amount_usd", typeClass =
MonetaryAmountType.class, parameters = { @Parameter(name = "convertTo", value = "USD") }),
@org.hibernate.annotations.TypeDef(name = "monetary_amount_eur", typeClass =
MonetaryAmountType.class, parameters = { @Parameter(name = "convertTo", value = "EUR") }) })
@org.hibernate.annotations.NamedQueries( { @org.hibernate.annotations.NamedQuery(name =
"findItemsOrderByPrice", query = "select i from Item i order by i.initialPrice)") })
package auction.persistence.types;
  • declares two Hibernate type converters
  • 같은 방법으로 쿼리를 외부화 시키거나 전역 식별자 생성기를 정의할 수 있다.
  • JPA 애노테이션은 package-info.java 파일 안에서 사용할 수 없다.
  • If you need portable global Java Persistence metadata, put it in an orm.xml file.
  • Global annotations (Hibernate and JPA) can also be placed in the source code of a particular class, right after the import section.

모르는 것

  • package-info.java는 '-' 문자 때문에 에러나는데.. 흠;; 어쩌라는 거지?
  • Global 애노테이션을 아무곳에나 놓을 수 있다고? 그럼 package-info.java 파일은 뭐지;; 왜 거기에 넣으라고 한거지?

'Hibernate > Chapter 3' 카테고리의 다른 글

Hibernate Core와 Java Persistence and EJB 3.0  (0) 2008.01.20
XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
top


Global XML mapping metadata

Hibernate/Chapter 3 : 2008.01.13 11:55


<hibernate-mapping>

<hibernate-mapping
schema="AUCTION"
default-lazy="false"
default-access="field"
auto-import="false">

<class ...>
...
</class>

</hibernate-mapping>
  • schema: 스키마 접두어로 사용한다. used by Hibernate for all SQL statements generated for the mapped classes.
  • default-lazy: 이 속성을 false로 하면, you enable default outer-join fetching for some class associations.
  • default-access: 이 속성의 값을 field로 하면, 하이버네이트가 이 파일 내부에 정의한 클래스의 필드에 바로 접근할 수 있다.
  • auto-import: 4장에서 다룸.

Tip

  • This default-lazy="true" switch has an interesting side effect: It switches to Hibernate 2.x default fetching behavior—useful if you migrate to Hibernate 3.x but don't want to update all fetching settings.

모르는 것

  • 스키마 접두어가 뭐지? Whiteship_Member, Whiteship_Group 뭐 이러식으로 테이블 이름이랑 컬럼 이름을 사용한다는 건가?
  • default outer-join fetching은 뭐지?

'Hibernate > Chapter 3' 카테고리의 다른 글

XML 도메인 모델  (0) 2008.01.13
Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
Accessor 메소드에 로직 추가하기  (0) 2008.01.09
top


Handling global metadata

Hibernate/Chapter 3 : 2008.01.13 11:53


전역적인 메타데이타
  • query strings can be externalized to metadata and called by a globally unique name in the application code.
  • a query usually isn't related to a particular class, and sometimes not even to a particular package.
  • Other application-scoped metadata includes user-defined mapping types (converters) and data filter (dynamic view) definitions.
Global XML mapping metadata

Global annotation metadata

Using placeholders

'Hibernate > Chapter 3' 카테고리의 다른 글

Map 도메인 모델  (0) 2008.01.13
Entity 표현 대안  (0) 2008.01.13
Using placeholders  (0) 2008.01.13
Global annotation metadata  (0) 2008.01.13
Global XML mapping metadata  (0) 2008.01.13
Handling global metadata  (0) 2008.01.13
XDoclet 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
애노테이션 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
XML 사용하기 - 하이버네이트 맵핑  (0) 2008.01.11
Accessor 메소드에 로직 추가하기  (0) 2008.01.09
POJO 관계 구현하기  (0) 2008.01.09
top


XDoclet 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:47


XDoclet

  • XDoclet leverages the Javadoc tag format (@attribute) to specify class-, field-, or method-level metadata attributes.
  • XDoclet is implemented as an Ant task that generates Hibernate XML metadata (or something else, depending on the plug-in) as part of the build process.

하이버네이트 XML 생성

XDoclet 사용
/**
* The Category class of the CaveatEmptor auction site domain model.
*
* @hibernate.class table="CATEGORY"
*/
public class Category {
...
/**
* @hibernate.id generator-class="native" column="CATEGORY_ID"
*/
public Long getId() {
return id;
}
...
/**
* @hibernate.property
*/
public String getName() {
return name;
}
...
}

단점

  • 별도의 Ant 태스크 필요해.
  • 배포 할 때마 설정을 좀 바꿔야 할 수도 있어.
  • 개발 환경에서 XDoclet Validation을 수행할 수 없지만, 최근 IDE는 최소한 자동 완성을 제공 해준다.
top


애노테이션 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:46


Annotation

  • JDK 5.0에 추가된 기능으로 JDK 1.4이하에서는 XDoclet 이라는 주석에 사용하는 애노테이션을 사용했었다.
  • type-safe and declared interfaces for the definition of annotations.
  • Autocompletion and compile-time checking are no longer an issue.
  • it has better defaults

Annotation 만들기

Entity 애노테이션 정의
package javax.persistence;

@Target(TYPE)
@Retention(RUNTIME)
public @interface Entity {
String name() default "";
}
  • @Target(TYPE)은 메타데이터의 메타데이터로, Entity 애노테이션이 Type위에만 붙일 수 있다는 것을 설정.
  • @Retention(RUNTIME)은 Entity 애노테이션을 하이버네이트가 런타임에도 읽을 수 있도록 보유 정책 설정.
  • 속성과 기본 값 설정할 수 있음.

Annotation 사용하기

Entity 애노테이션 사용
package auction.model;

import javax.persistence.*;

@Entity
@Table(name = "ITEM")
public class Item {
...
}
  • 애노테이션을 사용하면 소스를 수정할 때 같이 리팩터링 할 수 있기 때문에 좋다.

Utilizing vendor extensions

  • fetching and caching settings, are only available as Hibernate-specific annotations.
하이버네이트의 애노테이션 사용하기
package auction.model;

import javax.persistence.*;

@Entity
@Table(name = "ITEM")
@org.hibernate.annotations.BatchSize(size = 10)
@org.hibernate.annotations.DiscriminatorFormula(
"case when ITEM_IS_SPECIAL is not null then A else B end"
)
public class Item {
...
}
  • @BatchSize는 패칭 옵션.
  • @DiscriminatorFormula is especially useful for legacy schemas when class inheritance can't be determined with simple literal values.
  • JPA 표준 애노테이션이 아닌 특정 밴더가 제공하는 애노테이션 앞에는 전체 패키지 이름을 써주는 것이 좋다. 그래야 나중에 밴더가 바뀌더라도 해당 부분만 바꾸기 쉽기 때문이다.
  • 이 애노테이션들은 특정 클래스에 종속적인데, 간혹 다수의 클래스에 적용하고 싶은 메타데이터가 있을 수도 있다.

JPA XML descriptor

  • XML deployment descriptors in certain situations, especially for configuration metadata that changes with each deployment.
  • every annotation in EJB 3.0 and JPA can be replaced with an XML descriptor element
XML descriptor
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0">
<persistence-unit-metadata>
<xml-mapping-metadata-complete />
<persistence-unit-defaults>
<schema>MY_SCHEMA</schema>
<catalog>MY_CATALOG</catalog>
<cascade-persist />
</persistence-unit-defaults>
</persistence-unit-metadata>
<package>auction.model</package>
<entity class="Item" access="PROPERTY" metadata-complete="true">
<attributes>
<id name="id">
<generated-value strategy="AUTO" />
</id>
</attributes>
</entity>
</entity-mappings>
  • This XML is automatically picked up by the JPA provider if you place it in a file called orm.xml in your classpath, in the META-INF directory of the persistence unit.
  • 애노테이션 설정을 완전히 무시할 수도 있고, 오버라이딩 하게 할 수도 있다.
  • 하이버네이트 XML 맵핑 파일과 호환되지 않는다.
  • 하이버네이트 XML 맵핑을 사용하면 JPA XML Descriptor보다 더 다양한 맵핑 정보를 표현할 수 있다.
  • 하지만 하이버네이트 XML 맵핑으로 애노테이션을 오버라이딩 할 수는 없다.

모르는 것

  • 애노테이션이 Type-safe 하다는 것이 무슨 뜻일까?
  • @org.hibernate.annotations.BatchSize(size = 10) 무슨 뜻일까?
  • @org.hibernate.annotations.DiscriminatorFormula(
    "case when ITEM_IS_SPECIAL is not null then A else B end"
    ) 무슨 뜻일까?
top


XML 사용하기 - 하이버네이트 맵핑

Hibernate/Chapter 3 : 2008.01.11 11:46


단점

  • Metadata is not, by nature, more flexible or maintainable than plain Java code.
  • Many existing metadata formats weren't designed to be readable and easy to edit by hand. 적절한 기본값을 제공해주지 않아서 필요 이상의 타이핑이 필요하다. 속성없이 엘리먼트만 사용하는 경우도 있다.
  • Good XML editors, especially in IDEs, aren't as common as good Java coding environments. DTD가 제공되지 않아서 자동완성과 검증 기능을 사용하지 못하는 경우가 있다.

하이버네이트의 XML

  • 위의 모든 단점을 고려했다.
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

<class name="auction.model.Category" table="CATEGORY">
<id name="id" column="CATEGORY_ID" type="long">
<generator class="native"/>
</id>
<property name="name" column="NAME" type="string"/>
</class>

</hibernate-mapping>
  • 여러 클래스 맵핑 정보를 하나의 파일 안에 모두 두는 것도 가능하지만 클래스 당 매핑 파일 하나를 권장한다.
  • 맵핑 파일은 클래스와 같은 패키지에 놓는것을 권장한다.
top


Accessor 메소드에 로직 추가하기

Hibernate/Chapter 3 : 2008.01.09 16:43


Setter 메소드에 Validation 로직 추가.

  • 하이버네이트가 DB에서 데이터를 가져올 때 이 Setter 메소드를 사용하여 속성을 설정하는데, 그럴 경우에는 validation을 하지 않고 변수에 직접 접근하도록 설정할 수 있다. 어떻게? p122 첫 줄.

Getter 메소드에서 복사체 전달.

  • 하이버네이트는 Dirty Checking을 하기 때문에, Persistent 상태의 객체 속성의 변경을 DB에 반영하기 위해 UPDATE문을 자동으로 실행한다.
  • Getter에서 같은 값의 다른 객체를 반환하더라도 불필요한 Update문을 실행하지 않는다.
다른 객체 반환하는 Getter
public String getFirstname() {
return new String(firstname);
}
  • Hibernate compares the objects by value—not by object identity—to determine whether the property's persistent state needs to be updated.
  • 하지만 Collection일 경우에는 예외이며, 이 경우 같은 객체들을 가진 다른 Collection 객체를 반환하면, 불필요한 UPDATE 문을 실행한다.
다음과 같이 하지 말 것
public void setNames(List namesList) {
names = (String[]) namesList.toArray();
}
public List getNames() {
return Arrays.asList(names);
}

예외 던지기

  • Runtime Exception이 발생하면, 트랜잭션을 롤백하고 Checked Exception이 발생하면, 하이버네이트가 잡아서 Runtime Exception으로 랩핑한다.
참조 : Java Persistence With Hibernate
top


POJO 관계 구현하기

Hibernate/Chapter 3 : 2008.01.09 16:43


Scaffolding code

  • 연관을 맺기 위해 필요한 필드와 메소드.

1:다 관계

  • 다수를 가질 경우, Hibernate requires interfaces for collection-typed attributes
  • 양방향일 경우, 해당 타입의 속성이 필요함.
  • 연결하기: 두 가지 행위가 필요함.
  • Hibernate doesn't manage persistent associations. If you want to manipulate an association, you must write exactly the same code you would write without Hibernate.
  • Convenient Method 도입하기:
1:다 관계
public void addChildCategory(Category childCategory) {
if (childCategory == null)
throw new IllegalArgumentException("Null child category!");
if (childCategory.getParentCategory() != null)
childCategory.getParentCategory().getChildCategories().remove(childCategory);
childCategory.setParentCategory(this);
childCategories.add(childCategory);
}
    • reduces the lines of code
    • enforces the cardinality of the association

다:다 관계

  • both sides are implemented with collection-valued attributes.
  • Convenient Method
다:다 관계
public void addCategory(Category category) {
if (category == null)
throw new IllegalArgumentException("Null category");
category.getItems().add(this);
categories.add(category);
}
  • You can also add logic to your accessor methods.

참조 : Java Persistence With Hibernate
top


하이버네이트와 POJO

Hibernate/Chapter 3 : 2008.01.09 16:41


하이버네이트는 Pesistent 클래스가 Serializable 인터페이스를 구현하도록 강요하지 않지만, 객체가 HttpSession에 저장되어야 하거나 RMI를 사용하여 전송할 것이라면 구현해야한다.

JavaBeans 스펙은 특정 생성자를 필요로 하지 않지만, 하이버네이트(와 JPA)에서 모든 Persistent Class들은 인자가 없는 기본 생성자를 필요로 한다.

생성자는 public이 아니여도 괜찮지만, 만약에 프록시를 사용할 거라면, 최소한 package-visivle(public, protected, default 접근 지시자 사용 가능)해야한다.

프록시를 생성할 때는 클래스가 final이여서도 안되고 final 메소드를 가지고 있어도 안 된다!

Persistent Class 객체들의 상태를 어떻게 하이버네이트가 영속화할지는 필드에 직접 접근하거나 게터, 세터 메소드를 사용하는 방법 중에 선택할 수 있다.

참조 : Java Persistence With Hibernate
top


Transparent and automated persistence

Hibernate/Chapter 3 : 2008.01.09 16:31


Transparent

  • 도메인 모델의 영속성 클래스와 영속성 로직의 완전한 분리. transparent to mean a complete separation of concerns between the persistent classes of the domain model and the persistence logic, where the persistent classes are unaware of—and have no dependency on—the persistence mechanism.
  • Transparent persistence improves code readability and maintenance, as you'll soon see.
  • Testability is a basic requirement for applications with rich domain models
  • Transparent persistence fosters a degree of portability

Automatic

  • 자주 사용하는 SQL과 JDBC API사용으로부터 사용자를 해방시켜준다는 것을 의미한다.

하이버네이트의 투명성

  • 도메인 클래스가 별도의 인터페이스를 구현하거나 상위 클래스를 상속 받지 않아도 된다.
  • 도메인 클래스를 영속성 문맥 밖에서도 사용 할 수 있다.
  • objects aren't aware of the underlying data store.
참조 : Java Persistence With Hibernate
top

TAG hibernate

관심사 분리Seperation Of Concern

Hibernate/Chapter 3 : 2008.01.09 16:30


도메인에서 분리되어야 하는 이유

  • The domain model implementation is usually a central, organizing component; it's reused heavily whenever you implement new application functionality. For this reason, you should be prepared to go to some lengths to ensure that concerns other than business aspects don't leak into the domain model implementation.

관심사 누수leakage of concern

  • You shouldn't put code that addresses these crosscutting concerns in the classes that implement the domain model. When these concerns start to appear in the domain model classes, this is an example of leakage of concerns.
  • EJB 컨테이너가 interseption을 사용해서 몇몇 leakage of concern을 해결했지만, EJB 2.1에서 도메인에 많은 규칙과 제약을 부과하는 바람에 관심사 누수가 생겼다. 이 경우에는 컨테이너 구현 관심사가 누수 됐다. EJB 3.0은 이것을 반영해서 다시 비침략적nonintrusive이고 훨씬 전통적인 JavaBean 프로그래밍 모델에 가까워졌다.

하이버네이트의 관심사

  • Hibernate is a solution for just one of these concerns: persistence.
  • Hibernate persistent classes and the EJB 3.0 entity programming model offer transparent persistence. Hibernate and Java Persistence also provide automatic persistence.
참조 : Java Persistence With Hibernate
top

TAG hibernate

하이버네이트를 쓰려면 게터 세터가 꼭 필요하다.

Hibernate/study : 2007.12.26 14:58


뻥입니다. 보통 게터 세터를 많이 만들어서 사용하기때문에 이렇게 생각할 수도 있겠습니다. 하지만 미신입니다.

필드에 직접 접근할 수 있습니다.

코딩으로 검증작업은 찬욱군이 해주었습니다.

저는 구글링으로 검증을 해보았습니다.
바로 hibernate-mapping default-access="field" 이런 설정이 검색되었습니다. 하이버네이트 레퍼런스 5.1.2. hibernate-mapping 부분의 설정에 보면 위의 설정이 있습니다.

찬욱군 블로그의 Hibernate 기초 학습[6] - AccessType / fomula 이 글을 보시면 다양한 설정 방법을 참조하실 수 있습니다.
top


JPA @Transient

Hibernate/Annotation : 2007.09.27 16:46


@Entity 애노테이션이 붙은 클래스의 모든 속성들은 기본으로 모두 테이블의 필드로 생성하게 됩니다. 만약 어떤 속성을 테이블의 필드로 만들고 싶지 않다면, @Transient 애노테이션을 해당 속성 또는 해당 속성의 getter위에 붙여주면 됩니다.

@Entity
public class Member {
    private Long memberId;
    private String password;
    @Transient
    private String confirmPassword;
    ...
}

회원가입을 할 때 확인하는 패스워드의 경우 제대로 입력했는지 확인하기 위해서 한 번 더 입력을 하는데, 이러한 속성은 DB에 저장할 필요가 없기 때문에, @Transient로 설정해 줄 수 있습니다.

'Hibernate > Annotation' 카테고리의 다른 글

@CollectionOfElements 애노테이션  (0) 2008.09.19
Table 애노테이션  (0) 2008.06.19
JPA @Transient  (0) 2007.09.27
JPA @JoinColumn  (1) 2007.09.22
JPA @ManyToOne  (0) 2007.09.22
JPA @OneToMany  (0) 2007.09.22
top


JPA @JoinColumn

Hibernate/Annotation : 2007.09.22 15:18


참조 :http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html#JoinColumn
링크에 내용이 상당히 많아서 정리는 나중에 하기로 하고...

사용자 삽입 이미지

이름이 암시 하듯이 Join 컬럼 설정을 할 때 사용합니다. 위의 관계에서 Post에 Catergory 의 주키를 외례키로 가짐으로써 Join을 하고 있으니... Post Entity의 getCategory()에 @JoinColumn을 붙여 줍니다.

그러면 Post 테이블을 만들 때 join column 이름을 기본으로 Entity 명 + 언더바 + 주키 를 사용합니다.

public class Category {

    private Long categoryId;

    ..
}

현재 Category 클래스가 위와 같기 때문에 외례키(join column)이 categoty_categoryId 와 같은 형태로 생기게 됩니다. 별로 멋진 이름은 아닌 것 같으니 다음과 같이 설정해 줍니다.

    @ManyToOne(fetch=FetchType.LAZY, optional=false)
    @JoinColumn(name="categoryId")
    public Category getCategory() {
        return category;
    }

그리고  이전 글에서 잠시 고민했었던 cascading 설정은 Category를 지우면 해당 Categorry에 모든 Post마저 삭제 되도록 Category에 설정해 주겠습니다. 이밖에도 모든 cascading을 적용하도록 아예 all로 하겠습니다.

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "category", cascade = { CascadeType.ALL })
    public Set<Post> getPosts() {
        if (posts == null)
            posts = new HashSet<Post>();
        return posts;
    }

자 이제 설정은 마쳤고 제대로 설정을 한 건지, 원하는 대로 동작 하는지 테스트를 해봐야겠습니다.

'Hibernate > Annotation' 카테고리의 다른 글

@CollectionOfElements 애노테이션  (0) 2008.09.19
Table 애노테이션  (0) 2008.06.19
JPA @Transient  (0) 2007.09.27
JPA @JoinColumn  (1) 2007.09.22
JPA @ManyToOne  (0) 2007.09.22
JPA @OneToMany  (0) 2007.09.22
top


JPA @ManyToOne

Hibernate/Annotation : 2007.09.22 14:58


참조 : http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html#ManyToOne
사용자 삽입 이미지

자 이번에는 Post쪽에서 생각해 보겠습니다. "하나의 Post는 하나의 Category와 연관을 맺고 있습니다." 그럼 1:1 인가요? ㅋㅋ 아니죠. "또 다른 하나의  Post가 위의 Post가 연관을 맺고 있는 Category와 연관을 맺을 수 있습니다." 따라서 다:1 즉 ManyToOne의 관계이 있습니다.

사용자 삽입 이미지

@ManyToOne에 설정할 수 있는 속성들은 위와 같습니다. 이 중에서 세 개는 이미 @OneToMany에서 살펴보았고, 새로운 것은 딱 하나 optional 이 있습니다.

optional 은 "부가적인", "임의의"란 뜻으로 해당 속성이 임의적으로 있을 수도 있고, 없을 수도 있는지를 설정하는 것 같습니다.

속성

설명

기본값

cascade

관계를 맺고 있는 타겟 쪽에 어떠한 persistence operation들을 연쇄적으로 적용하고 싶을 때 설정합니다.

 

ALL, MERGE, PERSIST, REFRESH, REMOVE 등의 값을 사용하여 여러 개의 cascade 속성을 설정할 수 있습니다.

 

참조무결성을 위한 설정으로 보이며, Hibernate @Cascade 를 사용하여 보다 다양한 cascade 옵션을 사용할 수 있습니다.

비어있는 CascadeType 배열

fetch

연관을 맺고 있는 Entity들을 요청하는 순간 가져오는 설정이 LAZY ,

 

해당 Entity를 가져올 때 미리 연관을 맺고 있는 Entity들까지 모두 가져오는 것이 EAGER 입니다.

FetchType.LAZY

optinal

해당 속성 또는 필드에 빈 값(null)이 들어갈 수 있는지 여부를 나타냅니다.

 

반드시 값이 필요하다면, true로 설정합니다.

true

targetEntity

만약 Generic을 사용하지 않은 Collection일 때는 이 속성을 관계의 주인이 되는 쪽 클래스로 설정해 주어야 합니다.

타입을 명시한 Collection을 사용했을 때는 해당 타입으로 사용합니다.


다시 예제로 돌아가서 Post가 owning entity인데, 이 녀석을 삭제하거나, 변경한다고 해서, Category도 삭제되거나 변경되어야 하지는 않아도 될 것 같습니다. 흠.. 오히려 Category를 삭제하면 Post들이 모두 삭제 되어야 할 것 같은데 그러면 Cattegory에서 cascade 속성을 설정해야 하나;; 흠...

Post 객체를 불러올 때 Post와 연관을 맺고 있는 Category도 가져와야 할 필요는 없어 보입니다.

Post는 꼭 어느 Category엔가에는 들어야 할 것이기 때문에 외례키가 null일 경우는 없을 것 같습니다.

위 정황을 종합하여 다음과 같이 설정할 수 있겠습니다.

@ManyToOne(fetch=FetchType.LAZY, optional=false)

public Category getCategory() {

       return category;

}


여기서 이만 끝나면 좋겠지만, 아직 끝나지 않았습니다. @JoinColumn 이라는 녀석을 붙여줘야 합니다. 다음 글에서 살펴보겠습니다.

'Hibernate > Annotation' 카테고리의 다른 글

@CollectionOfElements 애노테이션  (0) 2008.09.19
Table 애노테이션  (0) 2008.06.19
JPA @Transient  (0) 2007.09.27
JPA @JoinColumn  (1) 2007.09.22
JPA @ManyToOne  (0) 2007.09.22
JPA @OneToMany  (0) 2007.09.22
top


JPA @OneToMany

Hibernate/Annotation : 2007.09.22 14:35


참조 : http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-annotations.html#OneToMany
사용자 삽입 이미지
위와 같은 관계에 있을 때 Category도 자신에 속해있는 Post를 참조할 수 있고 Post도 자신이 속한 Category를 참조할 수 있다면 Java 코드는 다음과 같이 작성할 수 있습니다.

public class Category {

    private Long categoryId;

    private String categoryName;

    private Set<Post> posts;

    ...
}

public class Post {

    private Long postId;

    private Category category;
 
    ...
}

Category 입장에서 Post를 보면 "Category 하나는 여러 Post와 연관을 맺습니다." 따라서 OneToMany 관계 입니다.

@OneToMany 애노테이션을 getter위에 붙여 줍니다.
사용자 삽입 이미지
설정 할 수 있는 속성은 위에 보이는 것과 같이 네 개가 있습니다.

cascade의 사전적인 의미는 "작은 폭포" "계단식 정보 전달" 이라는 뜻이 있습니다. 이것으로 추축할 때 어느쪽 Entity에 영향을 주면 다른 쪽 Entity에도 어떤 영향을 줄 수 있는 설정이라는 것으로 생각할 수 있습니다.

fetch의 사전적인 의미는 "가지고 오다" "자아내다" 라는 뜻이 있습니다. 즉 해당 Entity를 불러올 때 연관을 맺고 있는 상대방(OneToMany이기 때문에 상대방은 Many쪽이 되겠죠.)들을 가져오는 것과 관련된 속성이라고 생각할 수 있습니다.

mappedBy는 "누군가에 의해 관계를 맺고 있다." 즉, 누군가 한테 종속되어 있다. 라는 설정으로 생각할 수 있겠습니다.

targetEntity는 연관을 맺고 있는 타겟을 지칭하는 듯해 보입니다.

속성

설명

기본값

cascade

관계를 맺고 있는 타겟 쪽에 어떠한 persistence operation들을 연쇄적으로 적용하고 싶을 때 설정합니다.

 

ALL, MERGE, PERSIST, REFRESH, REMOVE 등의 값을 사용하여 여러 개의 cascade 속성을 설정할 수 있습니다.

 

참조무결성을 위한 설정으로 보이며, Hibernate @Cascade 를 사용하여 보다 다양한 cascade 옵션을 사용할 수 있습니다.

비어있는 CascadeType 배열

fetch

연관을 맺고 있는 Entity들을 요청하는 순간 가져오는 설정이 LAZY ,

 

해당 Entity를 가져올 때 미리 연관을 맺고 있는 Entity들까지 모두 가져오는 것이 EAGER 입니다.

FetchType.LAZY

mappedBy

관계가 양방향 일 때는 mappedBy 속성에 관계의 주인이 되는 쪽에서 어떤 속성으로 접근을 하는지 설정해 줍니다.

if the relationship is unidirectional, the persistence provider determines the field that owns the relationship.

targetEntity

만약 Generic을 사용하지 않은 Collection일 때는 이 속성을 관계의 주인이 되는 쪽 클래스로 설정해 주어야 합니다.

타입을 명시한 Collection을 사용했을 때는 해당 타입으로 사용합니다.


다시 Category와 Post의 관계로 돌아가서...

Category와 Post 관계 중에 어느 쪽이 관계의 주인이 되는지 생각해 보겠습니다. "관계의 주인" 영어 문서에는 owner side, owning entity등으로 표햔을 하고 있는데, 아무래도 직관적으로 생각해 봤을 때 DB 테이블 간의 관계를 설정할 때 상대방의 주키를 자신의 외례키로 가지는 쪽을 말하는 것 같습니다.

위의 관계라면 Post 에서 Catergory를 외례키로 가지고 있을 것이기 때문에, Post를 owning entity로 볼 수 있습니다.

그리고 Category 엔티티를 읽어 올 때 거기에 딸려 있는 모든 Post를 미리 읽어오게 하고 싶지 않습니다. 그러면 Category 목록만 보고 있는데도 그 안에 딸려 있는 모든 Post들을 DB에서 가져오게 될 텐데 그러면 엄청나게 많은 부하가 생길 것 같기 때문입니다. 그래서 fetch의 기본값인 LAZY를 사용하겠습니다.

cascade 속성은 owning entity에서 설정해주면 될 것 같고, targetEntity는 사용할 필요가 없습니다. 저는 Generic을 사용했기 때문에 별도로 명시해줄 필요가 없습니다.

위의 상황을 종합하여 다음과 같이 설정할 수 있습니다.

@OneToMany(fetch=FetchType.LAZY, mappedBy="category")

public Set<Post> getPosts() {

       if(posts == null) posts = new HashSet<Post>();

       return posts;

}


지금 예제는 양방향 관계이기 때문에 Owning Entity쪽 즉 Post 클래스의 getCategory()에 @ManyTonOne 설정을 하도록 하겠습니다. 너무 길어서 다음글로 이어집니다.

'Hibernate > Annotation' 카테고리의 다른 글

@CollectionOfElements 애노테이션  (0) 2008.09.19
Table 애노테이션  (0) 2008.06.19
JPA @Transient  (0) 2007.09.27
JPA @JoinColumn  (1) 2007.09.22
JPA @ManyToOne  (0) 2007.09.22
JPA @OneToMany  (0) 2007.09.22
top


잘못 된 openSession() 사용 예제ㅋ

Hibernate/study : 2007.05.04 20:55


이전 글에서 DAO 구현을 다음과 같이 했었습니다.
public class MemberDaoImpleWIthSpringTransaction implements MemberDao{

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void add(Member member) {
        Session session = sessionFactory.getCurrentSession();
        session.save(member);
    }
}

여기서 빨간 색 부분은 찬욱군이 알려줬기 때문이고 원래는 아래처럼 코딩했었습니다.
    public void add(Member member) {
        Session session = sessionFactory.openSession(); //(1)
        session.save(member);
        session.flush(); //(2)
        session.close(); //(3)
    }

위에 표시한 빨간 부분이 모두 잘못된 부분이였습니다.

(1) 오픈 세션은 새로운 세션을 만들게 되고 그럼 새로운 트랜잭션에서 save를 실행하게 됩니다. 그런데 지금 저 코드는 새로운 트랜잭션이 아니라 Service Layer에서 사용하던 트랜잭션을 사용해야 합니다. 그러려면 새로운 세션이 아닌 getCurrentSession을 사용하면 기존에 존재하는 트랜잭션을 사용하게 됩니다.

(2) flush()는 무조건 DB에 저장하게 된다고 합니다. 따라서 삭제해야합니다. 지금 이 코드는 트랜잭션 내에 있고 예외가 발생하면 롤백해야 되니까 무조건 DB에 넣어버리는 flush()를 사용하면 안되겠습니다.

(3) getCurrentSession은 자기가 알아서 세션을 닫기 때문에 명시적으로 session을 닫아버리면 안됩니다.(에러가 나더군요.)

찬욱군 베리베리 땡큐 감사!!
top


Convention over Configuration

Hibernate/study : 2007.03.02 00:06


RoR을 공부해 본적은 없지만 조만간 운좋게 베타리더로 Rails for Java Developer를 접하게 될 것 같아서 공부하게 될 것 같습니다.

짧게나마 이해한 바로는 '설정보다 규약이 편하니까 규약으로 할 수 있는 건 규약으로 하자.'는 것 같습니다. 숙제3 에 있는 링크 중에 하나에 다음과 같은 그림이 있습니다.

사용자 삽입 이미지
장점 : 1. 새로운 개발자가 시스템을 빨리 이해할 수 있다. 2. 일관성을 높일 수 있다. 3. 보다 유연하다.

단점 : 1. 잘 알고 있어야 한다. 2. 프레임웤이 커진다. 3. 프레임웤이 새로운 규약을 도입했을 때 리팩토링이 힘들다.

단점 중에 3번이 가장 치면적인 것 같습니다. EJB였나.. 3.0으로 올리면서 어떤 속성의 default값을 바꿔서 온라인에서 개발자와 된통 싸웠다는 이야기를 들은 것 같은데 3번에 딱 맞는 예가 될 것 같습니다.[각주:1]

Spring에 CoC가 적용된 예로는 InternalResourceViewResolver, MethodNameResolver, ControllerClassNameHandlerMapping. 이런 것들이 있다고 합니다. 참조


  1. 자세한 내용은 찬욱이한테 들은 것 같긴한데 기억이 잘 안납니다. [본문으로]
top


숙제 3

Hibernate/study : 2007.03.01 23:43


Controller
- Spring reference :: Chapter 13
- Spring API :: Controller
- Spring MVC :: p52(71)
- Pro Spring :: p531
- 영회형 전 블로그 :: Spring MVC컨트롤러 탐험기[1] Controller와 ModelAndView

SimpleFormController
- Spring reference

more..

- Spring API :: SimpleFormController
- Spring MVC :: p65(84)
- Pro Spring :: p547

PropertyEditor
- Spring Reference :: Chapter 5
- Java API :: PropertyEditor
- 영회형 블로그 :: Spring 기본 지원 Property type
- 영회형 전 블로그 :: Spring MVC 사용시 다수의 문자열을 List로 받기
- Whiteship 전 블로그 ::  Spring reference 5장 정리
- Spring MVC :: p124(143)
- Pro Spring :: p126

CoC
- Convention over Configuration 의 약어로 "설정을 능가하는 규약" 정도의 의미.
- http://softwareengineering.vazexqi.com/files/pattern.html
- Convention vs Configuration
- CoC in Spring MVC

top


The paradigm mismatch

Hibernate/study : 2007.02.16 15:48


Hibernate를 공부하는 중인데요. 객체와 Relation간의 어떤 차이들이 있는 것인지 궁금해서 살짝 공부해 봤습니다.

The problem of graularity
=> 알갱의 크기가 달라서 생기는 문제

The problem of subtypes
=> 객체의 상속을 Relation에서 표현하기 위한 문제

The problem of identity
=> 객체와 그에 해당하는 row를 식별하는 문제

Problems relating to associations
=> 객체에서의 reference 연관과 Relation의 외례키를 사용한 연관의 차이

The problem of data navigation
=> DB의 성능을 높이기 위한 join과 persistence 객체의 fetching으로 인한 n+1 slelect 문제

'Hibernate > study' 카테고리의 다른 글

하이버네이트의 update() 와 merge()  (2) 2008.04.29
하이버네이트를 쓰려면 게터 세터가 꼭 필요하다.  (0) 2007.12.26
잘못 된 openSession() 사용 예제ㅋ  (0) 2007.05.04
Convention over Configuration  (0) 2007.03.02
숙제 3  (4) 2007.03.01
The paradigm mismatch  (0) 2007.02.16
The problem of data navigation  (0) 2007.02.16
Problems relating to associations  (0) 2007.02.16
The problem of identity  (0) 2007.02.16
The problem of subtypes  (0) 2007.02.14
The problem of graularity  (0) 2007.02.14
top


The problem of data navigation

Hibernate/study : 2007.02.16 15:04


참조 : Java Persistence With Hibernate

객체에서는 . 을 사용해서 다른 객체로 이동하곤 합니다. 하지만 SQL db에서 데이타를 이런식으로 가져오는 것은 효율적이지 않습니다.

db의 성능을 높이는 방법으로 SQL 쿼리 숫자를 줄이는 겁니다. 그래서 연관된 table 간의 join을 이용해서 data를 가져 옵니다.

만약에 Member에 있는 데이타만 관심이 있다면 Select * From member; 이렇게 하면 되겠지만 Member와 Messenger의 데이터에 모두 관심이 있다면 outter join을 이용해서 member를 가져와 두면 나중에 messenger의 데이터를 위해 쿼리를 날릴 필요가 없습니다.

하지만 Object persistence의 경우 객체에 처음 접근 할 때 fetching이라는 기능으로 연관된 객체를 붙여오는 기능을 제공하는데 이것은 각 노드 또는 콜렉션 마다 하나의 쿼리문을 실행하도록 요구하기 때문에 비효율적일 수 있습니다. 이것을 바로 무서운 n+1 selects problem 이라고 한다는 군요.

이 문제에 관해서는 13, 14, 15장에서 Hibernate가 제공해 주는 효율적이면서도 투명한 fetching 기능을 공부할 수 있을 것 같습니다.

'Hibernate > study' 카테고리의 다른 글

하이버네이트를 쓰려면 게터 세터가 꼭 필요하다.  (0) 2007.12.26
잘못 된 openSession() 사용 예제ㅋ  (0) 2007.05.04
Convention over Configuration  (0) 2007.03.02
숙제 3  (4) 2007.03.01
The paradigm mismatch  (0) 2007.02.16
The problem of data navigation  (0) 2007.02.16
Problems relating to associations  (0) 2007.02.16
The problem of identity  (0) 2007.02.16
The problem of subtypes  (0) 2007.02.14
The problem of graularity  (0) 2007.02.14
Custom Tag 만들기  (0) 2007.02.07
top


Problems relating to associations

Hibernate/study : 2007.02.16 13:17


참조 : Java Persistence With Hibernate

객체에서는 객체들의 관계를 reference를 사용해서 나타내지만 관계형 DB에서는 외례키로 나타내기 때문에[footnote]이밖에 데이타 무결성을 위해서도 사용된다.[/foonote] 발생하는 문제입니다.

방향성에 대한 차이
  • Object Reference는 고유의 방향성이 있다. 참조 하는 쪽과 참조 되는 쪽이 있다는 말인듯 합니다. 따라서 양방향성을 설정 하려면 두 번 설정해 줘야 합니다.
public class Member{
    private Set<Messenger> messengers;
}

public class Messenger{
    private Member member;
}
  • Foreign key를 사용한 관계는 정해진 방향성이 없다. 임의로 join이나 projection을 사용해서 연관을 맺을 수 있기 때문에 Navigation이 관계형 데이타 모델에 의미가 없다.

관계에 있어서 차이
  • Java에서는 다 : 다 관계를 표현할 수 있다. Java class를 보고 어떤 관계인지 알 수가 없다.
  • DB에서는 항상 1 : 다 또는 1 : 1 관계다. 외례키 정의한 부분을 보면 어떤 관계인지 알 수 있다.

'Hibernate > study' 카테고리의 다른 글

잘못 된 openSession() 사용 예제ㅋ  (0) 2007.05.04
Convention over Configuration  (0) 2007.03.02
숙제 3  (4) 2007.03.01
The paradigm mismatch  (0) 2007.02.16
The problem of data navigation  (0) 2007.02.16
Problems relating to associations  (0) 2007.02.16
The problem of identity  (0) 2007.02.16
The problem of subtypes  (0) 2007.02.14
The problem of graularity  (0) 2007.02.14
Custom Tag 만들기  (0) 2007.02.07
책을 샀습니다.  (0) 2007.02.04
top


The problem of identity

Hibernate/study : 2007.02.16 12:27


참조 : Java Persistence With Hibernate

Java에는 두 가지의 동일성에 대한 표현[각주:1]이 있고 DB에서의 row에 대한 identity는 주키로 나타내기 때문에 발생하는 문제 입니다.[각주:2]

9.2.2에 보시면 equals()와 hashCode()를 구현할 때 주의할 것들이 나옵니다.
  • equals()와 hashCode()를 테이블의 주키 값의 동일성으로 구현을 하면 transient 객체의 동일성 비교를 할 때 아직 id가 없는 상태이기 때문에 문제가 발생하며..
  • equlas()와 hashCode()를 테이블의 주키를 제외한 다른 모든 속성들의 값으로 구현을 하면 같은 row인데 속성하나가 바꼈다고 다른 row로 인식하거나.. 다른 row인데 값이 같다고 해서 같은 객체로 인식하는 문제가 발생합니다.
  • 그래서 business key를 사용하라는 내용이 있었습니다. 주키는 surrogate key를 사용하는데 둘다 유일한 값을 가지며 차이가 있다면 business key는 어떤 의미가 있는 값(ex. 학번, 주민번호)이 지만 surrogate key는 아무런 의미가 없이 DB에서 식별자 역할 만 한다는 겁니다.
주키를 정할 때 surrogate key로 정하는데 DB를에 row 식별을 위해 만든 속성을 domain model에 표현을 해야하는 건지..? 라는 질문을 던지고 있습니다. 여기에 대해서는 p162쪽 4.2.2에 보시면 Hibernate는 db identity를 application에서 두 가지 방법으로 표현할 수 있다고 합니다.
  • persistence 객체의 식별자 속성의 값으로
  • Session.getIdentifier(Object entity)의 리턴값으로
  1. Equality를 나타내는 equals()와 Object identity를 나타내는 == 이 있습니다. [본문으로]
  2. 단순히 동일성 표현 방법의 갯수가 차이 나서 그런 것은 아닙니다. [본문으로]

'Hibernate > study' 카테고리의 다른 글

Convention over Configuration  (0) 2007.03.02
숙제 3  (4) 2007.03.01
The paradigm mismatch  (0) 2007.02.16
The problem of data navigation  (0) 2007.02.16
Problems relating to associations  (0) 2007.02.16
The problem of identity  (0) 2007.02.16
The problem of subtypes  (0) 2007.02.14
The problem of graularity  (0) 2007.02.14
Custom Tag 만들기  (0) 2007.02.07
책을 샀습니다.  (0) 2007.02.04
DisplayTag1.1 예제 보기  (0) 2007.01.30
top




: 1 : 2 : 3 : 4 : 5 : 6 : 7 :