Skip to content

TypeHandler can't get the parameter type rightly when insert data #391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
vran-dev opened this issue Sep 1, 2021 · 2 comments
Closed

TypeHandler can't get the parameter type rightly when insert data #391

vran-dev opened this issue Sep 1, 2021 · 2 comments

Comments

@vran-dev
Copy link

vran-dev commented Sep 1, 2021

Context

Mybatis 3.5.7

Mybatis Dynamic SQL 1.3.0

Mybatis Generator 1.4.0

Description

If use org.apache.ibatis.type.EnumOrdinalTypeHandler, it will cause IllegalArgumentException when save data, but query (select) action is right.

would you help me solve this problem?thanks very much.

the follow is debug information, it shows that the parameterType is DefaultInsertStatementProvider
debug2

so, can't get property record.username

debug3

Generator configuration

public enum Gender {
    MALE, FEMALE;
}
<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <context id="dsql" targetRuntime="MyBatis3DynamicSql">

        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/user" userId="root" password=""/>

        <javaTypeResolver>
            <property name="useJSR310Types" value="true"/>
        </javaTypeResolver>

        <javaModelGenerator targetPackage="com.example.dao.model" targetProject="src/main/java"/>

        <javaClientGenerator targetPackage="com.example.dao.mapper" targetProject="src/main/java">
            <property name="rootInterface" value="org.mybatis.dynamic.sql.util.mybatis3.CommonSelectMapper"/>
        </javaClientGenerator>

        <!-- override typehandler -->
        <table tableName="user" domainObjectName="UserEntity">
            <generatedKey column="id" sqlStatement="JDBC" identity="true" type="post"/>
            <columnOverride column="gender"
                            javaType="com.example.core.domain.enums.Gender"
                            typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
        </table>
    </context>

</generatorConfiguration>

class

  • enum definition
public enum Gender {
    MALE, FEMALE;
}
  • generate mapper
@Mapper
public interface UserEntityMapper extends CommonSelectMapper {

    @InsertProvider(type=SqlProviderAdapter.class, method="insert")
    @Options(useGeneratedKeys=true,keyProperty="record.id")
    int insert(InsertStatementProvider<UserEntity> insertStatement);
        
    @SelectProvider(type=SqlProviderAdapter.class, method="select")
    @Results(id="UserEntityResult", value = {
        @Result(column="id", property="id", jdbcType=JdbcType.BIGINT, id=true),
        @Result(column="username", property="username", jdbcType=JdbcType.VARCHAR),
        @Result(column="gender", property="gender", typeHandler=EnumOrdinalTypeHandler.class, jdbcType=JdbcType.TINYINT),
        @Result(column="create_at", property="createAt", jdbcType=JdbcType.TIMESTAMP),
        @Result(column="update_at", property="updateAt", jdbcType=JdbcType.TIMESTAMP)
    })
    List<UserEntity> selectMany(SelectStatementProvider selectStatement);
}
  • generate sqlSupport
public final class UserEntityDynamicSqlSupport {

    public static final UserEntity userEntity = new UserEntity();

    // ignore...

    public static final class UserEntity extends SqlTable {
        // ignore...
        
        public final SqlColumn<Gender> gender = column("gender", JDBCType.TINYINT, "org.apache.ibatis.type.EnumOrdinalTypeHandler");

        // ignore...
        
        public UserEntity() {
            super("user");
        }
    }
}

Error Log

java.lang.IllegalArgumentException: Object does not represent an enum type.
        at org.apache.ibatis.type.EnumOrdinalTypeHandler.<init>(EnumOrdinalTypeHandler.java:38) ~[mybatis-3.5.7.jar:3.5.7]
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) ~[na:na]
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) ~[na:na]
        at org.apache.ibatis.type.TypeHandlerRegistry.getInstance(TypeHandlerRegistry.java:446) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.BaseBuilder.resolveTypeHandler(BaseBuilder.java:143) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.BaseBuilder.resolveTypeHandler(BaseBuilder.java:132) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:141) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:87) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:77) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:50) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.scripting.defaults.RawSqlSource.<init>(RawSqlSource.java:46) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.scripting.xmltags.XMLLanguageDriver.createSqlSource(XMLLanguageDriver.java:60) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.createSqlSource(ProviderSqlSource.java:189) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.builder.annotation.ProviderSqlSource.getBoundSql(ProviderSqlSource.java:156) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:305) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:41) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:658) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181) ~[mybatis-3.5.7.jar:3.5.7]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.6.jar:2.0.6]
        at com.sun.proxy.$Proxy72.insert(Unknown Source) ~[na:na]
        at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272) ~[mybatis-spring-2.0.6.jar:2.0.6]
        at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) ~[mybatis-3.5.7.jar:3.5.7]
        at com.sun.proxy.$Proxy82.insert(Unknown Source) ~[na:na]
        at org.mybatis.dynamic.sql.util.mybatis3.MyBatis3Utils.insert(MyBatis3Utils.java:115) ~[mybatis-dynamic-sql-1.3.0.jar:1.3.0]
        at com.example.dao.mapper.UserEntityMapper.insertSelective(UserEntityMapper.java:129) ~[main/:na]
        at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:728) ~[na:na]
        at org.apache.ibatis.binding.MapperProxy$DefaultMethodInvoker.invoke(MapperProxy.java:159) ~[mybatis-3.5.7.jar:3.5.7]
        at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) ~[mybatis-3.5.7.jar:3.5.7]
        at com.sun.proxy.$Proxy82.insertSelective(Unknown Source) ~[na:na]
        at com.example.dao.repository.UserRepositoryImpl.insertAndReturnPrimaryKey(UserRepositoryImpl.java:54) ~[main/:na]
        at com.example.dao.repository.UserRepositoryImpl$$FastClassBySpringCGLIB$$e83d209f.invoke(<generated>) ~[main/:na]
        at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779) ~[spring-aop-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.9.jar:5.3.9]
        at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.9.jar:5.3.9]
        at com.example.dao.repository.UserRepositoryImpl$$EnhancerBySpringCGLIB$$36431fb.insertAndReturnPrimaryKey(<generated>) ~[main/:na]
        at com.example.core.service.UserService.createUser(UserService.java:25) ~[main/:na]
        at com.example.api.facade.UserFacade.createUser(UserFacade.java:38) ~[main/:na]
        at com.example.api.controller.UserController.register(UserController.java:25) ~[main/:na]
        at com.example.api.controller.UserController$$FastClassBySpringCGLIB$$ba85c027.invoke(<generated>) ~[main/:na]
      
@jeffgbutler
Copy link
Member

There are two issues...

First, EnumOrdinalTypeHandler requires specifying the Java Type in the mapping. There is an unreleased enhancement for that (#386). You can try it with the snapshot version (1.3.1-SNAPHSOT) and changing the generated code like this

public final SqlColumn<AddressRecord.AddressType> addressType = column("address_type", JDBCType.INTEGER)
.withTypeHandler("org.apache.ibatis.type.EnumOrdinalTypeHandler")
.withJavaType(AddressRecord.AddressType.class);

I will release the updated version of MyBatis Dynamic SQL containing this enhancement soon.

The second issue is in the generator. The generator will need a change to generate code like this. That change will take longer.

@vran-dev
Copy link
Author

vran-dev commented Sep 1, 2021

thx, I will use the SNAPSHOT version before release

maybe the generator's problem could be solved by Extension Point, I‘ll try

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants