Whiteship's Note


Embedded 객체 맵핑하기

Hibernate/Chapter 6 : 2008.02.07 22:20


Embeddable 맵핑하기

@Embeddable
public class Image {

@Parent
private Item item;

@Column(length = 255, nullable = false)
private String name;

@Column(length = 255, nullable = false)
private String filename;

@Column(nullable = false)
private int sizeX;

@Column(nullable = false)
private int sizeY;
}
  • 모든 속성이 복합키로 사용되기 때문에, 모두 Not Null로 설정해주어야 한다.
  • back point 필요 없으면 @Parent 애노테이션 붙인 속성 없애면 된다.

컬렉션 맵핑하기

	@CollectionOfElements
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "IMAGE_ID"))
@CollectionId(columns = @Column(name = "ITEM_IMAGE_ID"),
type = @Type(type = "long"), generator = "sequence")
@AttributeOverride(name = "element.name",
column = @Column(name = "IMAGENAME", length = 255, nullable = false))
private Set<Image> images = new HashSet<Image>();
  • 컴포넌트의 속성을 재정의 할 수 있다.
  • 컴포넌트 속성이 Null을 포함하게 하려면, @CollectinoId()를 추가해주면 된다.
top


Sorted 콜렉션과 Ordered 콜렉션 맵핑하기

Hibernate/Chapter 6 : 2008.02.07 22:18


Sorted 타입 맵핑하기

  • @Sort 애노테이션을 사용해서, Sorter Set과 Sorted Map 타입으로 맵핑할 수 있다.
  • type 속성에서 Comparator를 사용할 수도 있다.
@CollectionOfElements
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID"))
@Column(name = "FILENAME")
@Sort(type = SortType.NATURAL)
private SortedSet<String> images = new TreeSet<String>();

Ordered 타입 맵핑하기

  • Map, Set 그리고 Bag을 DB에서 읽어올 때 정렬해서 가져올 수 있다.
  • 하이버 @OrderBy 애노테이션의 clause 속성의 값은 DB에 직접 전달되는 SQL이다.
@CollectionOfElements
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID"))
@Column(name = "FILENAME")
@OrderBy(clause = "FILENAME asc")
private Set<String> images2 = new HashSet<String>();
top


기본 콜렉션 맵핑하기

Hibernate/Chapter 6 : 2008.02.07 22:17


Set 타입 맵핑하기

  • 외례키를 포함하여 모든 컬럼을 복합키로 사용한다.
@CollectionOfElements(targetElement = java.lang.String.class)
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID"))
@Column(name = "FILENAME", nullable = false)
private Set<String> images = new HashSet<String>();

List 타입 맵핑하기

  • 컬렉션의 index를 주키로 사용하는 테이블을 정의한다.
  • base 속성으로 시작 index를 정할 수 있다. 기본은 0
@CollectionOfElements
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID"))
@IndexColumn(name = "POSITION", base = 1)
@Column(name="FILENAME")
private List<String> images2 = new ArrayList<String>();
  • 위 설정에서 @IndexColumn을 빼먹으면, Bag 타입으로 맵핑된다.

Map 타입 맵핑하기

  • 맵의 키가 복합 타입일 때는 해당 타입의 모든 속성을 키로 등록할 수 있다.
  • @MapKey는 JPA가 아니라 하이버 애노테이션이다.
@CollectionOfElements
@JoinTable(name = "ITEM_IMAGE", joinColumns = @JoinColumn(name = "ITEM_ID"))
@MapKey(columns = @Column(name = "IMAGENAME"))
@Column(name = "FILENAME")
private Map<String, String> images3 = new HashMap<String, String>();
top


컴포넌트 콜렉션

Hibernate/Chapter 6 : 2008.02.07 22:16


  • 일반 POJO로 구현하고, equals() 메소드에서 모든 속성을 비교해야 한다. 하이버가 dirty checking 할 때 사용한다.
  • Set으로 맵핑할 때는 컴포넌트의 모든 속성이 복합키로 사용되기 때문에, not-null 속성을 true로 해줘야 한다.
  • Parent 속성을 사용하면 컴포넌트가 자신을 소유한 쪽으로 네비게이션을 할 수 있다.(불완전 양방향 설정)
  • Collection 인터페이스와 ArrayList를 사용하거나, Map을 사용하면, equlas()와 hashmap()을 구현할 필요도 없고, nullable 컬럼을 가질 수도 있다.
top


콜렉션 인터페이스 선택하기

Hibernate/Chapter 6 : 2008.02.07 22:15


특징

  • 꼭 변수의 타입은 구현체가 아닌 인터페이스를 사용해야 한다. private <<Interface>> images = new <<Iimplementataion>>();
  • 콜렉션은 항상 바로 초기화를 하도록 한다.(권장사항)
  • 하이버네이트는 선언된 필드를 초기화 할 때 콜렉션을 감싼다.

콜렉션

  • java.util.Set -> java.util.HashSet: 중복을 허용하지 않고, 순서를 따지지 않는다. 가장 흔하게 사용되는 타입.
  • java.util.SortedSet -> java.util.TreeSet: 정렬 조건을 설정할 수 있다.
  • java.util.List -> java.util.ArrayList: 인덱스를 가지고 있다. 중복 허용한다.
  • java.util.Collection -> java.util.ArrayList: Bag을 맵핑할 때 사용한다. 중복을 허용하고 순서는 없다.
  • java.util.Map -> java.util.HashMap: 키, 값 쌍으로 맵핑되어 있다.
  • java.util.Sortedmap -> java.util.TreeMap: 정렬할 수 있다.
  • 배열: 배열 타입을 감쌀 수는 없다. 배열은 사용하지 않는게 좋겠다.(lazy loading, optimized dirty checking 등 이 밖에도 영속성 콜렉션을 다루는데 있어서 편리하고 성능을 높이는 기능들을 사용할 수 없다.)
top


Value Type의 Set, Bag, List, Map

Hibernate/Chapter 6 : 2008.02.07 22:14


  • Entity가 Value Type 객체 하나를 가지고 있을 때는 Entity를 저장한 테이블의 레코드에 같이 저장된다.
  • Value Type의 콜렉션과 연관을 맺고 있을 때는 별도의 테이블이 필요하다.
  • 콜렉션 인터페이스 선택하기
  • Sorted: 자바 메모리 상에서 정렬이 되는 것. Ordered: 데이터베이스 레벨에서 order by 절을 사용해서 정렬한다.
  • Bag, List는 Sorting을 설정할 수 없다. 인덱스가 있으니까... 대신 Order는 할 수 있다.
  • Set이나 Map을 Soring이 아닌 Order를 사용하고 싶을 때는 order-by 속성을 사용한다.(XML 설정)
top


Hibernate Core VS JPA

Hibernate/Chapter 5 : 2008.02.04 17:39


Hibernate JPA
네 가지 상속 맵핑 전략을 제공하고, 상속 전략을 혼용하는 것이 가능하다. 네 가지 맵핑 전략을 표준화 했다. 이 중에선 Table Per Class Hierarchy와 Table Per Subclass만 JPA 호환 필수요소다.
영속성 대상이 되는 클래스의 상위 클래스는 abstract class나 interface도 될 수 있다. abstract class만 이식 가능하다.
Value Type을 위한 유연한 내장 타입과 컴버터를 제공한다. 표준화된 방법으로 맵핑 타입을 자동으로 찾아 준다. 커스텀 타입을 찾을 때는 하이버네이트 확장 애노테이션을 사용한다.
막강한 타입 확장 시스템 Enum을 위한 내장 타입 표준이 필요하다.

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


Enum Type 맵핑하기 - 실습

Hibernate/Chapter 5 : 2008.02.04 17:35


1. 테스트 코드

more..


* 그냥 하나를 저장하고 그걸 다시 꺼내 봅니다. 꺼낼 때 get을 사용해도 되지만, 쿼리를 어떻게 작성해야 하는지 보기 위해서 HQL로 작성했습니다.

* 그냥 문자열일 뿐인데, 저걸 읽어서 Enum 타입을 알아내고 그것의 name()을 호출한 값으로 대체 해주는 하이버... 정말 똑똑하지 않나요. 대단합니다.

* 위 클래스에 있는 애노테이션들을 붙이면 Spring 2.5 전에 사용하던 AbstractTransactionalDataSource어쩌구저쩌구를 상속받은 클래스와 같은 녀석이 됩니다.(엄밀히 따지면 같지는 않습니다. applicationContext를 가지고 있지 않아서, 명시적으로 getBean() 할 수가 없습니다.)

2. Member 클래스와 MemberType 클래스

more..


* 별거 없습니다. id, membeType, name.

* MemberType은 매우 단순한 enum입니다.

* 주목해야 할 것은 MemberType 속성 위에 붙인 @Enumerated 애노테이션 입니다. 이녀석이 굉장한 일을해줍니다.

3. XML 설정

more..


* 역시나 뭐 별거 없습니다. 그냥 스프링+하이버 SessionFactory, TransactionManager, DataSource입니다.

4. 결과
Hibernate: insert into Member (id, TYPE, name) values (null, ?, ?)
Hibernate: call identity()
Hibernate: select member0_.id as id0_, member0_.TYPE as TYPE0_, member0_.name as name0_ from Member member0_ where member0_.TYPE='ADMIN'
id: 1 name: 기선 type: ADMIN

결과 쿼리를 보면 재밌습니다. 저는 그냥 @Enumerated 애노테이션 하나 붙였을 뿐인데, 알아서 ADMIN으로 저장해주고, HQL도 알아서 변경해 줍니다. 엘레강트 한 녀석입니다.

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


Enum Type 만들기

Hibernate/Chapter 5 : 2008.02.04 17:20


클래스 구현하기.

  • EnhancedUserType와 ParameterizedType 인터페이스를 구현한다.
private Class<Enum> enumClass;
    
    public void setParameterValues(Properties parameters) {
        String enumClassName =
            parameters.getProperty("enumClassname");
        try {
            enumClass = ReflectHelper.classForName(enumClassName);
        } catch (ClassNotFoundException cnfe) {
            throw new
              HibernateException("Enum class not found", cnfe);
        }
    }

    public Class returnedClass() {
        return enumClass;
    }

    public Object fromXMLString(String xmlValue) {
        return Enum.valueOf(enumClass, xmlValue);
    }

    public String objectToSQLString(Object value) {
        return '\'' + ( (Enum) value ).name() + '\'';
    }

    public String toXMLString(Object value) {
        return ( (Enum) value ).name();
    }

    public Object nullSafeGet(ResultSet rs,
                              String[] names,
                              Object owner)
            throws SQLException {
        String name = rs.getString( names[0] );
        return rs.wasNull() ? null : Enum.valueOf(enumClass, name);
    }

    public void nullSafeSet(PreparedStatement st,
                            Object value,
                            int index)
            throws SQLException {
        if (value == null) {
            st.setNull(index, Hibernate.STRING.sqlType());
        } else {
            st.setString( index, ( (Enum) value ).name() );
        }
    }
  • setParameterValues()는 클래스 이름 가져와서 Class 변수에 세팅한다.
  • fromXMLString(), objectToSQLString(), toXMLString()는 XML과 Enum의 value를 맵핑한다.
  • nullSafeGet()는 DB에서 value를 읽은 다음 Enum으로 반환한다.
  • nullSafeSet()는 Enum에서 DB로 저장할 value를 뽑아낸다.

맵핑하기

  • JPA의 경우 커스텀 타입 클래스 만들지 않고도 String으로 저장하거나, 선택된 Enum의 value를 저장할 수 있다.
public class Comment {
    ...
    @Enumerated(EnumType.STRING)
    @Column(name = "RATING", nullable = false, updatable = false)
    private Rating rating;
    ...
}

쿼리 작성하기

  • 다음과 같이 쿼리를 작성할 수 있다.
Query q =
    session.createQuery(
      "from Comment c where c.rating = auction.model.Rating.BAD"
    );
  • c.rating의 rating은 DB 컬럼의 이름이 아니라 객체의 속성이름이다.
"from Member m where m.memberType = '" + MemberType.ADMIN + "'"
"from Member m where m.memberType = chapter5.customType.example.MemberType.ADMIN"

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


ParameterizedType 만들기

Hibernate/Chapter 5 : 2008.02.04 17:20


클래스 구현하기

  • DB에 값을 저장할 때 특정 조건에 따라 다른 값으로 변환하여 저장할 필요가 있다면, 파라미터가 필요하다. 이럴 때 유요하다.
  • ParameterizedType 인터페이스를 구현한다.
private Currency convertTo;

	@Override
	public void setParameterValues(Properties parameters) {
		this.convertTo = Currency.getInstance(
                parameters.getProperty("convertTo"));
	}

맵핑하기

  • 같은 Value Type 클래스 타입의 객체들 여럿을 맵핑 할 때는 TypeDef 애노테이션을 사용해서, 전역에서 사용할 설정을 정의해 둘 수 있다.
@org.hibernate.annotations.TypeDefs({
    @org.hibernate.annotations.TypeDef(
        name="monetary_amount_usd",
        typeClass = persistence.MonetaryAmountConversionType.class,
        parameters = { @Parameter(name="convertTo", value="USD") }
    ),
    @org.hibernate.annotations.TypeDef(
        name="monetary_amount_eur",
        typeClass = persistence.MonetaryAmountConversionType.class,
        parameters = { @Parameter(name="convertTo", value="EUR") }
    )
})
  • 위의 설정은 import문 바로 아래 또는 class정의 부분 위나, 별도의 자바 파일, package-info.java 같은 클래스에 둔다.(2.2.1 참조)
  • 다음과 같이 참조해서 사용할 수 있다.
@org.hibernate.annotations.Type(type = "monetary_amount_eur")
@org.hibernate.annotations.Columns({
  @Column(name = "BID_AMOUNT"),
  @Column(name = "BID_AMOUNT_CUR")
})
private MonetaryAmount bidAmount;

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


CompositeUserType 만들기

Hibernate/Chapter 5 : 2008.02.04 17:19


클래스 구현하기

public class MonetaryAmountCompositeUserType implements CompositeUserType {

	public String[] getPropertyNames() {
		return new String[] { "amount", "currency" };
	}

	public Type[] getPropertyTypes() {
		return new Type[] { Hibernate.BIG_DECIMAL, Hibernate.CURRENCY };
	}

	public Object getPropertyValue(Object component, int property)
			throws HibernateException {
		MonetaryAmount monetaryAmount = (MonetaryAmount) component;
		if (property == 0)
			return monetaryAmount.getAmount();
		else
			return monetaryAmount.getCurrency();
	}

	public Object nullSafeGet(ResultSet resultSet, String[] names,
			SessionImplementor session, Object owner)
			throws HibernateException, SQLException {
		BigDecimal value = resultSet.getBigDecimal(names[0]);
		if (resultSet.wasNull())
			return null;
		Currency currency = Currency.getInstance(resultSet.getString(names[1]));
		return new MonetaryAmount(value, currency);
	}

	public void nullSafeSet(PreparedStatement statement, Object value,
			int index, SessionImplementor arg3) throws HibernateException,
			SQLException {
		if (value == null) {
			statement.setNull(index, Hibernate.BIG_DECIMAL.sqlType());
			statement.setNull(index + 1, Hibernate.CURRENCY.sqlType());
		} else {
			MonetaryAmount amount = (MonetaryAmount) value;
			String currencyCode = amount.getCurrency().getCurrencyCode();
			statement.setBigDecimal(index, amount.getAmount());
			statement.setString(index + 1, currencyCode);
		}
	}

	public void setPropertyValue(Object arg0, int arg1, Object arg2)
			throws HibernateException {
		throw new UnsupportedOperationException("Immutable MonetaryAmount!");
	}

}
  • CompositeUserType 인터페이스를 구현한다.
  • nullSafeSet()은 ResultSet에 담겨있는 두 개의 값을 Monetary 객체의 속성값으로 변환하면 된다.
  • nullSafeSet()은 객체가 가진 두 개의 값을 DB에 저장하도록 statement를 수정한다.
  • getPropertyNames()를 사용해서 Value Type의 속성들을 알려준다.
  • getPropertyValue()를 사용해서 Value Type의 각각의 속성이 가진 값을 알려준다.
  • setPropertyValue()를 사용해서 Value Type의 속성에 값을 설정한다.

맵핑하기

@org.hibernate.annotations.Type(
    type = "persistence.MonetaryAmountUserType"
)
@org.hibernate.annotations.Columns(columns = {
    @Column(name="INITIAL_PRICE"),
    @Column(name="INITIAL_PRICE_CURRENCY", length = 2)
})
private MonetaryAmount initialPrice;
  • 다음과 같이 쿼리를 작성할 수 있다.
from Item i
where i.initialPrice.amount > 100.0
  and i.initialPrice.currency = 'AUD'

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


UserType만들기

Hibernate/Chapter 5 : 2008.02.04 17:18


클래스 구현하기

public class MonetaryAmountUserType implements UserType {

	public Object assemble(Serializable cached, Object owner)
			throws HibernateException {
		return cached;
	}

	public Object deepCopy(Object value) throws HibernateException {
		return value;
	}

	public Serializable disassemble(Object value) throws HibernateException {
		return (Serializable) value;
	}

	public boolean equals(Object x, Object y) throws HibernateException {
		if (x == y)
			return true;
		if (x == null || y == null)
			return false;
		return x.equals(y);
	}

	public int hashCode(Object x) throws HibernateException {
		return x.hashCode();
	}

	public boolean isMutable() {
		return false;
	}

	public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner)
			throws HibernateException, SQLException {

		BigDecimal valueInUSD = resultSet.getBigDecimal(names[0]);
		if (resultSet.wasNull())
			return null;

		// DB에서 가져온 다음에 원하는 값으로 캐스팅 해서 반환.

		return null;
	}

	public void nullSafeSet(PreparedStatement statement, Object value, int index)
			throws HibernateException, SQLException {
		
		// SQL을 DB에 보내기 전에 statement의 특정 위치에 들어갈 값을 변경한다.

	}

	public Object replace(Object original, Object target, Object owner)
			throws HibernateException {
		return original;
	}

	public Class returnedClass() {
		return MonetaryAmount.class;
	}

	public int[] sqlTypes() {
		return new int[] { Hibernate.BIG_DECIMAL.sqlType() };
	}

}
  • sqlTypes() 메소드는 하이버네이트가 어떤 SQL 컬럼 타입으로 DDL 스키마를 생성할 지 알려준다.
  • returnClass() 메소드는 어떤 자바 타입을 맵핑할 것인지 알려준다.
  • deepCopy()는 스냅샷 객체을 전달해 준다. 따라서, immutable한 타입일 경우에는 그냥 넘기면 된다.
  • disassemble()은 MonetaryAmount를 하이버네이트 2차 캐쉬에 집어 넣을 때 호출된다. 이곳에서 직렬화된 상태로 데이터를 캐슁한다.
  • assemble()은 캐쉬된 상태의 데이터를 MonetaryAmount 객체로 변환한다.
  • replace()는 detached 상태의 객체를 merging할 때 사용한다.
  • equals()는 dirty checking 할 때 사용한다.
  • nullSafeGet()은 ResultSet에서 데이터를 가져올 때 사용한다.
  • nullSafeSet()은 PreparedStatement에 저장할 값을 설정할 때 사용한다.

맵핑하기

@org.hibernate.annotations.Type(
    type = " persistence.MonetaryAmountUserType"
)
@Column(name = "INITIAL_PRICE")
private MonetaryAmount initialPrice;

단점

  • 하이버네이트는 Monetary Amount의 속성을 모른다. 따라서 그 안에 있는 amount나 currency를 가져오는 쿼리를 작성할 수 없다.

해결책

  • CompositeUserType을 사용하면 된다.

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

Hibernate Core VS JPA  (0) 2008.02.04
Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
top


맵핑 타입 사용하기

Hibernate/Chapter 5 : 2008.02.04 00:17


  • type 속성을 명시하지 않아도 된다.
  • java.lang.String 타입의 변수는 기본 맵핑으로 string을 사용한다.
  • java.util.Date는 timestamp를 사용한다.
  • JPA를 사용할 때는 @Temporal을 사용해서 정확도를 명시해 준다.
  • 기본값은 TemporalType.TIMESTAMP, (가용한 값은, TIEM, DATE)
  • 하이버네이트 맵핑 타입을 명시적으로 표현하고 싶을 때는 하이버네이트의 @Type 애노테이션 사용.
  • 커스텀 타입도 만들 수 있다.

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

Enum Type 맵핑하기 - 실습  (0) 2008.02.04
Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
top


내장된 맵핑 타입

Hibernate/Chapter 5 : 2008.02.04 00:17


특징

  • ORM은 자바의 타입과 SQL 데이터타입을 중개해 주는 역할을 해야한다.
  • 하이버는 보통 자바 타입 이름을 따르고 있다. 하지만 자바 타입 하나에 여러 하이버네이트 타입이 있을 수 있다.
  • Custom Value Type을 정의할 수 있다.

자바 기본 타입 맵핑

  • 벤더가 ANSI 표준을 따르지 않을 수도 있다. 그래도 JDBC 드라이버는 추상화 계층을 제공해 주니까 이걸 하이버네이트가 읽어 들여서 벤더에 적당한 타입으로 변환해준다.
  • 즉, 사용자는 타입 걱정하지 않아도 된다.
  • 문자열의 길이 제한 설정(length 속성 값)에 따라서 하이버가 적당한 타입으로 결정한다.
  • 이런 전략 자체도 사용자 맘대로 변경할 수 있다.
Java Type Hibernate Mapping Type SQL Type
int, Integer integer INTEGER
long, Long long BIGINT
short, Short short SMALLINT
float, FLOAT float FLOAT
double, Double double DOUBLE
BigDecimal big_decimal NUMERIC
String character CHAR(1)
String string VARCHAR
byte, Byte byte TINYINT
boolean, Boolean boolean BIT
boolean, Boolean yes_no CHAR(1) ('Y' or 'N')
boolean, Boolean true_false CHAR(1) ('T' or 'F')

날짜와 시간 맵핑

  • java.util.Date 타입을 timestamp로 맵핑할 경우 DB에서 나노초까지 값을 가져온다.
  • 책을 쓸 시점에서는 나노초를 짤라주지 않아서, equlas() 메소드로 비교할 경우 Date.getTime() 으로 비교하거나 Custom Mapping Type을 만들어서 사용해야 한다.
Java Type Hibernate Mapping Type SQL Type
java.util.Data, java.sql.Date date DATE
java.util.Date, Java.sql.Time time TIME
java.util.Date, java.sql.Timestamp timetamp TIMESTAMP
java.util.Calendar calendar TIMESTAMP
java.util.Calendar calendar_date DATE

바이너리와 큰 값 맵핑

  • binary 맵핑 타입만 식별자 속성으로 사용할 수 있다.
  • byte[]일 경우에는 VARBINARY로 맵핑하고, String일 경우에는 CLOB로 맵핑할 수 있다.
  • 이 두 경우에 Entity 객체가 속성 값을 읽어들일 때, 초기화를 하려고 할텐데, 너무 큰 값이라서 Lazy loading 하고 싶을 수 있다.
  • 특정 속성을 lazy loading 하는 두 가지 방법이 있다.
    • 13.1.6에서 다루는 Lazy loading with interception
    • java.sql.Clob 나 java.sql.Blob 타입을 사용한다.(로딩하는 시점에 Entity는 Persistent 상태여야 한다.)
  • JPA를 사용할 때 String 타입은 기본으로 VARCHAR로 맵핑 된다. Clob 타입으로 맵핑하려면 @Lob 애노테이션을 사용한다.
  • Serializable 타입은 변수의 값을 바이트 스트림으로 바꿔서 VARBINARY 타입 컬럼에 저장한다. 로딩할 때는 역직렬화한다.
Java Type Hibernate Mapping Type SQL Type
byte[] binary VARBINARY
String text CLOB
java.sql.Clob clob CLOB
java.sql.Blob blob BLOB
java.io.Serializable serializable VARBINARY

JDK 맵핑 타입

  • <property>만 type 속성을 가진 것은 아니다.
Java Type Hibernate Mapping Type SQL Type
java.lang.Class class VARCHAR
java.util.Locale locale VARCHAR
java.util.TimeZone timezone VARCHAR
java.util.Currency currency VARCHAR

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

Enum Type 만들기  (0) 2008.02.04
ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
top


Entity와 Value type 복습

Hibernate/Chapter 5 : 2008.02.04 00:16


특징

Entity Value Type
Coarse-grained Fine-grained
도메인 설명에 잘 나타난다. 잘 나타나지 않는다.
Persistent id를 가지고 있다. 그런거 없고, Entity 클래스에 종속된다.
상태(transient, detached, persistent)가 있다. 이런 상태를 신경쓰지 않는다.
자신만의 라이프 사이클을 가지고 있다. 라이프 사이클은 자신을 소유한 Entity를 따른다.
공유 된다. 공유되지 않는다. Entity는 고유한 Value Type을 가지고 있다.
@Entity로 맵핑한다. @Embeddable로 맵핑한다.

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

ParameterizedType 만들기  (0) 2008.02.04
CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
top


상속 맵핑 전략 선택하기

Hibernate/Chapter 5 : 2008.02.01 21:40


맵핑 전략

  • 다형적인 관계나 쿼리가 필요하지 ㅇ낳다면, Table Per Concrete Class를 사용하라. 즉, 상위 타입으로 객체들을 가져다 쓰지 않을거라면...
  • 다형적인 관계나 쿼리가 필요하고, 하위 클래스들의 속성이 몇 개 되지 않는 다면, Table Per Class Hierarchy를 사용하라.
  • 다형적인 관계나 쿼리가 필요하고, 하위 클래스들에 속성들이 많다면 Table Per SubClass를 사용하라.

특징

  • 간단한 경우에는 Table Per Class Hierarchy를 사용하라. 그 다음에 좀 더 복잡한 경우에 Table Per Subclass를 고려하라. 하지만 그렇게 하기 전에 상속구조를 Deligation으로 대체할 수 없을지 고민해 봐라.
  • 하이버네이트가 도메인과 관계형 모델의 버퍼 역할을 해주긴 하지만, 그렇다고 해서 Persistence Concern을 몰라도 된다는 뜻은 아니다.

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


상속 맵핑 전략 혼용하기

Hibernate/Chapter 5 : 2008.02.01 21:40


특징

  • 특정 하위 클래스에 대한 맵핑 정랸글 변경할 수 있다.
  • 하이버네이트가 2차 테이블에서 속성들을 가져오도록 설정한다.

맵핑하기

  • 기본으로 Table Per Class Hierachy를 사용하고 특정 하위 클래스만 Table Per Sub Class 사용하기.
  • @SecondaryTable 애노테이션 사용하기.
  • 2차 테이블에는 모든 속성을 명시해 주어야 한다.

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


Table per subclass

Hibernate/Chapter 5 : 2008.02.01 21:39


특징

  • 영속화 할 필드를 가진 모든 클래스의 테이블을 만든다.
  • 상위 클래스의 주키를 하위 클래스의 주키이자 외례키로 사용한다.
  • Join을 사용해서 상위 타입으로 하위 타입의 객체를 가져올 수 있다.

장점

  • 정규화를 할 수 있다.
  • 스키마 개선과 무결성 제약 정의가 간단하다.
  • 다형성은 특정 하위 클래스로의 외례키 참조로 가능하다.
  • 구분자 컬럼 필요없다.

단점

  • 복잡한 클래스 구조에서는 성능이 안 좋을 수 있다.

맵핑하기

  • 상위 클래스
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class BillingDetails {
  • 하위 클래스
@Entity
public class CreditCard extends BillingDetails {

or

@Entity
@PrimaryKeyJoinColumn(name="CREDIIT_CARD_ID")
public class CreditCard extends BillingDetails {

쿼리 분석

  • 상위 타입으로 요청할 때는 left outter join
select billingdet0_.BILLING_DETAILS_ID as BILLING1_0_, billingdet0_.OWNER as OWNER0_, 
billingdet0_1_.ACCOUNT as ACCOUNT1_, billingdet0_2_.CC_NUMBER as CC2_2_,
case
when billingdet0_1_.BILLING_DETAILS_ID is not null then 1
when billingdet0_2_.BILLING_DETAILS_ID is not null then 2
when billingdet0_.BILLING_DETAILS_ID is not null then 0 end as clazz_
from BILLING_DETAIL billingdet0_
left outer join BankAccount billingdet0_1_ on
billingdet0_.BILLING_DETAILS_ID=billingdet0_1_.BILLING_DETAILS_ID
left outer join CreditCard billingdet0_2_ on
billingdet0_.BILLING_DETAILS_ID=billingdet0_2_.BILLING_DETAILS_ID
  • 하위 타입으로 요청할 때는 inner join.
select bankaccoun0_.BILLING_DETAILS_ID as BILLING1_0_, bankaccoun0_1_.OWNER as OWNER0_, 
bankaccoun0_.ACCOUNT as ACCOUNT1_
from BankAccount bankaccoun0_
inner join BILLING_DETAIL bankaccoun0_1_ on
bankaccoun0_.BILLING_DETAILS_ID=bankaccoun0_1_.BILLING_DETAILS_ID

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


Table per class hierarchy

Hibernate/Chapter 5 : 2008.02.01 21:38


특징

  • 전체 상속 구조 하나를 단일 클래스로 맵핑한다.
  • 하위 클래스의 객체들은 타입 구분자 Type Discriminator 컬럼의 값으로 구분한다.
  • 구분자를 추가할 수 없는 상황에서는 formula를 사용한다. SQL의 CASE/WHERN

장점

  • 다형적이거나 그렇지 않은 쿼리를 수행하는 성능이 좋다. <- 조인이나 Union을 하지 않으니까.
  • 구현하기도 간편하다. <- 스키마가 간단하니까.

단점

  • 하위 클래스의 속성들은 반드시 nullable이어야 한다.
  • 정규화가 되지 않는다. 키가 아닌 값에 종속성에 생기므로, 3차 정규화를 깨트렸다. DBA가 싫어할 것이다.

맵핑하기

  • 상위 클래스(discriminator 사용)
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="BILLING_DETAILS_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class BillingDetails {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "BILLING_DETAILS_ID")
private Long id = null;

@Column(name = "OWNER", nullable = false)
private String owner;
  • 상위 클래스(formula 사용)
@Entity
@Table(name="BILLING_DETAIL")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorFormula("case when CC_NUMBER is not null then 'CC' else 'BA' end")
public abstract class BillingDetails {
  • 하위 클래스
@Entity
@DiscriminatorValue("CC")
public class CreditCard extends BillingDetails {

@Column(name = "CC_NUMBER")
private String number;

쿼리 분석

  • 상위 타입으로 가져올 때는 조건 없이 모든 컬럼 가져온다.
List<BillingDetails> bdList = session.createQuery("from BillingDetails").list();

select billingdet0_.BILLING_DETAILS_ID as BILLING2_0_, billingdet0_.OWNER as OWNER0_, billingdet0_.ACCOUNT as ACCOUNT0_, billingdet0_.CC_NUMBER as CC5_0_, billingdet0_.BILLING_DETAILS_TYPE as BILLING1_0_
from BILLING_DETAIL billingdet0_
  • 하위 타입으로 가져올 때는 Discriminator 사용해서 조건을 준다.
List<CreditCard> bdList = session.createQuery("from CreditCard").list();

select creditcard0_.BILLING_DETAILS_ID as BILLING2_0_, creditcard0_.OWNER as OWNER0_, creditcard0_.CC_NUMBER as CC5_0_
from BILLING_DETAIL creditcard0_
where creditcard0_.BILLING_DETAILS_TYPE='CC'

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


Table per concrete class

Hibernate/Chapter 5 : 2008.02.01 21:37


특징

  • 상위 클래스에 하위 클래스들을 Union으로 포함하여 가지고 있게 설정한다.
  • JPA에서 TABLE_PER_CLASS는 필수 구현사항이 아니다. 따라서 밴더마다 다를 수 있다.
  • Hibernate의 polymorphic loader engine이 쿼리의 성능 걱정을 덜어 줄 것이다.
  • 하위 클래스들이 상위 클래스에 정의한 하나의 주키를 공유한다.
  • 주키 생성 타입을 identity로 하면 안 된다. AUTO로 설정했을 때 주의할 것. 안 그러면 Cannot use identity column key generation with <union-subclass> mapping. 이 에러를 만나게 될 것이다.

장점

  • 다형적인 관계를 다룰 수 있다. UNION 쿼리를 사용해서 단일 테이블을 관계 맵핑 처럼 사용할 것이다.(?? 7.3 참조)
  • 지금까지는 SQL 스키마는 전혀 상속을 위한 추가 설정이 필요하지 않았다. 정규화도 잘 되었고 추가적인 외례키를 필요도 하지도 않았다.

맵핑하기

  • 상위 클래스
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class BillingDetails {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
@Column(name = "BILLING_DETAILS_ID")
private Long id = null;

@Column(name = "OWNER", nullable = false)
private String owner;
  • 하위 클래스
@Entity
@Table(name="CREDIT_CARD")
public class CreditCard extends BillingDetails {

@Column(name = "NUMBER", nullable = false)
private String number;

쿼리 분석

select BILLING_DETAILS_ID, OWNER, ACCOUNT, NUMBER, clazz_
from
( select OWNER, ACCOUNT, null as NUMBER, BILLING_DETAILS_ID, 1 as clazz_ from BANK_ACCOUNT
union
select OWNER, null as ACCOUNT, NUMBER, BILLING_DETAILS_ID, 2 as clazz_ from CREDIT_CARD )
  • clazz_ 컬럼: 컬렉션에서 하위 타입의 객체를 만들 때 구분하기 위해서 사용.
  • null 인 컬럼들(BANK_ACCOUNT의 NUMBER, CREDIT_CARD의 ACCOUNT): UNION을 사용하기 위해서는 같은 컬럼을 가지고 있어야 한다.

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


Table per connrete class with implicit polymorphism

Hibernate/Chapter 5 : 2008.02.01 21:37


특징

  • 모든 구현 클래스 하나 당 하나의 테이블로 표현한다.
  • 상속 받은 속성들도 테이블의 컬럼으로 맵핑한다.

문제점

  • 다형적인 관계를 잘 지원하지 못해. 왜? 상위 클래스와 관계를 맺고 있는 클래스가 하위 클래스를 참조해야 한다면, 이 클래스가 가져야 할 하위 클래스의 외례키는 두 개의 하위 클래스 모두의 주키를 대변해야 할 텐데, 이런게 테이블에서는 불가능하다.
  • 다형적인 쿼리(특정 상위 클래스 타입에 해당하는 모든 객체를 요구하는 쿼리)도 역시 문제가 된다. 왜? 각각의 하위 클래스마다 쿼리를 수행해서 데이터를 가져와야 한다.
  • 약간 다른 여러 테이블이 같은 정보를 공유하고 있다. 이게 왜 문제가 될까? 스키마를 점점 복잡하게 만든다. 예를들어, 상위 타입의 속성 하나를 변경하면 그것을 상속하나 모든 테이블을 수정해야 한다. 모든 하위 클래스에 무결성 제약을 적용하기도 힘들다.
  • 변경될 가능성이 거의 없고, 다형성이 별로 필요 없는, 최상위 레벨의 상속구조에서 사용하기를 권장한다.
  • JPA는 다형적인 쿼리를 지원하지 않는다. 하지만 Hibernate의 쿼리 인터페이스는 지원한다.

해결책

  • SQL의 UNION 함수를 사용해서 위에서 발생한 다형적인 쿼리와 관계에 대한 이슈 대부분을 제거할 수 있다.

맵핑하기

  • 하위 클래스는 @Entity로 맵핑하기
@Entity
@AttributeOverride(name = "owner", column = @Column(name = "CC_OWNER", nullable = false))
public class CreditCard extends BillingDetails {

@Id
@GeneratedValue
@Column(name = "CREDIT_CARD_ID")
private Long id = null;

@Column(name = "NUMBER", nullable = false)
private String number;
  • 상위 클래스는 @MappedSuperclass로 맵핑하기
@MappedSuperclass
public class BillingDetails {

@Column(name = "OWNER", nullable = false)
private String owner;

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

CompositeUserType 만들기  (0) 2008.02.04
UserType만들기  (0) 2008.02.04
맵핑 타입 사용하기  (0) 2008.02.04
내장된 맵핑 타입  (0) 2008.02.04
Entity와 Value type 복습  (0) 2008.02.04
상속 맵핑 전략 선택하기  (0) 2008.02.01
상속 맵핑 전략 혼용하기  (0) 2008.02.01
Table per subclass  (0) 2008.02.01
Table per class hierarchy  (0) 2008.02.01
Table per concrete class  (0) 2008.02.01
Table per connrete class with implicit polymorphism  (0) 2008.02.01
top


기본 속성 맵핑하기- 실습

Hibernate/Chapter 4 : 2008.01.22 09:41


기본값 설정하는 방법을 테스트합니다.
- @Column의 columnDefinition 속성을 사용해서 column을 만들 때 사용할 공식을 사용할 수 있습니다.
- 하이버의 @GenerationTime 애노테이션을 사용해서 기본값이나 생성되는 값을 언제 생성할 지 설정할 수 있습니다.

1. 테스트 코드

    @Test
    public void add() throws Exception {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();

        Member member = new Member();
        member.setName("썬");

        session.save(member);
        session.flush();

        transaction.rollback();
        session.close();
        assertNotNull(member.getId());
        assertEquals(new Integer(1), member.getDefaultNum());
    }

2. 결과 쿼리

Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into Member (name, id) values (?, ?)
Hibernate: select member_.defaultNum as defaultNum0_ from Member member_ where member_.id=?

3. Persistent Class

@Entity
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    @Column(columnDefinition = "number(10,2) default '1'")
    @org.hibernate.annotations.Generated(org.hibernate.annotations.GenerationTime.INSERT)
    private Integer defaultNum;

    ...

}

위 테스트 코드에서 flush를 하지 않으면 시퀀스만 가져오고 insertion은 이뤄지지 않습니다. insertion을 안하기 때문에 db가 생성하는 기본값을 가져오기 위해 발생하는 세번째 쿼리도 실행하지 않습니다. 따라서 다음의 SQL 한 문장만 실행합니다.

Hibernate: select hibernate_sequence.nextval from dual

참조 : 4.4.1 Mapping basic properties/Generated and default property values




'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 VS JPA

Hibernate/Chapter 4 : 2008.01.20 13:41


Hibetnate JPA
Entity와 Value-type 개념은 rich and fine-grained domain model을 지원하기 위한 필수 요소다. Value-type을 embeddable classes 라고 부른다. nonportable.
10가지나 되는 식별자 생성기 제공한다. 4가지만 지원한다. 벤더가 확장할 수 있도록 지원한다.
필드, Accessor 메소드, PropertyAccessor 인터페이스 구현체를 통해서 접근 가능하다. 혼용할 수 있다. 속성이나, Accessor 메소드로 접근할 수 있는데, 하이버네이트 애노테이션 없이 혼용할 수는 없다.
formula와 DB가 생성한 값을 사용할 수 있다. JPA에는 이런 거 없다. 하이버가 필요하다.

'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 Core와 Java Persistence and EJB 3.0

Hibernate/Chapter 3 : 2008.01.20 13:40


Hibernate Core Java Persistence and EJB 3.0
Persistence 클래스는 프록시 기반의 Lazy Loading을 사용할 때에만 아규먼트가 없는 public 또는 protected의 생성자를 필요로 한다. JPA는 모든 Entity 클래스들이 반드시 아규먼트가 없는 public 또는 protected의 생성자를 가지고 있어야만 한다.
Persistent 콜렉션은 반드시 인터페이스 타입이어야 하며, JDK가 제공하는 모든 인터페이스를 지원한다. 마찬가지로 모두 인터페이스 타입이어야 하며, 정렬된 콜렉션을 제외한 일부 인터페이스만 완전히 이식가능한 형태로 사용할 수 있다.
Persistent 속성들은 실행시에 accessor나 필드를 통해서 접근할 수 있으며, 혹은 완전히 다른 전략을 적용할 수도 있다. 마찬가지로 accessor나 필드를 통해서 접근가능하지만, 이식성이 필수라면 두 방법 모두 그렇치 않다.
XML 메타데이터 형식으로 모든 하이버네이트 맵핑 옵션을 사용할 수 있다. JPA 애노테이션은 기본적이고 가장 발전된 형태의 맵핑 옵션을 모두 제공한다. 하이버네이트 애노테이션은 별도의 맵핑과 튜닝을 필요로 한다.
XML 맵핑 메타데이터는 전역적으로 설정될 수 있으며 XML placeholder를 사용해서 메타데이터를 독립적으로 유지할 수 있다. 전역적인 메타데이터는 org.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


컴포넌트 맵핑하기

Hibernate/Chapter 4 : 2008.01.20 13:38


특징

  • 자바 객체에서 Value-type과 Entity를 구분지을 수 있는것은 식별자 속성 뿐이다.
  • 컴포넌트와 Entity 간의 양방향 관계를 설정할 수 있다.
  • 컴포넌트가 다른 컴포넌트나 Entity를 가지고 있을 수 있다.
    • This flexibility is the foundation of Hibernate's support for finegrained object models.

설정하기

  • 컴포넌트에는 @Embeddable Entity의 속성에는 @Embedded 사용하기
  • @org.hibernate.annotations.Parent 애노테이션으로 컴포넌트에서 back-pointer 프로퍼티 사용 가능.
  • if you store a component object with all null property values, Hibernate returns a null component when the owning entity object is retrieved from the database.
컴포넌트 사용하기
@Entity
@Table(name = "USERS")
public class User {
@Embedded
private Address homeAddress;


}
컴포넌트 클래스 정의하기
@Embeddable
public class Address {

@Column(name="ADDRESS_STREET", nullable=false)
private String street;

@Column(name="ADDRESS_ZIPCODE", nullable=false)
private String zipcode;

@Column(name="ADDRESS_CITY", nullable=false)
private String city;

}
  • 컴포넌트를 사용하는 쪽에서 컴포넌트의 컬럼 정의를 재정의 할 수도 있다.
  • 단점
    • First,shared references, as for all value types, aren't possible. -> 이건 value-type 이니까 당연히 그래야 하는거 아닌가.
    • Second, there is no elegant way to represent a null reference to an Address. -> 흠.. new Address()를 항상 가지고 있어야겠군.

'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.20 13:35


특징

  • @Transient 애노테이션을 붙이거나 자바의 transient 키워드를 사용하지 않으면 기본으로 전부 Persistent 대상으로 인식한다.
  • 애노테이션을 붙이지 않으면 다음과 같은 규칙이 적용된다.
    • JDK가 제공하는 타입일 경우에 자동으로 Persistent 대상이 된다.
    • 그렇지 않고, 속성의 타입에 해당하는 클래스에 @Embeddable 애노테이션이 붙어있는 경우, 컴포넌트를 가지고 있는 형태로 맵핑된다.
    • 그렇지도 않고, 속성의 타입이 Serializable 인터페이스를 구현한 경우, 직렬화된 형태로 DB에 저장된다. (이러길 원치 않을 것이다.)

설정하기

  • Chapter 17에서 하이버네이트 애노테이션으로 DDL을 작성하거나 동적으로 검증하는 기능에 대해 다룬다.
  • 클래스 속성에 접근하는 방법은 @Id 애노테이션이 붙어있는 위치가 기본 방법으로 설정 된다.(JPA)
  • 하이버네이트는 이 기본 방법을 변경할 수 있는 기능을 제공한다. @org.hibernate.annotations.AccessType(<strategy>)
    • 클래스에 AccessType 애노테이션을 사용하면, @Id로 인해 설정되는 접근 전략을 무시하며, 해당 클래스의 필드나 메서드에 붙어있는 모든 애노테이션들은 AccessType에서 정의한 접근 전략을 따른다.
    • 기본 상태이거나 필드 접근인 상태에서 @AccessType("property")를 필드 위에 붙여주면, 해당 속성을 accessor 메소드들을 이용해서 접근한다.
    • 기본 상태이거나 Accessor 접근이 상태에서 @AccessType("field")를 getter 위에 붙여주면, 해당 속성은 필드에 바로 접근한다.
    • @Embedded 클래스는 자신을 가지고 있는 쪽 클래스의 접근 방법을 따른다.
    • @MappedSuperclass 클래스는 맵핑 된 클래스의 접근 방법을 따른다.
  • noop 방식: "virtual" property in HQL queries. to use the database column in HQL queries only.
  • 마음에 드는게 없으면 org.hibernate.property.PropertyAccessor 인터페이스 구현해서 직접 만들어 됨.
    • 사용할 때는 @AccessType 애노테이션의 access 속성에 패키지 이름을 붙인 클래스 이름을 써주면 돼.

계산이 필요한 속성

  • 맵핑되는 컬럼은 없다.
  • @Fomula 애노테이션 사용하기
필드에서 계산된 속성 사용하기
@org.hibernate.annotations.Formula("TOTAL + TAX_RATE * TOTAL")
public BigDecimal getTotalIncludingTax() {
return totalIncludingTax;
}
  • SQL 함수도 사용할 수 있다.

h1, DB에서 생성된 값과 기본 값

  • public 세터를 만들지 말아라.
  • @Generated 애노테이션 사용하기
DB에서 생성된 값 사용하기
@Column(updatable = false, insertable = false)
@org.hibernate.annotations.Generated(
org.hibernate.annotations.GenerationTime.ALWAYS
)
private Date lastModified;
  • 기본값이 설정되도록 하려면 flush 해야한다.
  • columnDefinition 속성으로 기본값 설정하기
기본값 설정하기
@Column(name = "INITIAL_PRICE",
columnDefinition = "number(10,2) default '1'")
@org.hibernate.annotations.Generated(
org.hibernate.annotations.GenerationTime.INSERT
)
private BigDecimal initalPrice;
  • columnDefinition: complete properties for the column DDL, with datatype and all constraints.
    • DDL customization은 8장에서 다룬다.

모르는 것

  • @MappedSuperclass는 뭔가?

'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.20 13:29


특징

  • Hibernate provides a feature that allows you to enforce naming standards automatically.

설정하기

  • NamingStrategy 인터페이스 구현하기
  • ImprovedNamingStrategy 클래스 상속받아서 구현하기
네임스페이스 등록하기
import org.hibernate.cfg.ImprovedNamingStrategy;
import org.hibernate.util.StringHelper;

public class CENamingStrategy extends ImprovedNamingStrategy {
public String classToTableName(String className) {
return StringHelper.unqualify(className);
}

public String propertyToColumnName(String propertyName) {
return propertyName;
}

public String tableName(String tableName) {
return "CE_" + tableName;
}

public String columnName(String columnName) {
return columnName;
}

public String propertyToTableName(String className, String propertyName) {
return "CE_" + classToTableName(className) + '_'
+ propertyToColumnName(propertyName);
}
}
  • classToTableName(): <class> 맵핑에서 table 속성에 값을 입력하지 않았을 때 호출.
  • propertyToColumnName(): 명시적인 column 이름을 설정하지 않았을 때 호출.
  • tableName(), columnName(): 명시적으로 이름을 설정했을 때 호출.
  • 동적으로 설정을 바꿀 수 있음.
동적으로 네임스페이스 바꾸기
Configuration cfg = new Configuration();
cfg.setNamingStrategy( new CENamingStrategy() );
SessionFactory sessionFactory sf =
cfg.configure().buildSessionFactory();

모르는 것

  • SessionFactory 설정할 때 구현한 클래스를 등록해 주면 되는건가?

'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:27


특징

  • Hibernate doesn't quote table and column names in the generated SQL.
  • 대소문자를 구분하거나, 특수 문자를 사용하는 기존 DB의 경우 하이버네이트가 자동으로 생성하는 컬럼이나 테이블이름을 인식하지 못할 수도 있다.

설정하기

역따옴표 사용하기
<property name="description"
column="`DESCRIPTION`"/>
  • If you quote a table or column name with backticks in the mapping document, Hibernate always quotes this identifier in the generated SQL.
  • 애노테이션에서도 설정할 수 있으나, 하이버네이트 @Column 애노테이션을 사용하야 한다. JPA에서는 지원하지 않는다.

'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.20 13:24


특징

  • (XML 설정 파일 이용 시)
  • Persistent 클래스 등록할 때, 패키지 이름까지 붙어있는 이름을 등록해야 한다.
  • 같은 패키지에 위치한 여러 클래스들을 등록할 때 패키지 이름을 매번 붙여주기가 귀찮다.

설정하기

기본 패키지 설정하기
<hibernate-mapping package="auction.model">
<classname="Item" table="ITEM">
...
</class>
</hibernate-mapping>
  • 애노테이션에서는 이런 설정이 필요 없겠지. 해당 클래스에 가서 직접 붙여주는데...

'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


쿼리에서 사용할 Entity 이름 설정하기

Hibernate/Chapter 4 : 2008.01.20 13:24


특징

  • 기본으로 모든 클래스 이름들이 자동으로 HQL의 네임스페이스로 import 된다.
  • 즉, HQL에서 패키지 이름을 제외한 클래스 이름을 사용할 수 있다.
  • 서로 다른 패키지에 같은 이름의 클래스가 존재한다면, auto-import를 끄거나, 명시적으로 네임스페이스를 설정해야 한다.

설정하기

HQL에서 사용할 네임스페이스 설정하기
@Entity(name="AuctionItem")
public class Item {

}

모르는 것

  • 애노테이션을 사용해서 auto-import를 끄는 방법은?
  • auto-import를 끄면 패키지 이름이 붙어있는 클래스 이름을 네임스페이스로 사용하는 건가?

'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




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