mybatis There is no getter for property named 'xx' in 'class java.lang.String

本文介绍使用MyBatis查询时如何正确处理字符串参数,避免因属性获取错误而导致的问题,并提供正确的XML映射文件示例。
用mybatis查询时,传入一个字符串传参数,且进行判断时,会报

There is no getter for property named 'moduleCode' in 'class java.lang.String


错误写法:


<select id="queryAllParentModule" resultType="jobModule" parameterType="jobModule">
select modulecode,
modulename,
modulevalue,
linkurl,
rank,
parentmodule=isnull(parentmodule,1),
moduledescription
from job_module
<where>
<choose>
<when test="moduleCode!=null and moduleCode!=''">modulecode = #{moduleCode}</when>
<when test="moduleCode==null or moduleCode==''">(parentmodule is null or len(parentmodule)<=0)</when>
</choose>
</where>
</select>


需要修改成:


<select id="queryModuleByCode" resultType="jobModule" parameterType="string">
select modulecode,
modulename,
modulevalue,
linkurl,
rank,
parentmodule=isnull(parentmodule,1),
moduledescription
from job_module
<where>
<choose>
<when test="_parameter!=null and _parameter!=''">modulecode = #{_parameter}</when>
<when test="_parameter==null or _parameter==''">(parentmodule is null or len(parentmodule)<=0)</when>
</choose>
</where>
</select>


不管你的参数是什么,都要改成"_parameter"
<think> 我们遇到了一个MyBatis错误:`There is no getter for property named 'hosCode' in 'class java.lang.String'`。 这个错误通常发生在MyBatis试图访问一个对象的属性,但该对象是String类型(没有属性)时。 常见场景: 1. 在Mapper的XML中,我们使用了`#{}`或`${}`表达式,其中包含了一个属性名(例如`#{hosCode}`),但是传入的参数是一个String类型(而不是一个带有hosCode属性的对象)。 2. 例如,如果我们在Mapper方法中这样写: ```java User getUserByHosCode(@Param("hosCode") String hosCode); ``` 然后在XML中这样使用: ```xml SELECT * FROM user WHERE hos_code = #{hosCode} ``` 这是正确的,因为MyBatis知道从参数`hosCode`(被@Param命名为"hosCode")中获取值。 3. 但是,如果我们没有使用@Param注解,并且只有一个参数(String类型),那么在XML中应该直接使用`_parameter`(或者使用参数的索引,如`param1`),或者使用任意名称(因为MyBatis允许使用任何名称来引用单个参数,但要求使用`_parameter`或索引名更安全)。然而,如果我们错误地使用了属性名(例如`#{hosCode}`),而实际上传入的只是一个String,那么就会抛出上述错误。 4. 另一种常见情况是在动态SQL中(如<if>标签)使用了错误的变量名。 解决方案: 情况一:如果方法只有一个参数(String类型),且没有使用@Param注解: 错误写法:`<if test="hosCode != null">hos_code = #{hosCode}</if>` 正确写法1:使用`_parameter`(代表整个参数) `<if test="_parameter != null">hos_code = #{_parameter}</if>` 正确写法2:使用索引`param1` `<if test="param1 != null">hos_code = #{param1}</if>` 正确写法3:在方法参数上添加@Param注解,然后在XML中使用该名称。 情况二:在动态SQL的test表达式中,如果参数是String,我们想判断字符串是否为空,应该这样写: 错误写法:`<if test="hosCode != null and hosCode != ''">` (当参数是String时,这样写会报错,因为hosCode会被当成一个对象的属性) 正确写法:使用`_parameter`或者使用@Param注解给参数命名,然后在test中使用该名称。 示例代码: 错误示例: Mapper接口: User getUserByHosCode(String hosCode); XML: <select id="getUserByHosCode" resultType="User"> SELECT * FROM user WHERE <if test="hosCode != null"> <!-- 这里会报错,因为hosCode不是String对象的属性 --> hos_code = #{hosCode} </if> </select> 修正方法1:使用@Param注解 ```java User getUserByHosCode(@Param("hosCode") String hosCode); ``` XML: <if test="hosCode != null"> <!-- 现在hosCode是参数映射中的一个属性 --> hos_code = #{hosCode} </if> 修正方法2:不使用@Param,但在test中使用_parameter(注意:在test中判断字符串是否为空字符串时,需要额外判断) ```xml <select id="getUserByHosCode" resultType="User"> SELECT * FROM user <where> <if test="_parameter != null and _parameter != ''"> hos_code = #{_parameter} </if> </where> </select> ``` 修正方法3:使用默认的参数名param1(如果有多个参数,则使用param1, param2等) ```xml <select id="getUserByHosCode" resultType="User"> SELECT * FROM user <where> <if test="param1 != null and param1 != ''"> hos_code = #{param1} </if> </where> </select> ``` 总结: 当MyBatis报错`There is no getter for property named 'xxx' in 'class java.lang.String'`时,主要是因为我们在XML中使用了属性表达式(如`#{xxx}`或`${xxx}`),而传入的参数是String类型(或基本类型),MyBatis会试图从该参数中获取名为'xxx'的属性(通过getter方法),但String类型没有这个属性。 因此,我们需要: 1. 检查Mapper方法的参数是否使用了@Param注解,如果没有,则在XML中引用该参数时,应该使用`_parameter`(单个参数)或`param1`(第一个参数)等。 2. 或者,给参数加上@Param注解,指定一个名称,然后在XML中使用该名称。 另外,在动态SQL的test表达式中,同样需要按照上述规则使用正确的名称。 下面是一个完整的修正示例: 假设原始错误代码: Mapper接口: public interface UserMapper { User findByHosCode(String hosCode); } XML: <select id="findByHosCode" resultType="User"> SELECT * FROM user <where> <if test="hosCode != null"> AND hos_code = #{hosCode} </if> </where> </select> 修正后(使用@Param): Mapper接口: User findByHosCode(@Param("hosCode") String hosCode); XML不变。 或者修正为(不使用@Param,使用_parameter): <select id="findByHosCode" resultType="User"> SELECT * FROM user <where> <if test="_parameter != null"> AND hos_code = #{_parameter} </if> </where> </select> 注意:在test表达式中,`_parameter`代表整个传入的参数(这里就是hosCode字符串)。在值表达式`#{...}`中,我们也可以使用`_parameter`,但通常我们直接使用参数名(如果有@Param)或`_parameter`。 最后,如果我们的方法有多个参数,那么必须使用@Param注解来命名每个参数,否则在XML中只能通过param1, param2等索引来访问。 例如: User login(@Param("username") String username, @Param("password") String password); 然后在XML中: ... where username=#{username} and password=#{password} </think> ### 解决 MyBatis "There is no getter for property named 'hosCode'" 错误 这个错误通常发生在 MyBatis 尝试访问对象属性时,但指定的属性(hosCode)在参数对象中不存在。以下是完整的解决方案: #### 常见原因及解决方案 **1. 参数类型错误(最常见)** ```java // MyBatis Mapper 接口 public interface HospitalMapper { // ❌ 错误:直接传递 String 类型 Hospital findHospitalByCode(String hosCode); // ✅ 正确:使用 @Param 注解 Hospital findHospitalByCode(@Param("hosCode") String code); } ``` **2. XML 映射文件问题** ```xml <!-- 错误示例 --> <select id="findHospitalByCode" resultType="Hospital"> SELECT * FROM hospitals WHERE hos_code = #{hosCode} <!-- 没有指定参数来源 --> </select> <!-- 解决方案1:使用 @Param 别名 --> <select id="findHospitalByCode" resultType="Hospital"> SELECT * FROM hospitals WHERE hos_code = #{hosCode} </select> <!-- 解决方案2:使用 _parameter --> <select id="findHospitalByCode" resultType="Hospital"> SELECT * FROM hospitals WHERE hos_code = #{_parameter} <!-- 适用于单个参数 --> </select> ``` **3. 动态 SQL 中的问题** ```xml <!-- 错误示例 --> <select id="findHospitals" resultType="Hospital"> SELECT * FROM hospitals <where> <if test="hosCode != null"> <!-- 这里会报错 --> hos_code = #{hosCode} </if> </where> </select> <!-- 解决方案 --> <select id="findHospitals" resultType="Hospital"> SELECT * FROM hospitals <where> <!-- 使用 param 前缀 --> <if test="param1.hosCode != null"> hos_code = #{param1.hosCode} </if> <!-- 或使用 @Param 别名 --> <if test="criteria.hosCode != null"> hos_code = #{criteria.hosCode} </if> </where> </select> ``` **4. 完整的修复示例** ```java // 实体类 public class Hospital { private Long id; private String hosCode; // 确保有 getHosCode() 方法 // 必须要有 getter 方法 public String getHosCode() { return hosCode; } } // Mapper 接口 public interface HospitalMapper { // ✅ 正确用法1:使用 @Param Hospital findByCode(@Param("hosCode") String code); // ✅ 正确用法2:传递对象参数 Hospital findByCriteria(HospitalCriteria criteria); } // 查询条件类 public class HospitalCriteria { private String hosCode; public String getHosCode() { return hosCode; } } ``` ```xml <!-- Mapper XML --> <select id="findByCode" resultType="Hospital"> SELECT * FROM hospitals WHERE hos_code = #{hosCode} </select> <select id="findByCriteria" resultType="Hospital"> SELECT * FROM hospitals <where> <if test="hosCode != null and hosCode != ''"> hos_code = #{hosCode} </if> </where> </select> ``` #### 根本原因分析 1. **参数绑定问题**: - MyBatis 默认需要 POJO 对象或使用 `@Param` 注解 - 直接传递 String/基本类型时,MyBatis 尝试从对象中查找属性 2. **OGNL 表达式问题**: - MyBatis 在动态 SQL 中使用 OGNL 表达式解析属性 - `test="hosCode != null"` 会尝试访问 `getHosCode()` 方法 3. **缺失 Getter 方法**: - 即使对象包含字段,缺少 getter 方法也会导致错误 #### 完整解决方案总结 | 情况 | 解决方案 | |------|----------| | 单个字符串参数 | 使用 `@Param("hosCode")` 或 `#{_parameter}` | | 动态 SQL 测试 | 使用 `param1.hosCode` 或 `@Param` 别名 | | 对象参数 | 确保对象有对应的 getter 方法 | | 集合参数 | 使用 `@Param` 或 `list[0].hosCode` | #### 调试技巧 在 MyBatis 配置中启用完整日志: ```xml <!-- mybatis-config.xml --> <configuration> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> </configuration> ``` 检查实际传递的参数类型: ```java // 在 Mapper 方法中添加日志 public interface HospitalMapper { default Hospital findHospital(String code) { System.out.println("Parameter type: " + code.getClass().getName()); return findHospitalByCode(code); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值