1. 개요
PostgreSQL 은 테이블의 열 유형으로 정의될 모든 유형(내장 또는 사용자 정의)의 배열을 지원합니다 . 이 예제에서 우리는 PostgreSQL 배열을 Hibernate 와 매핑하는 몇 가지 방법을 탐구할 것 입니다.
2. 기본 설정
PostgreSQL 데이터베이스와 연결하기 위한 전제 조건으로 Hibernate 구성과 함께 최신 postgresql Maven 의존성을 pom.xml 에 추가해야 합니다. 또한 String 배열 역할 을 사용하여 User 라는 엔터티 클래스를 생성해 보겠습니다 .
@Entity
public class User {
@Id
private Long id;
private String name;
private String[] roles;
//getters and setters
}
3. 커스텀 하이버네이트 타입
Hibernate는 사용자 정의 유형을 SQL 쿼리에 매핑하는 사용자 정의 유형을 지원합니다. 따라서 데이터를 저장/패치하기 위해 Hibernate와 PostgreSQL 어레이를 매핑하는 사용자 정의 유형을 생성할 수 있습니다 . 먼저, String 배열 을 매핑하기 위한 커스텀 타입을 제공하기 위해 Hibernate의 UserType 클래스 를 구현하는 CustomStringArrayType 클래스 를 생성하자 :
public class CustomStringArrayType implements UserType {
@Override
public int[] sqlTypes() {
return new int[]{Types.ARRAY};
}
@Override
public Class returnedClass() {
return String[].class;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
Array array = rs.getArray(names[0]);
return array != null ? array.getArray() : null;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value != null && st != null) {
Array array = session.connection().createArrayOf("text", (String[])value);
st.setArray(index, array);
} else {
st.setNull(index, sqlTypes()[0]);
}
}
//implement equals, hashCode, and other methods
}
여기에서 우리는 반환된 클래스 메서드 의 반환 유형이 String 배열 이라는 점에 주목해야 합니다 . 또한 nullSafeSet 메서드 는 PostgreSQL 유형 text 의 배열을 만듭니다 .
4. 커스텀 하이버네이트 타입으로 배열 매핑하기
4.1. 사용자 엔터티
그런 다음 CustomStringArrayType 클래스를 사용하여 String 배열 역할 을 PostgreSQL 텍스트 배열 에 매핑합니다 .
@Entity
public class User {
//...
@Column(columnDefinition = "text[]")
@Type(type = "com.baeldung.hibernate.arraymapping.CustomStringArrayType")
private String[] roles;
//getters and setters
}
그게 다야! 사용자 엔터티 에서 CRUD 작업을 수행하기 위한 사용자 지정 유형 구현 및 배열 매핑이 준비되었습니다 .
4.2. 단위 테스트
사용자 정의 유형을 테스트하기 위해 먼저 String 배열 역할 과 함께 User 객체를 삽입하겠습니다 .
@Test
public void givenArrayMapping_whenArraysAreInserted_thenPersistInDB()
throws HibernateException, IOException {
transaction = session.beginTransaction();
User user = new User();
user.setId(2L);
user.setName("smith");
String[] roles = {"admin", "employee"};
user.setRoles(roles);
session.persist(user);
session.flush();
session.clear();
transaction.commit();
User userDBObj = session.find(User.class, 2L);
assertEquals("smith", userDBObj.getName());
}
또한 PostgreSQL 텍스트 배열 형식의 역할 을 포함하는 사용자 레코드를 가져올 수 있습니다 .
@Test
public void givenArrayMapping_whenQueried_thenReturnArraysFromDB()
throws HibernateException, IOException {
User user = session.find(User.class, 2L);
assertEquals("smith", user.getName());
assertEquals("admin", user.getRoles()[0]);
assertEquals("employee", user.getRoles()[1]);
}
4.3. 사용자 정의 정수 배열 유형
마찬가지로 PostgreSQL에서 지원하는 다양한 배열 유형에 대한 사용자 정의 유형을 생성할 수 있습니다. 예를 들어 PostgreSQL int 배열 을 매핑하기 위해 CustomIntegerArrayType 을 생성해 보겠습니다.
public class CustomIntegerArrayType implements UserType {
@Override
public int[] sqlTypes() {
return new int[]{Types.ARRAY};
}
@Override
public Class returnedClass() {
return Integer[].class;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
Array array = rs.getArray(names[0]);
return array != null ? array.getArray() : null;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
if (value != null && st != null) {
Array array = session.connection().createArrayOf("int", (Integer[])value);
st.setArray(index, array);
} else {
st.setNull(index, sqlTypes()[0]);
}
}
//implement equals, hashCode, and other methods
}
CustomStringArrayType 클래스 에서 발견한 것과 유사하게 , 반환된Class 메서드 의 반환 유형은 Integer 배열 입니다. 또한 nullSafeSet 메소드 의 구현은 PostgreSQL 유형 int 의 배열을 생성합니다 . 마지막으로 CustomIntegerArrayType 클래스를 사용하여 정수 배열 위치 를 PostgreSQL int 배열에 매핑할 수 있습니다.
@Entity
public class User {
//...
@Column(columnDefinition = "int[]")
@Type(type = "com.baeldung.hibernate.arraymapping.CustomIntegerArrayType")
private Integer[] locations;
//getters and setters
}
5. 최대 절전 모드 유형으로 배열 매핑
반면에 String , Integer , Long 과 같은 각 유형에 대해 사용자 정의 유형을 구현하는 대신 유명한 Hibernate 전문가 Vlad Mihalcea가 개발한 hibernate 유형 라이브러리 를 사용할 수 있습니다 .
5.1. 설정
먼저 pom.xml 에 최신 hibernate-types-52 Maven 의존성을 추가합니다 .
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.10.4</version>
</dependency>
5.2. 사용자 엔터티
다음으로 User 엔터티에 통합 코드를 추가하여 String 배열 phoneNumbers 를 매핑합니다 .
@TypeDefs({
@TypeDef(
name = "string-array",
typeClass = StringArrayType.class
)
})
@Entity
public class User {
//...
@Type(type = "string-array")
@Column(
name = "phone_numbers",
columnDefinition = "text[]"
)
private String[] phoneNumbers;
//getters and setters
}
여기에서 커스텀 타입 CustomStringArrayType 과 유사하게 , 우리는 Hibernate-types 라이브러리에 의해 제공되는 StringArrayType 클래스를 String 배열 을 위한 매퍼로 사용했습니다 . 마찬가지로 라이브러리에서 DateArrayType , EnumArrayType 및 DoubleArrayType 과 같은 몇 가지 편리한 매퍼 를 찾을 수 있습니다 .
5.3. 단위 테스트
그게 다야! hibernate-types 라이브러리 를 사용하여 배열 매핑을 할 준비가 되었습니다 . 삽입 작업을 확인하기 위해 이미 논의된 단위 테스트를 업데이트해 보겠습니다.
@Test
public void givenArrayMapping_whenArraysAreInserted_thenPersistInDB()
throws HibernateException, IOException {
transaction = session.beginTransaction();
User user = new User();
user.setId(2L);
user.setName("smith");
String[] roles = {"admin", "employee"};
user.setRoles(roles);
String[] phoneNumbers = {"7000000000", "8000000000"};
user.setPhoneNumbers(phoneNumbers);
session.persist(user);
session.flush();
session.clear();
transaction.commit();
}
마찬가지로 읽기 작업을 확인할 수 있습니다.
@Test
public void givenArrayMapping_whenQueried_thenReturnArraysFromDB()
throws HibernateException, IOException {
User user = session.find(User.class, 2L);
assertEquals("smith", user.getName());
assertEquals("admin", user.getRoles()[0]);
assertEquals("employee", user.getRoles()[1]);
assertEquals("7000000000", user.getPhoneNumbers()[0]);
assertEquals("8000000000", user.getPhoneNumbers()[1]);
}
6. 결론
이 기사에서 우리는 PostgreSQL 어레이를 Hibernate와 매핑하는 방법을 탐구했습니다. 먼저 Hibernate의 UserType 클래스 를 사용하여 String 배열을 매핑하는 사용자 정의 유형을 생성했습니다. 그런 다음 사용자 지정 유형을 사용하여 PostgreSQL 텍스트 배열을 Hibernate와 매핑했습니다. 마지막으로 PostgreSQL 배열을 매핑하기 위해 hibernate-types 라이브러리를 사용했습니다. 평소와 같이 소스 코드는 GitHub에서 사용할 수 있습니다 .