第一步:添加自定义类:
package com.a.entity; import java.io.Serializable; public class ConfigEntry implements Serializable { private static final long serialVersionUID = 6796578004411833529L; private String key; private String value; private Integer type; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public Integer getType() { return type; } public void setType(Integer type) { this.type = type; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((key == null) ? 0 : key.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ConfigEntry other = (ConfigEntry) obj; if (key == null) { if (other.key != null) return false; } else if (!key.equals(other.key)) return false; if (type == null) { if (other.type != null) return false; } else if (!type.equals(other.type)) return false; if (value == null) { if (other.value != null) return false; } else if (!value.equals(other.value)) return false; return true; } }
第二步:添加Hibernate UserType的实现类:
package com.aspire.usertype; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.List; import java.util.Properties; import net.sf.json.JSONArray; import org.hibernate.HibernateException; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; public class ListObjectType implements UserType, ParameterizedType { private static final int[] TYPES = new int[] { Types.CLOB }; private static final String paramName = "clazzName"; private Properties parameters; @Override public Object assemble(Serializable serializable, Object owner) throws HibernateException { return deepCopy(serializable); } @Override public Object deepCopy(Object object) throws HibernateException { if (object == null) return null; if (!(object instanceof java.util.List)) throw new UnsupportedOperationException("can't convert " + object.getClass()); List sourceSet = (List) object; List targetSet = new ArrayList(); if (sourceSet != null) { targetSet.addAll(sourceSet); } return targetSet; } @Override public Serializable disassemble(Object object) throws HibernateException { if (!(object instanceof java.util.List)) throw new UnsupportedOperationException("can't convert " + object.getClass()); return (Serializable) deepCopy(object); } @Override public boolean equals(Object one, Object other) throws HibernateException { if (one == other) {// 如果两个对象的指针是指向同一位置。 return true; } if (!(one instanceof java.util.List)) throw new UnsupportedOperationException("can't convert " + one.getClass()); if (!(other instanceof java.util.List)) throw new UnsupportedOperationException("can't convert " + other.getClass()); if (one != null && other != null) { List set0 = (List) one; List set1 = (List) other; if (set0.size() != set1.size()) {// 如果列表的长度不相等 return false; } Object[] s0 = set0.toArray(); Object[] s1 = set1.toArray(); if (s0.length != s1.length) {// 如果列表的长度不相等 return false; } for (int i = 0; i < s0.length; i++) { Object id0 = s0[i]; Object id1 = s1[i]; if (!id0.equals(id1)) {// 如果在列表中相同位置上的对象不相等 return false; } } return true; } return false; } @Override public int hashCode(Object obj) throws HibernateException { return obj.hashCode(); } @Override public boolean isMutable() { return true; } @Override public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException { String value = rs.getString(names[0]); List resultList = null; if (value != null) { try { String clazzName = parameters.getProperty(paramName); resultList = parse(value, Class.forName(clazzName)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } else { resultList = new ArrayList(); } return resultList; } /** * 解析JSON字符成对象 * * @param value * @return */ private List parse(String value, Class clazz) { List resultList = null; if (value != null) { JSONArray jsonArray = JSONArray.fromObject(value); resultList = jsonArray.toList(jsonArray, clazz); } else { resultList = new ArrayList(); } return resultList; } /** * 格式化对象成Json字符串 * * @param value * @return * @throws ClassNotFoundException */ private String format(List value) { String result = null; if (value != null) { JSONArray jsonArray = JSONArray.fromObject(value); result = jsonArray.toString(); } return result; } @Override public void nullSafeSet(PreparedStatement stmt, Object value, int index) throws HibernateException, SQLException { if (value == null) { stmt.setNull(index, Types.CLOB); return; } if (!(value instanceof java.util.List)) throw new UnsupportedOperationException("can't convert " + value.getClass()); stmt.setString(index, format((java.util.List) value)); } @Override public Object replace(Object original, @SuppressWarnings("unused") Object target, @SuppressWarnings("unused") Object owner) throws HibernateException { return original; } @Override public Class returnedClass() { return List.class; } @Override public int[] sqlTypes() { return TYPES; } @Override public void setParameterValues(Properties parameters) { this.parameters = parameters; } }
第三步:添加组合关键字字,
package com.a.entity; import java.io.Serializable; import javax.persistence.CascadeType; import javax.persistence.Embeddable; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; @Embeddable public class ClientAppCfgId implements Serializable { private static final long serialVersionUID = 2291408665473574896L; @ManyToOne(targetEntity = ClientApp.class, cascade = { CascadeType.ALL }, optional = false) @JoinColumn(name = "app_id") @OnDelete(action = OnDeleteAction.CASCADE) private ClientApp app; @ManyToOne(targetEntity = Area.class, cascade = { CascadeType.ALL }, optional = false) @JoinColumn(name = "area_id") @OnDelete(action = OnDeleteAction.CASCADE) private Area area; public ClientApp getApp() { return app; } public void setApp(ClientApp app) { this.app = app; } public Area getArea() { return area; } public void setArea(Area area) { this.area = area; } }
第四步:配置属性:
package com.a.entity; import java.io.Serializable; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import org.hibernate.annotations.TypeDefs; /** 客户端配置 */ @TypeDefs({ @TypeDef(name = "listObjectType", typeClass = com.a.usertype.ListObjectType.class, parameters = { @Parameter(name = "clazzName", value = "com.a.entity.ConfigEntry") }) }) @Entity @Table(name = "t_client_app_cfg") public class ClientAppCfg implements Serializable { private static final long serialVersionUID = -8929122435053630855L; @Id private ClientAppCfgId id; /***/ @Type(type = "listObjectType") @Column(name = "config_params", columnDefinition = " clob default null") private List<ConfigEntry> configParams; public ClientAppCfgId getId() { return id; } public void setId(ClientAppCfgId id) { this.id = id; } public List<ConfigEntry> getConfigParams() { return configParams; } public void setConfigParams(List<ConfigEntry> configParams) { this.configParams = configParams; } }
第五:运行应用,将自动创建表(以下是表结构创建示例):
create table T_CLIENT_APP_CFG ( bg_type NUMBER(10), bg_value VARCHAR2(255 CHAR), help_url VARCHAR2(500 CHAR), show_style NUMBER(10), ver NUMBER(10), app_id NUMBER(19) not null, area_id NUMBER(19) not null, config_params CLOB, primary key (APP_ID, AREA_ID) )
第六:插入数据:
INSERT INTO T_CLIENT_APP_CFG(APP_ID, AREA_ID, CONFIG_PARAMS) VALUES (10000, 1001, '[{"key":"a","type":0,"value":"a1"},{"key":"b","type":1,"value":"b1"}, {"key":"c","type":3,"value":"c1"},{"key":"d","type":4,"value":"d1"}, {"key":"e","type":5,"value":"e1"},{"key":"f","type":6,"value":"f1"}, {"key":"g","type":7,"value":"g1"},{"key":"h","type":8,"value":"h1"}]');
第七:可以使用java代码试试。
第八:关于第四步的配置方法还有另外一种,可以参考以下示例:
package com.a.entity; import java.io.Serializable; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version; import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Type; /** 客户端配置 */ @Entity @Table(name = "t_client_app_cfg") public class ClientAppCfg implements Serializable { private static final long serialVersionUID = -8929122435053630855L; @Id private ClientAppCfgId id; /***/ @Type(type= "com.a.usertype.ListObjectType", parameters = { @Parameter(name = "clazzName", value = "com.a.entity.ConfigEntry") }) @Column(name = "config_params", columnDefinition = " clob default null") private List<ConfigEntry> configParams; public ClientAppCfgId getId() { return id; } public void setId(ClientAppCfgId id) { this.id = id; } public List<ConfigEntry> getConfigParams() { return configParams; } public void setConfigParams(List<ConfigEntry> configParams) { this.configParams = configParams; } }