英文:
iBatis (version 2.0) with Java 1.5 code throwing : No type handler could be found to map the property 'codec' to the column 'codec'
问题
我正在处理一个使用Java 1.5、PostgreSQL 8.4.20和iBatis版本<2.3.4.726的遗留应用程序(因为我必须使用两个iBatis的jar,分别是ibatis-common-2.jar和ibatis-sqlmap-2.jar)。我必须将编解码器用作Java枚举,并且数据库中的对应列是varchar。在尝试从后端数据库获取数据并在屏幕上显示时,我遇到了以下错误:
[root@cent610-server iBatis-jdk18-work]# javac15 -cp .:jars-old-postgre/ibatis-sqlmap-2.jar:jars-old-postgre/ibatis-common-2.jar:jars-old-postgre/postgresql.jdbc3.jar:jars-old-postgre/commons-logging-1.1.1.jar com/dummy/iBatis/*.java
[root@cent610-server iBatis-jdk18-work]#
[root@cent610-server iBatis-jdk18-work]# java15 -cp .:jars-old-postgre/ibatis-sqlmap-2.jar:jars-old-postgre/ibatis-common-2.jar:jars-old-postgre/postgresql.jdbc3.jar:jars-old-postgre/commons-logging-1.1.1.jar com/dummy/iBatis/EnumMain5
正在读取记录.....
异常线程"main"中出现异常"com.ibatis.common.jdbc.exception.NestedSQLException:
---出现错误的位置是SqlMapPostgre.xml。
---在应用结果映射时出现错误。
---检查codec-dscp-result。
---检查属性为'codec'的结果映射。
---原因:com.ibatis.sqlmap.client.SqlMapException:找不到映射属性'codec'到列'codec'的类型处理程序。类型或类型组合中的一个或两个不受支持。
原因:com.ibatis.sqlmap.client.SqlMapException:找不到映射属性'codec'到列'codec'的类型处理程序。类型或类型组合中的一个或两个不受支持。
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:183)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:99)中
在com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:561)中
在com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:536)中
在com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:97)中
在com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:69)中
在com.dummy.iBatis.EnumMain5.main(EnumMain5.java:28)中
由com.ibatis.sqlmap.client.SqlMapException引起:找不到将属性'codec'映射到列'codec'的类型处理程序。类型或类型组合中的一个或两个不受支持。
在com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getPrimitiveResultMappingValue(BasicResultMap.java:521)中
在com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicResultMap.java:274)中
在com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:354)中
在com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:179)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:200)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:168)中
... 6 more中
由于:com.ibatis.sqlmap.client.SqlMapException引发:
找不到将属性'codec'映射到列'codec'的类型处理程序。类型或类型组合中的一个或两个不受支持。
在com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getPrimitiveResultMappingValue(BasicResultMap.java:521)中
在com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicResultMap.java:274)中
在com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:354)中
在com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:179)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:200)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:168)中
在com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:99)中
在com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:561)中
在com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:536)中
在com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:97)中
在com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:69)中
在com.dummy.iBatis.EnumMain5.main(EnumMain5.java:28)中
[root@cent610-server iBatis-jdk18-work]#
注意,使用单个iBatis 2.3.4.726的jar,与JDK1.5代码库一起使用,而不使用任何自定义类型处理程序,可以顺利运行,但在我的遗留应用程序中,我必须使用旧版本的iBatis。
这是数据库架构:
表 "public.enumtest"
列 | 类型 | 修改器
--------+-----------------------+-----------
id | integer | not null
codec | character varying(10) | not null
dscp | integer | not null
索引:
"enumtest_pkey" PRIMARY KEY, btree (id)
这是具有主要功能的类:EnumMain5.java,用于从后端数据库拉取数据并显示:
package com.dummy.iBatis;
import java.io.Reader;
import java.util.List;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
public class EnumMain5 {
public static void main(String[] args) throws Exception {
String resource = "SqlMapConfigPostgre.xml";
Reader reader = Resources.getResourceAsReader(resource);
SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(reader);
int id = 4;
System.out.println("Going to read record.....");
EnumiBatisTest e = (
<details>
<summary>英文:</summary>
I'm working on a legacy application using Java 1.5, PostgreSQL 8.4.20 and iBatis version < 2.3.4.726 (as I've to use two jars for iBatis namely ibatis-common-2.jar & ibatis-sqlmap-2.jar) . I've to use codec as Java Enum and corresponding column in db is varchar. While trying to get data from backend db and displaying on screen I get the following error:
[root@cent610-server iBatis-jdk18-work]# javac15 -cp .:jars-old-postgre/ibatis-sqlmap-2.jar:jars-old-postgre/ibatis-common-2.jar:jars-old-postgre/postgresql.jdbc3.jar:jars-old-postgre/commons-logging-1.1.1.jar com/dummy/iBatis/*.java
[root@cent610-server iBatis-jdk18-work]#
[root@cent610-server iBatis-jdk18-work]# java15 -cp .:jars-old-postgre/ibatis-sqlmap-2.jar:jars-old-postgre/ibatis-common-2.jar:jars-old-postgre/postgresql.jdbc3.jar:jars-old-postgre/commons-logging-1.1.1.jar com/dummy/iBatis/EnumMain5
Going to read record.....
Exception in thread "main" com.ibatis.common.jdbc.exception.NestedSQLException:
--- The error occurred in SqlMapPostgre.xml.
--- The error occurred while applying a result map.
--- Check the codec-dscp-result.
--- Check the result mapping for the 'codec' property.
--- Cause: com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'codec' to the column 'codec'. One or both of the types, or the combination of types is not supported.
Caused by: com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'codec' to the column 'codec'. One or both of the types, or the combination of types is not supported.
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:183)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:99)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:561)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:536)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:97)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:69)
at com.dummy.iBatis.EnumMain5.main(EnumMain5.java:28)
Caused by: com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'codec' to the column 'codec'. One or both of the types, or the combination of types is not supported.
at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getPrimitiveResultMappingValue(BasicResultMap.java:521)
at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicResultMap.java:274)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:354)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:179)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:200)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:168)
... 6 more
Caused by:
com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'codec' to the column 'codec'. One or both of the types, or the combination of types is not supported.
at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getPrimitiveResultMappingValue(BasicResultMap.java:521)
at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.getResults(BasicResultMap.java:274)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:354)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:179)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery(GeneralStatement.java:200)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback(GeneralStatement.java:168)
at com.ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryForObject(GeneralStatement.java:99)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:561)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.queryForObject(SqlMapExecutorDelegate.java:536)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.queryForObject(SqlMapSessionImpl.java:97)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.queryForObject(SqlMapClientImpl.java:69)
at com.dummy.iBatis.EnumMain5.main(EnumMain5.java:28)
[root@cent610-server iBatis-jdk18-work]#
Note that, using the single iBatis 2.3.4.726 jar with JDK1.5 codebase without any custom typehandler works smoothly, but on my legacy application I've to use older iBatis version.
Here is the db schema:
Table "public.enumtest"
Column | Type | Modifiers
--------+-----------------------+-----------
id | integer | not null
codec | character varying(10) | not null
dscp | integer | not null
Indexes:
"enumtest_pkey" PRIMARY KEY, btree (id)
This is the class with main:EnumMain5.java, it is used for pulling the data from backend db and displaying :
package com.dummy.iBatis;
import java.io.Reader;
import java.util.List;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
/**
-
@author geek
*
*/
public class EnumMain5 {/** * @param args */ public static void main(String[] args) throws Exception { // TODO Auto-generated method stub String resource = "SqlMapConfigPostgre.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlMapClient smc = SqlMapClientBuilder.buildSqlMapClient(reader); int id = 4; System.out.println("Going to read record....."); EnumiBatisTest e = (EnumiBatisTest)smc.queryForObject ("getCodecDscpPairValues", id); System.out.println("dscp: " + e.getDscp()); System.out.println("codec: " + e.getCodec()); System.out.println("Record read Successfully "); }
}
Other Java class files are as below
EnumiBatisTest:
package com.dummy.iBatis;
/**
-
@author geek
*
*/
public class EnumiBatisTest {/* codec value for a pair */ private Codec codec; /* dscp value for a pair */ private Integer dscp; /** * @return the codec */ public Codec getCodec() { return codec; } /** * @param codec the codec to set */ public void setCodec(Codec codec) { this.codec = codec; } /** * @return the dscp */ public Integer getDscp() { return dscp; } /** * @param dscp the dscp to set */ public void setDscp(Integer dscp) { this.dscp = dscp; }
}
SqlMapConfigPostgre.xml :
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings
lazyLoadingEnabled="false"
cacheModelsEnabled="true"
enhancementEnabled="true"
errorTracingEnabled="false"
maxRequests="512"
maxSessions="128"
maxTransactions="32"
/>
<typeHandler callback="com.dummy.iBatis.CodecTypeHandlerCallback" javaType="com.dummy.iBatis.Codec" jdbcType="VARCHAR"/>
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="org.postgresql.Driver"/>
<property name="JDBC.ConnectionURL" value="jdbc:postgresql://localhost:7654/mydb"/>
<property name="JDBC.Username" value="dbuser"/>
<property name="JDBC.Password" value="nano123"/>
</dataSource>
</transactionManager>
<sqlMap resource="SqlMapPostgre.xml" />
</sqlMapConfig>
Codec.java :
package com.dummy.iBatis;
public enum Codec {
G711, G729, UNDEFINED;
}
Custom typehandler callback class CodecTypeHandlerCallback is:
package com.dummy.iBatis;
/**
*
*/
import java.sql.SQLException;
import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.ResultGetter;
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
/**
-
@author geek
*
*/
public class CodecTypeHandlerCallback implements TypeHandlerCallback {private static final String G711 = "G711";
private static final String G729 = "G729";
private static final String UNDEFINED = null;public void setParameter(
ParameterSetter setter, Object parameter
) throws SQLException {
setter.setString(enumToString((Enum) parameter));
}private String enumToString(Enum b) {
if (b == null) {
return UNDEFINED;
} else if (b==Codec.G711) {
return G711;
} else if (b==Codec.G729) {
return G729;
} else
return UNDEFINED;
}
private Enum stringToEnum(String str) {
if (str == null) return Codec.UNDEFINED;
if (str.toUpperCase().indexOf("G711") >= 0) return Codec.G711;
if (str.toUpperCase().indexOf("G729") >= 0) return Codec.G729;
return Codec.UNDEFINED;
}public Object getResult(ResultGetter getter)
throws SQLException {
return stringToEnum(getter.getString());
}public Object valueOf(String s) {
return stringToEnum(s);
}
}
SqlMapPostgre.xml is as below:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>
<resultMap id="codec-dscp-result"
class="com.dummy.iBatis.EnumiBatisTest">
<result property="dscp" column="dscp"/>
<result property="codec" column="codec"/>
</resultMap>
<select id="getCodecDscpPairValues"
resultMap="codec-dscp-result"
parameterClass="int">
SELECT codec, dscp
FROM enumtest
where id=#id#
</select>
</sqlMap>
What is missing here? How to properly use the custom typehandler mentioned here? I also checked the custom type handler example(YesNo one) from iBatis docs: https://livebook.manning.com/book/ibatis-in-action/chapter-12/ and created my custom type handler.
Anything wrong with iBatis configuration xml files?
Appreciate your time.
</details>
# 答案1
**得分**: 0
经过尝试了许多方法并搜索了网络教程,找到了一个快速解决方案(当然还有其他很多方法,这只是一种方法):在 SqlMapConfigPostgre.xml 文件中,从 typehandler 语句中移除这部分 **jdbcType="VARCHAR"**。
简而言之,将这一行更新为:
```xml
<typeHandler callback="com.dummy.iBatis.CodecTypeHandlerCallback" javaType="com.dummy.iBatis.Codec"/>
编译并运行代码,应该可以正常工作,没有任何问题。
希望这对于遇到类似问题的人有所帮助。
英文:
After trying lot many things and searching the web tutorials, found a quick solution(there could be many other ways as well, this is just one approach): In SqlMapConfigPostgre.xml file, remove this part jdbcType="VARCHAR" from typehandler statement.
In short update this line:
<typeHandler callback="com.dummy.iBatis.CodecTypeHandlerCallback" javaType="com.dummy.iBatis.Codec" jdbcType="VARCHAR"/>
to this:
<typeHandler callback="com.dummy.iBatis.CodecTypeHandlerCallback" javaType="com.dummy.iBatis.Codec"/>
Compile and run the code, it should work without any issue.
Hope this helps someone dealing with similar problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论