问题描述
在使用hibernate拼接hql时,新增字段竟然没有出现在构造方法中(下面是简化版,真实情况要复杂的多)
//实体类
public class Tmd {
private String CBh;
private Integer NSjzzaqxx;
//private String CAjysly;//新加字段
public static final String cTmdConstructorFields = "(CBh,NSjzzaqxx)";
//public static final String cTmdConstructorFields = "(CBh,NSjzzaqxx,CAjysly)";//新增字段添加进构造器
//......Constructos......
//......getter/setter......
}
//工具类
public class DatamodelUtils{
public static String CTmdConstructorFields = Tmd.cTmdConstructorFields;
}
通过Hibernate查询对象,这里使用select new 的方式,SQL里的对象有多少个参数,实体类也要有数据类型和参数个数一致的构造器
StringBuilder hql = new StringBuilder();
hql.append("select new ").append("com.luo.Tmd").append(DatamodelUtils.CTmdConstructorFields);
服务器上跑的就是这个,因为需求,我在Tmd新增了一个字段CAjysly,构造器也进行了修改,最后我把修改后的 Tmd.class 放到测试环境上的工作目前work中,重启项目,报错
Caused by: org.springframework.orm.hibernate3.HibernateQueryException: Unable to locate appropriate constructor on class .....
看了日志,发现没有我新增的字段,最后拼接的hql是这样的
select new com.luo.Tmd(CBh,NSjzzaqxx)
为啥我新增的字段没有呢?
原因分析:
是不是新增了字段后,代码没有编译上
随后我马上到生成环境上查看Tmd.class,看看是不是我没有编译上,随后使用arthas去看了Tmd.class,发现新增字段是存在的,构造器里面也有,此时的我很懵逼
//修改之前的DatamodelUtils.class
public static String CTmdConstructorFields = "(CBh,NSjzzaqxx)";
然后看看DatamodelUtils.CTmdConstructorFields
值,发现竟是 "(CBh,NSjzzaqxx)"
,还是原来的值,此时大概就明白了,我出的替换文件仅仅是Tmd.class,但是DatamodelUtils.class还是原来的,并没有重新加载,因为服务器根本没有检测到DatamodelUtils的变化
解决方案:
对DatamodelUtils重新进行编译,发布到测试环境上
反思总结:
在出增量替换文件的情况下,对于常量的修改,要切记使用到常量的地方,都要重新进行编译,然后发布