最近项目后台整体使用ICE提供服务,返回JSON数据给前台
整体架构大致如下:
1.Controller 接受客户端请求
2.使用IceClient调用iceservice
3.iceservice调用数据库层
有趣的是,在controller和dao层定义了两个业务对象,一个是ice数据对象,另一个是dao层众所周知的java pojo对象,ice service层使用cglib来回拷贝,请注意注释部分
session = SqlSessionFactoryUtil.getSqlSessionFactory().openSession();
BaseDataDAO dao = session.getMapper(BaseDataDAO.class);
ProvincePOJO provincePOJO = new ProvincePOJO();
BeanCopierUtil.copy(province, provincePOJO);//拷贝参数
List<ProvincePOJO> provinces = dao.getProvince(provincePOJO);
List<Province> _provinces = new ArrayList<Province>(provinces.size());
for (int i = 0; i < provinces.size(); i++) {
ProvincePOJO _provincePOJO = provinces.get(i);
Province _province = new Province();
BeanCopierUtil.copy(_provincePOJO, _province);//拷贝返回值
_provinces.add(i, _province);
}
return _provinces;
cglib拷贝工具
public class BeanCopierUtil {
public static void copy(Object source, Object target) {
BeanCopier bc = BeanCopier.create(source.getClass(), target.getClass(), false);
bc.copy(source, target, null);
}
public static void copy(Object source, Object target, Converter converter) {
BeanCopier bc = BeanCopier.create(source.getClass(), target.getClass(), true);
bc.copy(source, target, converter);
}
}
数据对象如下
public class ProvincePOJO {
private Integer provinceID;
private String provinceName;
private Integer areaId;
private Integer countryId;
private Date dateCreate;
}
["java:getset"]
struct Province{
int provinceID;
string provinceName;
int areaId;
int countryId;
string dateCreate;
};
ice为支持多语言,只提供基本数据类型,而Interger,Date是Java类型的!问题来了,我们知道,大名鼎鼎的cglib拷贝工具BeanCopier只会对同类型的的数据做拷贝,int->int ok! int->Ingeter no! 这种情况迫使我们不得不加上一个转换器
public static Converter getDefaultConverter() {
return converter = new Converter() {
@SuppressWarnings("rawtypes")
@Override
public Object convert(Object arg0, Class arg1, Object arg2) {
return arg0;//直接返回
}
};
}
//加上转换器
BeanCopierUtil.copy(province, provincePOJO,BeanCopierUtil.getDefaultConverter());//拷贝参数
BeanCopierUtil.copy(_provincePOJO, _province,BeanCopierUtil.getDefaultConverter());//拷贝返回值
至此,我以为万事大吉了 int ->integer no problem!,我只想说,呵呵! tooyoung, too simple, sometimes naïve!
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Date
at org.springframework.cglib.empty.Object$$BeanCopierByCGLIB$$a26519e4.copy(
at com.huilian.hlej.loan.utils.BeanCopierUtil.copy(BeanCopierUtil.java:23)
at com.huilian.hlej.loan.utils.BeanCopierUtil.main(BeanCopierUtil.java:64)
字符串转日期失败!!好吧
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if ("setDateCreate".equals(arg2)) {// date<->string
if ("java.util.Date".equals(typeName)) {
try {
return sdf.parse((String) arg0);
}
catch (ParseException e) {
}
return null;
}
}
日期转字符串失败!!
Exception in thread "main" java.lang.ClassCastException: java.util.Date cannot be cast to java.lang.String
at org.springframework.cglib.empty.Object$$BeanCopierByCGLIB$$e3dd8d28.copy
at com.huilian.hlej.loan.utils.BeanCopierUtil.copy(BeanCopierUtil.java:23)
at com.huilian.hlej.loan.utils.BeanCopierUtil.main(BeanCopierUtil.java:77)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
if ("setDateCreate".equals(arg2)) {// date<->string
if ("java.util.Date".equals(typeName)) {
try {
return sdf.parse((String) arg0);
}
catch (ParseException e) {
}
return null;
}
return sdf.format(arg0);//加上日期转字符串代码
}
后来业务需求不断调整,加入了多个日期字段,大字段java.math.BigDecimal,不断地修改转换器代码,另外接受前台的非法参数,如何不经过严格判断,直接系统错误,这简直就是噩梦!!
JAVA POJO类字段类型为何一定要定义数据表字段相应的类型?
接口本身的功能是从数据库查询到前台JSON,反过来从前台JSON保存到数据库
JS和SQL语言本身是弱类型,为何在中间强制加上强类型?
架构师给出的答案:性能问题,我大概只能呵呵了
实际上,mybatis已经很好完成类型转换的工作,不管数据库定义什么类型,都能映射到JAVA String字段
反过来,即使将一个非法的int类型传递到数据库(where t.loan_status > '123d'),数据库也能正常的工作,而不是直接崩溃
自己写的转换器,性能就一定好吗,不尽然吧!不管怎样,我还是推荐POJO全部定义成String类型