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

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只能认定它自己的接口,自己重写的接口是不能用的

猜你喜欢

转载自blog.csdn.net/qq_37225699/article/details/81916548