nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for propert

1. 复现错误


今天写好导入hive表的接口,如下代码所示:

/**
 * hive表导入
 *
 * @author super先生
 * @datetime 2023/3/20:16:32
 * @return
 */
@ResponseBody
@PostMapping(value = "/xxx/importTables")
public ServiceStatusData localHiveImportTables(
    @RequestBody ImportTablesBo importTablesBo, @RequestHeader("x-userid") Long userId) {
  logger.info("入参记录:importTablesBo={},userId={}", importTablesBo, userId);
  if (isBlank(importTablesBo.getHiveTableName())) {
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "hive表名不能为空", null);
  }
  if (isBlank(importTablesBo.getTableImportType())) {
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "导表类型不能为空", null);
  }
  if (isBlank(importTablesBo.getCron())) {
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "执行周期表达式不能为空", null);
  }
  if (null == importTablesBo.getDatasetId()) {
    return new ServiceStatusData(ServiceStatusData.Status.Fail, "工作表id不能为空", null);
  }
  return hiveImportTaskService.localHiveImportTables(importTablesBo,userId);
}

同时,也写好hiveImportTaskService.localHiveImportTables方法,如下代码所示:

public ServiceStatusData localHiveImportTables(ImportTablesBo importTablesBo, Long userId) {
  // TODO 调用第三方接口,获取任务信息
  String missionId = "uuuddssdddsssss";
  HiveImportTask hiveImportTask = new HiveImportTask();
  hiveImportTask.setMissionId(missionId);
  hiveImportTask.setDatasetId(1L);
  hiveImportTask.setRequestConfig(JSONUtil.toJsonStr(importTablesBo));
  hiveImportTask.setUserId(userId);
  hiveImportTaskMapper.saveTask(hiveImportTask);
  return new ServiceStatusData(ServiceStatusData.Status.Success, "", importTablesBo);
}

启动项目后,使用postman测试,却报出如下错误:

在这里插入图片描述

nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'mission_state' in 'class com.xxx.pojo.po.HiveImportTask'的错误。

2. 分析错误


正赶上最近ChatGPT比较火,可以借助它来分析我的错误,如下图所示:

在这里插入图片描述

ChatGPT说我在HiveImportTask实体类中没有mission_stategetter方法,让我检查是否存在mission_state属性。

如下为HiveImportTask实体类的代码,确实不存在mission_state属性:

/**
* @author super先生
* @datetime 2023/3/21 16:11
* @desc 任务记录
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@ToString
public class HiveImportTask {
  private Long id;
  private String missionId;
  private Long datasetId;
  private String requestConfig;
  
  @Column(name = "mission_state")
  private String missionState;
  
  private Long userId;
  private Date createTime = new Date();
  private Date updateTime = new Date();
  private boolean deleted;
}

当然,也不应该存在mission_state属性,它是missionState属性对应的mysql数据库中的字段,如上HiveImportTask实体类的代码所示。

但为什么报出是mission_state属性的错误呢?百思不得其解。

分析上述代码hiveImportTaskService.localHiveImportTables中的hiveImportTaskMapper.saveTask(hiveImportTask);方法,如下代码所示:

/**
* @author super先生
* @datetime 2023/3/21 16:25
* @desc
*/
@Mapper
@Repository
public interface HiveImportTaskMapper {

 /**
  * 保存任务
  *
  * @param hiveImportTask 任务对象
  * @author super先生
  * @datetime 2023/3/21:17:37
  * @return
  */
 Integer saveTask(HiveImportTask hiveImportTask);
}

再根据saveTask方法,定位到hiveImportTaskMapper.xml文件中的saveTask的代码,如下所示:

<insert id="saveTask" parameterType="com.xxx.pojo.po.HiveImportTask">
   INSERT INTO hive_import_task ( 
       `mission_id`, `dataset_id`, `request_config`, 
       `mission_state`, `user_id`, `create_time`, 
       `update_time` 
   )
   VALUES( 
       #{missionId}, #{datasetId}, #{requestConfig}, 
       #{mission_state}, #{userId}, #{createTime}, 
       #{updateTime} 
   );
</insert>

原来问题出现在这个#{mission_state}占位符,如下图所示:

在这里插入图片描述

此处的#{mission_state}应该写成HiveImportTask类中的missionState属性,而不是hive_import_task表中的mission_state字段。

3. 解决错误


hiveImportTaskMapper.xml中的#{mission_state}修改成HiveImportTask类中的missionState属性,如下代码所示:

<insert id="saveTask" parameterType="com.xxx.pojo.po.HiveImportTask">
    INSERT INTO hive_import_task (
        `mission_id`, `dataset_id`, `request_config`,
        `mission_state`, `user_id`, `create_time`,
        `update_time`
    )
    VALUES(
        #{missionId}, #{datasetId}, #{requestConfig},
        #{missionState}, #{userId}, #{createTime},
        #{updateTime}
    );
</insert>

在这里插入图片描述

此时,重新启动服务,再次使用postman测试,便能成功保存数据,如下图所示:

在这里插入图片描述

同时,使用mysql也能查询到保存的任务记录,如下代码所示:

mysql> SELECT * FROM hive_import_task \G;
*************************** 1. row ***************************
            id: 1
    mission_id: uuuddssdddsssss
    dataset_id: 1
request_config: {"cron":"0 0 11 * * ?","tableImportType":"1","incrementColumn":"projectname","hiveTableName":"project","pkColumn":"id","datasetId":2}
 mission_state: start
       user_id: 1
   create_time: 2023-03-22 17:45:32
   update_time: 2023-03-22 17:45:32
       deleted:
1 row in set (0.00 sec)

4. 解决该错误的其他方法


如果我上述错误的解决方法,无法解决你的错误,可以参考如下解决方法。

假如,我们在xxxMapper.java接口中的入参为java.lang.Integer或者java.lang.String,在写对应的xxxMapper.xml文件时,就需要注意了。

如下为错误示例:

<select id="LangId" parameterType="java.lang.Integer" resultType="java.lang.Integer">
    select
    	trnsct_id
    from  
    	t_trnsct_way_l 
    where
    <if test="Id != null" >
        and id = #{Id}
    </if>
</select>

上述代码存在某些问题:首先入参是java.lang.Integer, 而不是map或者实体的入参方式。

对于这类单个入参,继而用if判断的,mybatis有自己的内置对象。

那么,本来Mybatis有自己的gettersetter方法,这里又指定了传入类型。

所以,在指定类型里面,获取不到getter方法,也就可以理解了。

因而,我们需要修改上述错误的代码,如下为正确的代码:

<select id="LangId" parameterType="java.lang.Integer" resultType="java.lang.Integer">
    select
    	trnsct_id
    from  
    	t_trnsct_way_l 
    where
    <if test="parameter != null" >
        and id = #{Id,jdbcType=INTEGER}
    </if>
</select>

当然,也可以在xxxMapper.java接口上添加@Param用来给传入参数命名,那么参数就被转化为Mybatis内置对象。

5. 文末总结


如果上述的方法无法解决你的错误,可以在评论区留言,大家共同进步。


版权声明:本文为lvoelife原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。