😱 요구사항
- 상품 테이블에 옷 사이즈열이 있다. 사이즈 여러 개를 데이터로 넣고 싶은데 어떻게 해야할까?
- 배열을 값으로 넣을 수는 없을까?
- 그래서 column 타입을 배열로 하니까 오류가 난다ㅠㅠ
// 오류나는 코드
@Column
private String[] clothSize; //옷 사이즈
사용 DB: PostgreSQL
🚩 해결방법
- 배열 커스텀 타입 클래스를 생성해야 한다
Item entity
import lombok.*;
import mirim.itshow.kiru.entity.enum_col.Size;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.*;
@Data //TODO 엔티티에 @Data쓰면 set 남용 때문에 안 좋음
@Entity //엔티티
@Table(name = "item")
public class Item {
@Id
@Column
private Long itemId; //상품 고유 id
@Column(columnDefinition = "text[]")
@Type(type = "mirim.itshow.kiru.entity.hibernatesetting.CustomStringArrayType")
private String[] clothSize; //옷 사이즈
// 생성자, 일부 column 생략
}
text[ ]는 뭐고, @Type 어노테이션은 왜 있는 걸까? 차근차근 보도록 하자
CustomStringArrayType.java
커스텀한 배열 타입 클래스가 필요하다
나는 entity 폴더 안에 hibernatesetting 폴더를 만들어서 클래스를 만들어줬다
✨ 아래 코드를 복붙하여서 새로운 클래스를 생성하자! ✨
코드가 길어보이는 이유는 추상메서드 구현 때문이다
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.UserType;
import java.io.Serializable;
import java.sql.*;
public class CustomStringArrayType implements UserType {
@Override
public int[] sqlTypes() {
return new int[]{Types.ARRAY};
}
@Override
public Class returnedClass() {
return String[].class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return false;
}
@Override
public int hashCode(Object x) throws HibernateException {
return 0;
}
@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]);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return null;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return null;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return null;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return null;
}
//implement equals, hashCode, and other methods
}
자기 입맛대로 nullSafeSet() 메서드 안에 있는 데이터 타입이나 배열명을 수정하면 된다
여기서 다시 위로 올라가 Entity를 살펴보자
@Column(columnDefinition = "text[]")
@Type(type = "mirim.itshow.kiru.entity.hibernatesetting.CustomStringArrayType")
private String[] clothSize; //옷 사이즈
- 커스텀 클래스의 nullSafeSet() 메서드에서 설정했던 이름대로
- columnDefinition 속성을 text[]로 설정하고
- 커스텀 배열 클래스를 type으로 설정해준다
값 넣어주기
item1.setClothSize(new String[]{"S", "M", "L"});
set 메서드 안에 배열을 만들어서 넣어주면 된다
🙇♂️ 더 쉬운 방법이 있다면 댓글에 남겨주세요 🙇♂️
참고: https://www.baeldung.com/java-hibernate-map-postgresql-array
'스프링 독학 여정' 카테고리의 다른 글
HTTP header, body란? (0) | 2023.05.31 |
---|---|
JPA fk column으로 findBy하기 (0) | 2023.05.18 |
스프링 입문 독학 :: day1 - 1.프로젝트 생성 (0) | 2023.01.03 |