본문 바로가기

백엔드 개발/JPA

[하이버네이트 유저 가이드 파헤치기] Column transformers: read and write expressions - 2.3.19

반응형

2.3.19. Column transformers: read and write expressions

하이버네이트는 @Basic 타입에 매핑되는 칼럼의 값을 읽고 쓰는데 사용하는 SQL를 사용자가 정의할 수 있도록 허용한다.

예를 들면, 만일 당신의 데이터베이스가 데이터 암호화 함수 세트를 제공한다면, 당신은 아래 예제와 같이 개별 칼럼에 대해서 암호화 함수 세트를 호출할 수 있다.

 

원문
Hibernate allows you to customize the SQL it uses to read and write the values of columns mapped to @Basic types. For example, if your database provides a set of data encryption functions, you can invoke them for individual columns like in the following example.

 

 

Example 78. @ColumnTransformer example

@Entity(name = "Employee")
public static class Employee {

	@Id
	private Long id;

	@NaturalId
	private String username;

	@Column(name = "pswd")
	@ColumnTransformer(
		read = "decrypt( 'AES', '00', pswd  )",
		write = "encrypt('AES', '00', ?)"
	)
	private String password;

	private int accessLevel;

	@ManyToOne(fetch = FetchType.LAZY)
	private Department department;

	@ManyToMany(mappedBy = "employees")
	private List<Project> projects = new ArrayList<>();

	//Getters and setters omitted for brevity
}

 

 

만일 엔티티의 속성이 칼럼을 하나 이상 사용한다면, 당신은 @ColumnTransformer가 대상으로 하는 읽기/쓰기 표현의 칼럼을 명시하기 위해 'forColumn' 속성을 사용해야한다.

원문
If a property uses more than one column, you must use the 'forColumn' attribute to specify which column the 
@ColumnTransformer read and write expressions are targeting.

 

 

Example 79. @ColumnTransformer forColumn attribute usage

@Entity(name = "Savings")
public static class Savings {

	@Id
	private Long id;

	@Type(type = "org.hibernate.userguide.mapping.basic.MonetaryAmountUserType")
	@Columns(columns = {
		@Column(name = "money"),
		@Column(name = "currency")
	})
	@ColumnTransformer(
		forColumn = "money",
		read = "money / 100",
		write = "? * 100"
	)
	private MonetaryAmount wallet;

	//Getters and setters omitted for brevity

}

 

 

하이버네이트는 쿼리에서 속성이 참조가될 때 마다 자동으로 사용자 정의 표현식을 적용한다.

이 기능은 두 가지 차이점이 있는 파생된 속성 @Formula과 비슷하다.

  - 속성은 자동 스키마 생성의 부분으로 내보낸 하나 이상의 칼럼을 뒷받침해 준다. (필자: 가상 칼럼이 아니다!)

  - 속성은 읽기/쓰기가 된다. 읽기 전용이 아니다.

 

쓰기 표현식이 명시되었다면, 값을 위해 정확하게 하나의 자리표시자인 '?'를 포함해야한다.

원문
Hibernate applies the custom expressions automatically whenever the property is referenced in a query.
This functionality is similar to a derived-property @Formula with two differences:
  - The property is backed by one or more columns that are exported as part of automatic schema generation.
  - The property is read-write, not read-only.

The write expression, if specified, must contain exactly one '?' placeholder for the value.

 

Example 80. Persisting an entity with a @ColumnTransformer and a composite type

doInJPA( this::entityManagerFactory, entityManager -> {
	Savings savings = new Savings( );
	savings.setId( 1L );
	savings.setWallet( new MonetaryAmount( BigDecimal.TEN, Currency.getInstance( Locale.US ) ) );
	entityManager.persist( savings );
} );

doInJPA( this::entityManagerFactory, entityManager -> {
	Savings savings = entityManager.find( Savings.class, 1L );
	assertEquals( 10, savings.getWallet().getAmount().intValue());
} );
INSERT INTO Savings (money, currency, id)
VALUES (10 * 100, 'USD', 1)

SELECT
    s.id as id1_0_0_,
    s.money / 100 as money2_0_0_,
    s.currency as currency3_0_0_
FROM
    Savings s
WHERE
    s.id = 1

 

 

반응형