====== StringDate Hibernate UserType ======
Database에 날짜를 문자열로 저장했을 경우 사용하는 [[java:hibernate:usertype|Hibernate User Type]].
''java.util.Date'' 객체를 문자열로 변환해서 저장하고, 읽을 때 문자열에서 다시 Date 객체로 변환한다.
===== 코드 =====
public class StringDateUserType implements UserType, ParameterizedType {
public static final String PARAM_FORMAT = "format";
public static final String DEFAULT_FORMAT = "yyyyMMddHHmmss";
private AbstractSingleColumnStandardBasicType type;
private int[] sqlTypes = null;
private String format;
@Override
public void setParameterValues(Properties parameters) {
format = parameters.getProperty(PARAM_FORMAT, DEFAULT_FORMAT);
populateSqlTypes();
}
private void populateSqlTypes() {
TypeResolver tr = new TypeResolver();
String stringClassName = String.class.getName();
// type은 org.hibernate.type.StringType 으로 사실상 고정값임.
type = (AbstractSingleColumnStandardBasicType) tr.basic(stringClassName);
sqlTypes = new int[] { type.sqlType() };
}
@Override
public int[] sqlTypes() {
return sqlTypes;
}
@Override
public Class returnedClass() {
return Date.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return Objects.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return Objects.hashCode(x);
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return dateDeepCopy((Date) value);
}
@Override
public boolean isMutable() {
return true; // java.util.Date is mutable
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
// TODO : Date는 mutable이라서 deep copy가 맞는듯. 확인 필요.
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
// TODO : Date는 mutable이라서 deep copy가 맞는듯. 확인 필요.
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return dateDeepCopy((Date) original);
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
String stringDate = (String) type.get(rs, names[0], session);
if (stringDate == null) { // 데이터에 null이 아닌 empty가 있다면 empty 체크도 해야함.
log.trace("Found [{}] as column [{}] original value [{}]", null, names[0], stringDate);
return null;
}
try {
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date parsedDate = sdf.parse(stringDate);
log.trace("Found [{}] as column [{}] original value [{}]", parsedDate, names[0], stringDate);
return parsedDate;
} catch (Exception ex) {
throw new HibernateException("Failed to parse [" + stringDate + "] with [" + format + "].", ex);
}
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
try {
String formattedDate = null;
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(format);
formattedDate = sdf.format((Date) value);
}
log.trace("binding parameter [{}] as [{}] - [{}] original value [{}]", index, JdbcTypeNameMapper.getTypeName(sqlTypes[0]), formattedDate, value);
st.setObject(index, formattedDate);
} catch (Exception ex) {
throw new HibernateException("Failed to format date object to string.", ex);
}
}
String getFormat() {
return format;
}
}
===== 설정 =====
@TypeDef(name = "string_datetime", typeClass = StringDateUserType.class,
parameters = @Parameter(name = StringDateUserType.PARAM_FORMAT, value = "yyyy/MM/dd HH:mm:ss")),
// 이제 @Type(type = "string_datetime") 으로 사용가능해짐. 컬럼은 기본적으로 String의 컬럼인 varchar 계열로 지정됨.