GenericJsonStringType<T>
package com.gss.gmo.cao.hibernate.usertype;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.gss.gmo.cao.gson.ISODateTimeAdapter;
public abstract class GenericJsonStringType<T> implements UserType {
private static final int[] SQL_TYPES = { Types.LONGVARCHAR };
private final Type userType;
private final Gson gson;
public GenericJsonStringType() {
Type type = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) type;
userType = pt.getActualTypeArguments()[0];
gson = new GsonBuilder().registerTypeAdapter(Date.class, new ISODateTimeAdapter()).create();
}
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
if (userType instanceof Class) {
return (Class) userType;
} else {
return (Class) ((ParameterizedType) userType).getRawType();
}
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
String jsonString = rs.getString(names[0]);
return gson.fromJson(jsonString, userType);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
st.setString(index, gson.toJson(value, userType));
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return gson.fromJson(gson.toJson(value, userType), userType);
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return gson.toJson(value, userType);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return gson.fromJson((String) cached, userType);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
Sample有四個部分:
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.gss.gmo.cao.gson.ISODateTimeAdapter;
public abstract class GenericJsonStringType<T> implements UserType {
private static final int[] SQL_TYPES = { Types.LONGVARCHAR };
private final Type userType;
private final Gson gson;
public GenericJsonStringType() {
Type type = getClass().getGenericSuperclass();
ParameterizedType pt = (ParameterizedType) type;
userType = pt.getActualTypeArguments()[0];
gson = new GsonBuilder().registerTypeAdapter(Date.class, new ISODateTimeAdapter()).create();
}
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
if (userType instanceof Class) {
return (Class) userType;
} else {
return (Class) ((ParameterizedType) userType).getRawType();
}
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.equals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
String jsonString = rs.getString(names[0]);
return gson.fromJson(jsonString, userType);
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
st.setString(index, gson.toJson(value, userType));
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return gson.fromJson(gson.toJson(value, userType), userType);
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return gson.toJson(value, userType);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return gson.fromJson((String) cached, userType);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
- Setup org.springframework.orm.hibernate4.LocalSessionFactoryBean
- Setup org.hibernate.annotations.TypeDef in package-info.java
- Extend GenericJsonStringType<T>
- Mapping UserType field in entity
Setup org.springframework.orm.hibernate4.LocalSessionFactoryBean
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.gss.gmo.cao.hibernate.impl" />
<property name="annotatedPackages" value="com.gss.gmo.cao.hibernate.impl" />
</bean>
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.gss.gmo.cao.hibernate.impl" />
<property name="annotatedPackages" value="com.gss.gmo.cao.hibernate.impl" />
</bean>
Setup org.hibernate.annotations.TypeDef in package-info.java
@TypeDef(name = "listType", typeClass = ListJsonType.class)
package com.gss.gmo.cao.hibernate.impl;
import org.hibernate.annotations.TypeDef;
package com.gss.gmo.cao.hibernate.impl;
import org.hibernate.annotations.TypeDef;
Extend GenericJsonStringType<T>
package com.gss.gmo.cao.hibernate.impl;
import java.util.List;
import com.gss.gmo.cao.hibernate.usertype.GenericJsonStringType;
public class ListJsonType extends GenericJsonStringType<List<String>> {
}
import java.util.List;
import com.gss.gmo.cao.hibernate.usertype.GenericJsonStringType;
public class ListJsonType extends GenericJsonStringType<List<String>> {
}
Mapping UserType field in entity
package com.gss.gmo.cao.hibernate.impl;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Type;
import com.gss.gmo.cao.base.BaseDto;
import com.gss.gmo.cao.hibernate.audit.AuditInfo;
/**
* @author linus_chien
*
*/
@Getter
@Setter
@EqualsAndHashCode(callSuper = false, of = { "id" })
@ToString
@Entity
public class Person extends BaseDto {
private static final long serialVersionUID = 1L;
@Id
private String id;
@Column
private String name;
@Column
private String address;
@Embedded
private AuditInfo auditInfo;
@Type(type = "listType")
private List<String> emails;
}
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Type;
import com.gss.gmo.cao.base.BaseDto;
import com.gss.gmo.cao.hibernate.audit.AuditInfo;
/**
* @author linus_chien
*
*/
@Getter
@Setter
@EqualsAndHashCode(callSuper = false, of = { "id" })
@ToString
@Entity
public class Person extends BaseDto {
private static final long serialVersionUID = 1L;
@Id
private String id;
@Column
private String name;
@Column
private String address;
@Embedded
private AuditInfo auditInfo;
@Type(type = "listType")
private List<String> emails;
}