欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

关于mybatis自定义类型转换器时报没有找到相应的控制器处理的问题

程序员文章站 2024-02-21 23:34:16
...

mybatis的类型转换器typeHandler是mybatis用于Java类型与数据库类型之间的转换用到的东西,事实上mybatis的typeHandler已经能够应对大部分的场景了,但是有时候也会不够用,比如在使用枚举的时候,枚举有特殊的转化规则,这时就需要用到自定义的类型转换器来处理了。
我在使用时出现了两次这样类似的异常如图:

org.apache.ibatis.exceptions.PersistenceException: 
### Error building SqlSession.
### The error may exist in mapper/UserMapper.xml
### The error occurred while processing mapper_resultMap[userMapper]
### Cause: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class handler.SexEnumTypeHandler
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:80)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:64)
    at util.SqlSessionFactoryUtils.getSqlSessionFactory(SqlSessionFactoryUtils.java:28)
    at util.SqlSessionFactoryUtils.openSqlSession(SqlSessionFactoryUtils.java:42)
    at personal.Test.test1(Test.java:38)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at junit.framework.TestCase.runTest(TestCase.java:176)
    at junit.framework.TestCase.runBare(TestCase.java:141)
    at junit.framework.TestResult$1.protect(TestResult.java:122)
    at junit.framework.TestResult.runProtected(TestResult.java:142)
    at junit.framework.TestResult.run(TestResult.java:125)
    at junit.framework.TestCase.run(TestCase.java:129)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:121)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing SQL Mapper Configuration. Cause: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class handler.SexEnumTypeHandler
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:120)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parse(XMLConfigBuilder.java:98)
    at org.apache.ibatis.session.SqlSessionFactoryBuilder.build(SqlSessionFactoryBuilder.java:78)
    ... 20 more
Caused by: org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML. Cause: org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class handler.SexEnumTypeHandler
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:120)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.parse(XMLMapperBuilder.java:92)
    at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.loadXmlResource(MapperAnnotationBuilder.java:170)
    at org.apache.ibatis.builder.annotation.MapperAnnotationBuilder.parse(MapperAnnotationBuilder.java:121)
    at org.apache.ibatis.binding.MapperRegistry.addMapper(MapperRegistry.java:72)
    at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:97)
    at org.apache.ibatis.binding.MapperRegistry.addMappers(MapperRegistry.java:105)
    at org.apache.ibatis.session.Configuration.addMappers(Configuration.java:709)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.mapperElement(XMLConfigBuilder.java:359)
    at org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XMLConfigBuilder.java:118)
    ... 22 more
Caused by: org.apache.ibatis.type.TypeException: Unable to find a usable constructor for class handler.SexEnumTypeHandler
    at org.apache.ibatis.type.TypeHandlerRegistry.getInstance(TypeHandlerRegistry.java:360)
    at org.apache.ibatis.builder.BaseBuilder.resolveTypeHandler(BaseBuilder.java:143)
    at org.apache.ibatis.builder.MapperBuilderAssistant.buildResultMapping(MapperBuilderAssistant.java:377)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.buildResultMappingFromContext(XMLMapperBuilder.java:378)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:280)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElement(XMLMapperBuilder.java:252)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(XMLMapperBuilder.java:244)
    at org.apache.ibatis.builder.xml.XMLMapperBuilder.configurationElement(XMLMapperBuilder.java:116)
    ... 31 more
Caused by: java.lang.ClassCastException: handler.SexEnumTypeHandler cannot be cast to org.apache.ibatis.type.TypeHandler
    at org.apache.ibatis.type.TypeHandlerRegistry.getInstance(TypeHandlerRegistry.java:358)
    ... 38 more

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
    <resultMap id="userMapper" type="user">
        <result property="id" column="id"/>
        <result property="userName" column="user_name"/>
        <result property="sex" column="sex" 
            typeHandler="handler.SexEnumTypeHandler"/>
        <result property="mobile" column="mobile"/>
        <result property="tel" column="tel"/>
        <result property="email" column="email"/>
        <result property="note" column="note"/>
    </resultMap>
    <select id="getUser" resultMap="userMapper" parameterType="long">
        select id,user_name,password,sex,mobile,tel,email,note from t_user 
        where id=#{id}
    </select>
</mapper>

我先检查了数据库要转换的jdbc类型是否有些错,发现没有问题,然后检查sql语句自动转换的resultMap是否有指向到上面自己定义的resultMap,发现也没有问题,那么是不是自己定义的resultMap字段映射不对呢,这里我将我自定义的类型转换器换成了apache自己定义的。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.UserMapper">
    <resultMap id="userMapper" type="user">
        <result property="id" column="id"/>
        <result property="userName" column="user_name"/>
        <result property="sex" column="sex" 
            typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
        <result property="mobile" column="mobile"/>
        <result property="tel" column="tel"/>
        <result property="email" column="email"/>
        <result property="note" column="note"/>
    </resultMap>
    <select id="getUser" resultMap="userMapper" parameterType="long">
        select id,user_name,password,sex,mobile,tel,email,note from t_user 
        where id=#{id}
    </select>
</mapper>

然后执行了测试方法,发现测试通过了,说明是我自己定义的SexEnumTypeHandler枚举类型转换器出了问题。
那么我的自定义枚举类型哪里不对呢,后来发现是我实现的接口的包不对,我导入的是我自己写的接口的包,我换成apache的包后就好了。
那么问题又来了,我自己写的接口那里不对呢?

package handler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
/*import org.apache.ibatis.type.TypeHandler;*/

import pojo.SexEnum;



@MappedTypes(SexEnum.class)
@MappedJdbcTypes(JdbcType.INTEGER)
public class SexEnumTypeHandler implements TypeHandler<SexEnum> {

    public void setParameter(PreparedStatement ps, int i, SexEnum parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getId());

    }

    public SexEnum getResult(ResultSet rs, String columnName) throws SQLException {
        int id = rs.getInt(columnName);
        return SexEnum.getSexById(id);
    }

    public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
        int id = rs.getInt(columnIndex);
        return SexEnum.getSexById(id);
    }

    public SexEnum getResult(CallableStatement cs, int columnIndex) throws SQLException {
        int id = cs.getInt(columnIndex);
        return SexEnum.getSexById(id);
    }

}

自己写的TypeHandler接口

package handler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.JdbcType;

public interface TypeHandler<T> {
     void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

      T getResult(ResultSet rs, String columnName) throws SQLException;

      T getResult(ResultSet rs, int columnIndex) throws SQLException;

      T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}

apachet提供的TypeHandler接口

/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.type;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Clinton Begin
 */
public interface TypeHandler<T> {

  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

  T getResult(ResultSet rs, String columnName) throws SQLException;

  T getResult(ResultSet rs, int columnIndex) throws SQLException;

  T getResult(CallableStatement cs, int columnIndex) throws SQLException;

}

后来经过大神指点原来Mybatis只能认定它自己的接口,自己重写的接口是不能用的

相关标签: ssm TypeHandler