7.1 자신만의 유형 변환기 만들기
때때로 테이블의 한 열에 상당히 복잡한 데이터 유형을 저장하려는 경우 상황이 발생합니다. Hibernate가 문자열로 변환하는 방법을 안다면 모든 것이 정상입니다. 그렇지 않은 경우 자체 데이터 변환기를 작성해야 합니다.
누군가가 사용자의 생년월일을 데이터베이스에 로 저장하기로 결정했다고 가정해 보겠습니다 YY.MM.DD. 예를 들면 다음과 같습니다 98.12.15. 또한 일반 날짜로 변환해야 합니다 15/12/1998. 그런 다음 자신만의 변환기를 작성해야 합니다.
이렇게 하려면 인터페이스를 구현해야 합니다 AttributeConverter<EntityType, DbType>.
@Converter(autoApply = true)
public class DateConverter implements AttributeConverter<java.time.LocalDate, String> {
public String convertToDatabaseColumn(java.time.LocalDate date) {
return date.format("YY.MM.DD");
}
public java.time.LocalDate convertToEntityAttribute(String dbData) {
String[] data = dbData.split(".");
return LocalDate.of(data[2], data[1], "19"+data[0]);
}
}
물론 이 변환기는 모든 필드에 추가할 수 있습니다(유형이 일치하는 경우).
@Entity @Table(name="user")
class User {
@Id
@Column(name="id")
public Integer id;
@Column(name="join_date")
@Convert(converter = DateConverter.class)
public java.time.LocalDate date;
}
데이터베이스를 설계하지 않은 경우 변환기를 자주 사용해야 합니다. 거기에 있는 데이터는 "이상한 형식"일 수 있습니다. 날짜는 문자열로, 부울은 Y 및 N 값이 있는 CHAR 등으로 저장할 수 있습니다.
7.2 자체 데이터 유형 만들기
Hibernate에 알려진 유형 목록이 있는 표를 기억하십니까? 주석과 함께 지정된 유형에 대해 이야기하고 있습니다 @Type. Hibernate의 다른 내장 유형과 동일한 방식으로 사용할 수 있는 고유한 데이터 유형을 작성할 수 있습니다.
예를 들어 데이터베이스에 TIME이 아니라 VARCHAR로 저장되는 LocalTime 유형을 원합니다. 예를 들어, 우리는 그러한 데이터베이스에 액세스할 수 있으며 해당 열의 데이터 유형을 변경할 수 없습니다. 그런 다음 우리는 우리 자신의 Hibernate 유형을 작성할 수 있습니다. LocalTimeString이라고 부르겠습니다.
먼저 새 유형을 설명하는 작은 클래스가 필요합니다.
public class LocalTimeStringType extends AbstractSingleColumnStandardBasicType<<LocalTime> {
public static final LocalTimeStringType INSTANCE = new LocalTimeStringType ();
public LocalTimeStringType () {
super(VarcharTypeDescriptor.INSTANCE, LocalTimeStringJavaDescriptor.INSTANCE);
}
@Override
public String getName() {
return "LocalTimeString";
}
}
하나의 값으로 구성된 Enum 유형입니다. 이러한 단일 enam 세트는 Hibernate에 알려진 모든 유형입니다.
또한 두 가지 방법을 포함하는 변환기의 아날로그 클래스 wrap()와 unwrap()LocalTime 유형의 값을 문자열로 변환하는 클래스가 필요합니다.
다음은 메서드를 구현하지 않고 표시되는 방식입니다.
public class LocalTimeStringJavaDescriptor extends AbstractTypeDescriptor<LocalTime> {
public static final LocalTimeStringJavaDescriptor INSTANCE = new LocalTimeStringJavaDescriptor();
public LocalTimeStringJavaDescriptor() {
super(LocalTime.class, ImmutableMutabilityPlan.INSTANCE);
}
public <X> X unwrap(LocalTime value, Class<X> type, WrapperOptions options) {
}
public <X> LocalTime wrap(X value, WrapperOptions options) {
}
}
이제 메서드 구현을 작성해 보겠습니다.
public <X> X unwrap(LocalTime value, Class<X> type, WrapperOptions options) {
if (value == null)
return null;
if (String.class.isAssignableFrom(type))
return (X) LocalTimeType.FORMATTER.format(value);
throw unknownUnwrap(type);
}
두 번째 방법:
@Override
public <X> LocalTime wrap(X value, WrapperOptions options) {
if (value == null)
return null;
if(String.class.isInstance(value))
return LocalTime.from(LocalTimeType.FORMATTER.parse((CharSequence) value));
throw unknownWrap(value.getClass());
}
준비가 된. 이 클래스를 사용하여 시간을 문자열로 저장할 수 있습니다.
@Entity @Table(name="user")
class User
{
@Id
@Column(name="id")
public Integer id;
@Column(name="join_time")
@Type(type = "com.codegym.hibernate.customtypes.LocalTimeStringType")
public java.time.LocalTime time;
}
7.3 유형 등록
Hibernate 구성 중에 데이터 유형을 등록할 수도 있습니다. 이것은 사소한 일이 아닙니다.
ServiceRegistry serviceRegistry = StandardServiceRegistryBuilder()
.applySettings(getProperties()).build();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
Metadata metadata = metadataSources
.addAnnotatedClass(User.class)
.getMetadataBuilder()
.applyBasicType(LocalTimeStringType.INSTANCE)
.build();
SessionFactory factory = metadata.buildSessionFactory();
먼저 MetadataSources를 가져와 MetadataBuilder를 가져와 클래스를 추가하는 데 사용해야 합니다. 를 통해 가능 hibernate.cfg.xml하지만 조금 번거롭기도 합니다.
그러나 등록 후 다음과 같이 작성할 수 있습니다.
@Entity @Table(name="user")
class User
{
@Id
@Column(name="id")
public Integer id;
@Column(name="join_time")
@Type(type = "LocalTimeString")
public java.time.LocalTime time;
}
GO TO FULL VERSION