问题调试 - mybaties查询结果集封装实体类失败

问题描述

        Mybatis sql查询日志打印显示有一条数据,转化成实体类时为null

实体类

Dao SQL

通过设置dao xml中 select标签的resultType为DataCollectPushVo自动映射到实体类

问题分析

    结果集映射到实体类问题,查看近期git提交记录,代码改动包括mybatis 3.4.0升级3.5.7,引入mybatis-plus,与现有mybatis共用同一个全局配置文件

调试

mybaties查询结果封装 DefaultResultSetHandler 类  handleResultSets方法

sql字段映射实体类属性

createAutomaticMappings()方法获取当前查询结果集中没有在resultMap中映射的字段,以进行自动映射

获取结果集中字段对应的实体类属性名

驼峰转换,去掉字段名中的“_”, JOB_ID变成JOBID

在实体类里面找不到JOBID属性,返回空

字段名转化为大写,大小写不敏感

解决

全局配置类配置关闭字段驼峰映射

启动调试,能获取到结果集中JOB_ID映射到实体类JOB_ID的映射关系

 根据autoMapping从结果集(jdbc的rsresult)中取值注入实体类

 

扩展验证

验证一:自动映射时实体类属性大小写不敏感

开启驼峰式命名,将实体类属性设置为小写

结果:能正确获取到映射关系,并将值注入到实体类

验证二:如果大小写不敏感,结果集的JOB_ID能否同时映射实体类jobid和joBid两个属性中

实体类配置属性 jobid 和 joBid

 启动程序查看处理结果:只映射到joBid

 

 跟进属性名获取:反射找到vo类的 MetaClass  -> Reflector

在Reflector中 caseInsensitivePropertyMap 用key-value保存vo类每个属性,属性大写名称为key,属性名称为value

caseInsensitivePropertyMap 初始化,第一次调用dao时候初始化,部分在程序启动时就初始化,大写名称相同的属性会覆盖,后一个覆盖前一个,map中的key为“JOBID”的value先是jobid,后被joBid覆盖掉

结论,自动映射(jdbcType=“实体类“)时,结果集根据字段名映射到实体类属性中

  1. 实体类中属性大小写不敏感,映射时将实体类属性转为大写英文进行匹配;
  2. 属性名大写相同的属性会有冲突,后面的属性会覆盖前面的属性;
  3. 开启驼峰式命名配置(mapUnderscoreToCamelCase=true)时,结果集根据字段名会删除下划线再匹配实体类属性;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个示例代码,可以通过用户名和密码查询数据库,并将结果封装为具有`username`和`password`属性的实体类对象,然后将对象存入: ```java import java.sql.*; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> userList = new ArrayList<>(); // 数据库连接信息 String url = "jdbc:mysql://localhost:3306/mydatabase"; String username = "your_username"; String password = "your_password"; try { // 加载数据库驱动 Class.forName("com.mysql.cj.jdbc.Driver"); // 建立数据库连接 Connection connection = DriverManager.getConnection(url, username, password); // 创建查询语句 String query = "SELECT username, password FROM users WHERE username = ? AND password = ?"; PreparedStatement statement = connection.prepareStatement(query); // 设置查询参数 statement.setString(1, "your_username"); statement.setString(2, "your_password"); // 执行查询 ResultSet resultSet = statement.executeQuery(); // 遍历结果 while (resultSet.next()) { // 获取查询结果 String usernameResult = resultSet.getString("username"); String passwordResult = resultSet.getString("password"); // 创建实体类对象并设置属性 User user = new User(); user.setUsername(usernameResult); user.setPassword(passwordResult); // 将对象存入合 userList.add(user); } // 关闭连接 resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { e.printStackTrace(); } // 非空验证 if (!userList.isEmpty()) { System.out.println("查询结果非空"); } else { System.out.println("查询结果为空"); } } } class User { private String username; private String password; // 省略构造方法和Getter/Setter方法 } ``` 请将代码的`your_username`和`your_password`替换为实际的用户名和密码。此示例使用了MySQL数据库,你需要根据自己的数据库类型和连接信息进行相应的更改。这段代码会执行查询,并将查询结果封装为`User`对象存入`userList`,最后进行非空验证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值