2017-01-07 3 views
0

Mybatisを初めて使用しています。最近、私はカスタムのジェネリック型のHanderを使用しました.Beanのプロパティがテーブルの列名と同じ場合、selectはClassCastExceptionを発生させます。Mybatisがカスタムジェネリック型ハンドラを使用していて、Beanプロパティ名とテーブルの列が同じ場合、SelectがClassCastExceptionを発生させます。

:後

は、コンフィギュレーション

MyBatisの-configuration.xmlの

<typeHandlers> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.WhetherTypeEnum" jdbcType="CHAR"/> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.SexTypeEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.ArticleTypeEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.EducationLevelEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.ServiceLevelEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.ServiceTypeEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.StaffLevelEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.ArticleStatusEnum" jdbcType="CHAR" /> 
     <typeHandler handler="com.sut.util.enumerate.mybatis.GenericEnumUserType" 
      javaType="com.sut.util.meta.HealthyStatusEnum" jdbcType="CHAR" /> 
</typeHandlers> 

staffMapper.xml

<resultMap type="com.sut.persist.entity.Staff" id="staff"> 
    <id property="id" javaType="int" column="id" /> 
    <result property="staffName" javaType="String" column="STAFF_NAME" /> 
    <result property="imgPath" javaType="String" column="IMG_PATH" /> 
    <result property="staffLevel" javaType="com.sut.util.meta.StaffLevelEnum" column="LEVEL" 
     typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" jdbcType="CHAR"/> 
    <result property="birthDate" javaType="java.util.Date" column="BIRTH_DATE" /> 
    <result property="address" javaType="String" column="address" /> 
    <result property="healthyStatus" javaType="com.sut.util.meta.HealthyStatusEnum" column="HEALTHY_STATUS" 
     typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" jdbcType="CHAR" /> 
    <result property="education" column="education" typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" /> 
    <result property="workYears" javaType="integer" column="WORK_YEARS" /> 
    <result property="selfIntroduction" javaType="String" column="SELF_INTRODUCTION" /> 
    <result property="cert" javaType="String" column="CERT" /> 
    <result property="remark" javaType="String" column="REMARK" /> 
    <result property="serviceType" javaType="com.sut.util.meta.ServiceTypeEnum" column="SERVICE_TYPE" 
     typeHandler="com.sut.util.enumerate.mybatis.GenericEnumUserType" /> 
    <result property="mobile" javaType="String" column="MOBILE" /> 
    <result property="qqNumber" javaType="String" column="QQ_NUMBER" /> 
    <result property="webchatNumber" javaType="String" column="WEBCHAT_NUMBER" /> 
    <result property="webchatQrcode" javaType="String" column="WEBCHAT_QRCODE" /> 
</resultMap> 

<!-- query user by id --> 
<select id="getById" parameterType="long" resultMap="staff"> 
    select 
     staff_id, 
     staff_name, 
     img_path, 
     level as staffLevel, 
     birth_date, 
     address, 
     healthy_status as healthyStatus, 
     education as education, 
     work_years, 
     self_introduction, 
     cert, 
     remark, 
     service_type as serviceType, 
     mobile, 
     qq_number, 
     webchat_number, 
     webchat_qrcode 
    from bbs_staff where staff_id = #{id} 

Staff.javaです

com.sut.util.enumerate.mybatis.GenericEnumUserType:ジェネリックTypeHandlerを使用した場合

Struts has detected an unhandled exception: 

Messages: 
[email protected] 
Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value '[email protected]' Cause: java.lang.IllegalArgumentException: [email protected] 
nested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'education' of 'class com.sut.persist.entity.Staff' with value '[email protected]' Cause: java.lang.IllegalArgumentException: [email protected] 

MyBatisのドキュメントは言った:getByIdメソッドを呼び出すと、それは例外を発生させます

public class GenericEnumUserType<E extends StringEnumTypeImp> extends BaseTypeHandler<E>{ 

    private static final Logger LOG = LoggerFactory.getLogger(GenericEnumUserType.class); 

    //mybatis will pass actual class when constructing TypeHandler 
    private Class<E> type; 

    private static final String fromStringCode = "fromStringCode"; 

    public GenericEnumUserType(Class<E> type){ 
     Preconditions.checkNotNull(type, "Type argument cannot be null"); 
     this.type = type; 
    } 

    /** 
    * @see org.apache.ibatis.type.BaseTypeHandler#setNonNullParameter(java.sql.PreparedStatement, int, java.lang.Object, org.apache.ibatis.type.JdbcType) 
    */ 
    @Override 
    public void setNonNullParameter(PreparedStatement ps, int i, StringEnumTypeImp parameter, JdbcType jdbcType) throws SQLException { 
     ps.setString(i, parameter.getStoreValue()); 
    } 

    /** 
    * getResult and use reflect 
    * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, java.lang.String) 
    */ 
    @Override 
    @SuppressWarnings("unchecked") 
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException { 
     LOG.info("return type is : {}", type); 
     String storeValue = rs.getString(columnName); 
     Preconditions.checkNotNull(type, "Type argument cannot be null"); 
     try { 
      Method fromMethod = type.getMethod(fromStringCode, String.class); 
      return (E) fromMethod.invoke(null, storeValue); 
     } catch (IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    /** 
    * 
    * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.ResultSet, int) 
    */ 
    @SuppressWarnings("unchecked") 
    @Override 
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 
     LOG.info("return type is {}", type); 
     String storeValue = rs.getString(columnIndex); 
     Preconditions.checkNotNull(type, "Type argument cannot be null"); 
     try { 
      Method fromMethod = type.getMethod(fromStringCode, String.class); 
      return (E) fromMethod.invoke(null, storeValue); 
     } catch (IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

    /** 
    * not used 
    * @see org.apache.ibatis.type.BaseTypeHandler#getNullableResult(java.sql.CallableStatement, int) 
    */ 
    @Override 
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 
     try { 
      return type.newInstance(); 
     } catch (InstantiationException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 

} 

JavaTypeによって、jdbcTypeがnullであっても、正しいTypeHandlerを取得します。設定を3回チェックし、ソースコードをデバッグしました。次に、ResultSetWrapperがmappedColumnsとUnmappedColumnsに列を分離し、mappedColumnsがそうでないので、unmappedColumnsが正しいTypeHandlerを返すことがわかります。私はなぜこれが起こるのか不思議です。これはバグですか、私の設定が正しくありません。

環境:
MyBatisの:3.4.1
のMySQL:5.6

任意の助けが理解されるであろう!あなたの実際のmapper.xmlで

+0

こんにちは、(MyBatisのは、それをやらせる)結果マッピングからハンドラを削除w。 com.sut.util.enumerate.mybatis.GenericEnumUserTypeの実装も提供してください。 – hakamairi

+0

ありがとうございます。 'GenericEnumUserType'コードを追加しました。 –

+0

Staffクラスも追加してください。 – hakamairi

答えて

0

あなたが列挙型は種類

<result property="educationLevel" column="education" javaType="com.sut.util.meta.EducationLevelEnum" jdbcType="CHAR" /> 
  • あなたからプロパティ名に一致するPOJO educationLevel代わりの教育
  • がJavaTypeが及びjdbcTypeを提供取り扱うために次の操作を実行しようとすることができます
  • Stackoverfloへようこそ
+0

これは動作しました!しかし、私は理由を把握することができません –

+0

特定のjavaとjdbcタイプのペアに対してmyBatisでハンドラーを登録しました。今では、myBatisがハンドラを検索するタイプのものをベースにしています.JBCタイプをスキップすると、実際のP​​OJOからJavaタイプを検索しますが、それだけでそれを行うべきです。これは、実際のハンドラの作成(コンストラクタで適切なEnum型を提供する必要がある場合)にとって重要です。 – hakamairi

+0

あなたは正しいでしょう、これはresultMappingでカスタムタイプハンドラを使用する正しい方法かもしれません。ご協力いただきありがとうございます –

関連する問題