java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy0 implementing (解决)

本文解决了Spring框架中由于AOP代理导致的类型转换错误问题,提供了两种解决方案:一种是在<aop:config/>中增加proxy-target-class属性;另一种是在事务配置bean中设置proxyTargetClass为true。

Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy0 implementing com.mysoft.applications.database.interfaces.MyInterface,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [ibatis.ibator.services.TestService] for property 'service': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:231)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:138)
    at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:386)
    ... 42 more

 

如果在Spring配置文件中配置的事务是通过AOP标签实现的,那就在<aop:config />中增加proxy-target-class="true"属性。就异常显示的信息可以看到,Spring在转换时,主要是将代理类转换成接口,反而不能转换成实际类。

如果是通过bean方式增加事务控制,则在配置文件中增加

<!--     <bean  -->
<!--         class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">  -->
<!--          <property name="proxyTargetClass">  -->
<!--            <value>true</value>  -->
<!--        </property>        -->
<!--      </bean>  -->

去掉上面的注释

上面这段配置信息只是一部分。其他的各位再摸索吧!

这里有个兄弟也是这样的问题,他的是bean控制事务的http://longterm.javaeye.com/blog/394395

<think>我们正在处理一个MyBatis框架中出现的异常:`org.apache.ibatis.exceptions.PersistenceException`,其根本原因是`java.lang.IllegalArgumentException: Unable to convert type java.lang.Character of % to type of java.lang.CharSequence`。这个错误通常发生在MyBatis执行SQL映射语句时,参数类型转换失败。 根据引用[5]中提到的类似问题(时间参数比较的bug),我们可以推测这里也是由于类型转换问题导致的。具体错误信息指出:无法将类型为`java.lang.Character`的'%'转换为`java.lang.CharSequence`。这通常发生在MyBatis处理SQL语句中的参数时,特别是在使用`like`查询时,我们常常会使用`%`作为通配符,而这里可能将`%`当作一个字符(Character)传递,而MyBatis在处理时期望它是一个字符串(CharSequence)。 解决方案的核心在于确保传递给MyBatis的参数类型正确。 ### 错误原因分析 1. **参数类型不匹配**:在SQL映射文件中,可能有一个查询使用了`like`,例如: ```sql SELECT * FROM table WHERE column LIKE #{param} ``` 而我们在传递参数时,可能传递了一个字符(例如`'%'`)而不是字符串(例如`"%"`)。在Java中,字符字面量用单引号,字符串用双引号。如果我们在Java代码中传递了一个`char`类型的值(如`'%'`),而MyBatis期望的是字符串,就会导致类型转换失败。 2. **错误的参数传递**:另一种可能是我们在传递参数时,将`%`直接拼接在字符串中,但MyBatis在处理参数时,可能因为某些原因(如使用了`${}`而不是`#{}`)导致类型推断错误。 ### 解决方案 #### 方法一:确保传递字符串类型的参数 在Java代码中,确保传递给`like`语句的参数是字符串(String)类型,而不是字符(Character)类型。例如: ```java // 错误示例:传递了字符 char c = '%'; String param = c; // 这样转换后是字符串,但直接传递字符是不行的 // 正确做法:使用字符串 String param = "%"; ``` 在Mapper接口中,参数应该是字符串类型: ```java List<Entity> findByPattern(String pattern); ``` 在映射文件中: ```xml <select id="findByPattern" resultType="Entity"> SELECT * FROM table WHERE column LIKE #{pattern} </select> ``` 调用时: ```java String pattern = "%keyword%"; List<Entity> result = mapper.findByPattern(pattern); ``` #### 方法二:在SQL映射中使用CONCAT函数 如果参数是单个字符(比如我们想匹配以某个字符开头),那么我们可以使用`CONCAT`函数来构建字符串: ```xml <select id="findByPattern" resultType="Entity"> SELECT * FROM table WHERE column LIKE CONCAT(#{pattern}, '%') </select> ``` 这里,`pattern`可以是一个字符,但通过`CONCAT`将其转换为字符串。 #### 方法三:检查参数传递方式 避免在SQL语句中直接使用`${}`进行字符串拼接,因为这样容易引发类型问题,而且不安全(有SQL注入风险)。尽量使用`#{}`进行参数绑定。 #### 方法四:检查MyBatis版本 如果上述方法不能解决问题,可能是MyBatis的版本存在bug。尝试升级到最新版本,因为MyBatis团队可能会修复这类类型转换的问题。 ### 示例代码 假设我们有一个根据用户名模糊查询的需求,我们这样实现: Mapper接口: ```java public interface UserMapper { List<User> findByNameLike(String pattern); } ``` XML映射文件: ```xml <select id="findByNameLike" resultType="User"> SELECT * FROM user WHERE name LIKE #{pattern} </select> ``` 调用代码: ```java String pattern = "%张%"; // 查找包含“张”字的用户 List<User> users = userMapper.findByNameLike(pattern); ``` ### 总结 这个错误的关键在于参数类型不匹配。确保在传递`like`语句的参数时使用字符串(String)类型,并且在SQL映射中正确使用参数占位符(`#{}`)。如果问题仍然存在,检查MyBatis版本并考虑升级。 ### 引用说明 在引用[5]中,我们看到了类似的问题(时间类型比较的bug),这提醒我们在MyBatis中参数类型匹配的重要性[^5]。 §§相关问题§§ 1. MyBatis中`#{}`和`${}`有什么区别? 2. 如何避免MyBatis中的SQL注入问题? 3. MyBatis中如何处理日期类型的参数? </think> ### 解决 `PersistenceException: Unable to convert type java.lang.Character of % to type of java.lang.CharSequence` 该错误通常发生在 MyBatis 处理 SQL 语句时,尝试将 `%` 字符(Java 的 `Character` 类型)转换为字符串(`CharSequence`)失败。以下是完整解决方案: #### 1. **问题根源分析** - **直接原因**:在 SQL 语句的 `LIKE` 查询中,`%` 通配符被当作 `Character` 类型处理,但 MyBatis 预期其为字符串(`CharSequence`)。 - **典型场景**: ```sql -- 错误示例:直接使用字符 '%' SELECT * FROM users WHERE name LIKE #{prefix} -- 若参数是字符 '%' 而非字符串 "%" ``` #### 2. **解决方案** ##### ✅ 方法一:确保参数为字符串类型 在 Java 代码中显式使用字符串包裹 `%`: ```java // 正确做法:传递字符串类型参数 String prefix = "%"; // 使用双引号定义字符串 List<User> users = userMapper.findByNameLike(prefix + "John"); ``` 对应的 Mapper 接口: ```java List<User> findByNameLike(String pattern); ``` ##### ✅ 方法二:在 SQL 中拼接通配符 在 XML 映射文件中使用 `CONCAT` 函数: ```xml <select id="findByNameLike" resultType="User"> SELECT * FROM users WHERE name LIKE CONCAT(#{prefix}, '%') <!-- 自动转为字符串 --> </select> ``` 此时 Java 代码只需传递前缀值: ```java userMapper.findByNameLike("John"); // 无需手动添加 % ``` ##### ✅ 方法三:使用 `<bind>` 标签(动态 SQL) 在 MyBatis 映射文件中动态构建参数: ```xml <select id="findByNameLike" resultType="User"> <bind name="pattern" value="prefix + '%'" /> <!-- 强制转为字符串 --> SELECT * FROM users WHERE name LIKE #{pattern} </select> ``` #### 3. **验证与注意事项** 1. **参数类型检查**: ```java // 错误示例:避免使用字符类型 char c = '%'; // 字符类型会引发转换异常 userMapper.findByNameLike(c); // 导致错误 ``` 2. **日志调试**:在 `mybatis-config.xml` 开启日志: ```xml <configuration> <settings> <setting name="logImpl" value="STDOUT_LOGGING" /> </settings> </configuration> ``` 3. **版本兼容性**:升级 MyBatis 至最新版(如 3.5.6+),部分早期版本存在类型推断缺陷[^5]。 #### 4. **总结步骤** 1. 确认 SQL 中 `LIKE` 子句的参数是否为字符串类型; 2. 避免直接传递 `Character` 类型的 `%`,改用字符串 `"%"`; 3. 优先使用 SQL 函数(`CONCAT`)或 MyBatis 动态标签(`<bind>`)构建通配符; 4. 升级 MyBatis 版本并检查日志。 > **引用说明**:类似问题曾出现在时间类型与字符串的错误比较中,核心在于类型匹配[^5]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值