public class User implements Serializable{ private static final long serialVersionUID = -3120416800441648924L; private List<String> hobbys;
//存储hobbys private String hobbyExt; private String ext1; private String ext2; private String ext3; //存储ext1 、 ext2、 ext3 的信息 private String extInfo; public String getExtInfo() { return extInfo; } public void setExtInfo(String extInfo) { this.extInfo = extInfo; } public String getExt1() { return ext1; } public void setExt1(String ext1) { this.ext1 = ext1; } public String getExt2() { return ext2; } public void setExt2(String ext2) { this.ext2 = ext2; } public String getExt3() { return ext3; } public void setExt3(String ext3) { this.ext3 = ext3; } public List<String> getHobbys(){ this.parseInfo(); return hobbys; } public void parseInfo() { //TODO 解析字段hobbyExt 成hobbys, 将extInfo解析成ext1、ext2、ext3 } public void fillExtendInfo(){ //TODO 将List hobbys拼装成一个字符串,ext1、ext2、ext3拼接成一个字符串 } public String getHobbyExt() { return hobbyExt; } public void setHobbyExt(String hobbyExt) { this.hobbyExt = hobbyExt; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } }
这样处理操作繁琐,程序进行存取时要注意解析及填充操作,如果一旦忽略或误用了某个操作,会导致数据库中某个信息没被填充进去,或者产生一些脏数据,极易引入潜在的bug。public List<String> getHobbys(){ this.parseInfo(); return hobbys; }
这种处理方式会导致每次存取该字段时都要进行解析操作,增加了不必要的性能开销。不同程序员对不同domain对象定义难以想用,这种解析操作无法共用。如果要增加附加字段,需修改原有的解析方法,又增加了引入bug的风险。这种拼接,解析操作也减低了程序的易读性,导致可维护性降低。//UserDO 对象
public class UserDO implements Serializable { private static final long serialVersionUID = 377875304139361819L; private int id; private String name; private UserExtDO extDO; private List<String> hobbys ; private Map<String,String> votes; public Map<String, String> getVotes() { return votes; } public void setVotes(Map<String, String> votes) { this.votes = votes; } public void addHobby(String hobby){ if(hobbys == null){ hobbys = new ArrayList<String>(); } hobbys.add(hobby); } public List<String> getHobbys() { return hobbys; } public void setHobbys(List<String> hobbys) { this.hobbys = hobbys; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public UserExtDO getExtDO() { return extDO; } public void setExtDO(UserExtDO extDO) { this.extDO = extDO; } }
//其扩展字段的对象
public class UserExtDO implements Serializable{ private static final long serialVersionUID = -6065939028174333314L; private String school; private List<String> loves;
public String getSchool() { return school; } public void setSchool(String school) { this.school = school; } public List<String> getLoves() { return loves; } public void setLoves(List<String> loves) { this.loves = loves; } public void addLove(String love){ if(loves == null){ loves = new ArrayList<String>(); } loves.add(love); } }
UserDO 的ORM映射文件:xml version="1.0" encoding="UTF-8" ?> "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import com.alibaba.fastjson.JSON;
public class JSONHandler implements TypeHandler<Object> { /** * json数据和类名的分隔符号 * */ private static final char SPLIT = '/'; public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { if(parameter == null){ ps.setString(i, null); return; } String json = JSON.toJSONString(parameter); json = json + SPLIT + parameter.getClass().getName(); ps.setString(i, json); } public Object getResult(ResultSet rs, String columnName) throws SQLException { String json = rs.getString(columnName); return jsonToObject(json); } public Object getResult(CallableStatement cs, int columnIndex) throws SQLException { String json = cs.getString(columnIndex); return jsonToObject(json); } /** * json 转换成对象 * */ private Object jsonToObject(String json){ if(json == null){ return null; } int index = json.lastIndexOf(SPLIT); if(index < 0){ return null; } String key = json.substring(index + 1, json.length()); json = json.substring(0, index); Class> cls = null; try { cls = Class.forName(key); } catch (ClassNotFoundException e) { throw new RuntimeException("序列化成json时找不到指定的类", e); } Object ob = JSON.parseObject(json, cls); return ob; } }
在ibatis.xml 文件增加如下配置:Reader rd = Resources.getResourceAsReader("ibatis.xml"); SqlSessionFactory sf = new SqlSessionFactoryBuilder().build(rd); Configuration cfg = sf.getConfiguration(); TypeHandlerRegistry tr = cfg.getTypeHandlerRegistry(); //程序注册,不然不起作用 tr.register(UserExtDO.class, new JSONHandler()); tr.register(List.class, new JSONHandler()); tr.register(Map.class, new JSONHandler());
这样既可把List、Map及对象当做基本类型进行存储。 如果需要在UserExtDO 添加字段,则直接添加属性,设置普通的set和get方法既可,无需做拼接解析操作,并且mybatis配置及映射文件无需做任何变化,数据库也无需做任何变化。 减少字段也可以很方便的进行。 业务开发人员无需在做任何字段的解析及拼接的操作, 极大增强了程序的扩展性,易读性,及维护性。