韩顺平满汉楼demo中碰到查询账单部分字段显示为null的结果。
观察到显示为空的字段,Java Bean中的field名称和实际数据库中不相符。
前者使用小驼峰法命名,在数据库则是下划线分割单词。
private Integer diningTableId;
private Date billDate;
dining_table_id INT NOT NULL DEFAULT 0,
bill_date DATETIME NOT NULL,
但是真的是因为这两个命名不一致而导致java bean 对应的值为空的吗?
试着追一下源码,看一下给java bean赋值的细节。
@Test
public void test01(){
String sql = "select * from bill";
/*此处下断点*/ List<Bill> bills = billDao.queryMulti(sql, Bill.class);
Bill bill = bills.get(0);
System.out.println(bill);
}
step into
return queryRunner.query(connection, sql, new BeanListHandler<>(clazz), objects);
step into query
result = rsh.handle(rs);
step into handle
return this.convert.toBeanList(rs, this.type);
step into toBeanList
return this.convert.toBeanList(rs, type);
step into 最重要的toBeanList方法,就是在此方法里赋值的。
do {
results.add(this.createBean(rs, type, props, columnToProperty));
} while(rs.next());
step into createBean
columnToProperty应该是数据库和java Bean 类字段间的某种对应关系。原先搜索不出结果的字段对应值为-1,图里是浅灰色是正常的值,只是懒得再改回异常情况debug了,用红字标记了一下,可以到从这个数组的第二个元素开始值一旦是负一,它不会进入赋值的分支,所以值为空。
虽然得到了这些信息,但是对问题帮助不大,对于我这个初学者来说一时半会要把这个过程的来龙去脉弄得清楚很不容易,里面一个注释也不写我也是很服气,也希望有大佬指点一二。
后来想到,这个赋值过程一定会使用到JavaBean类的字段名吗?根据老韩的土办法(也就是此工具类的核心思想),只需要将查找出来的字段,根据set方法赋值即可。
有理由相信,此工具内部要解决的一个核心问题,就是将数据库的字段名和JavaBean类的对应字段的set方法对应起来。
看似是JavaBean 字段和数据库字段不一致,但如果set方法是用idea alt insert 进来的,那会不会本质上是set方法名和字段名不一致导致的?
当机立断做了一个测试
public class DiningTable {
private Integer id;
private String state;
private String order_name;
private String orderTel;
public DiningTable(){}
public DiningTable(Integer id,String state,String orderName,String orderTel){
this.id = id;
this.state = state;
this.order_name = orderName;
this.orderTel = orderTel;
}
注意看其中有一个 orderTel字段用了驼峰法命名
而在数据库中使用下划线分割
关键一步,将set方法用下划线方式命名
public void setOrder_tel(String orderTel) {
this.orderTel = orderTel;
}
用Junit测试一下
@Test
public void test01(){
String sql = "select * from dining_table";
List<DiningTable> tableList = diningTableDao.queryMulti(sql, DiningTable.class);
Iterator<DiningTable> iterator = tableList.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(next);
}
}
toString方法如下
@Override
public String toString() {
return "DiningTable{" +
"id=" + id +
", state='" + state + '\'' +
", orderName='" + order_name + '\'' +
", orderTel='" + orderTel + '\'' +
'}';
}