Allow registering a type handler for a common interface of enums. #947

Merged
merged 1 commit into from Mar 15, 2017

Conversation

Projects
None yet
5 participants
@harawata
Member

harawata commented Mar 15, 2017

It is common for multiple enums to have a common interface along with a corresponding type handler.
Up to version 3.4.2, to use this type handler, users had to list all the enum implementations in the @MappedType or <typeHandlers />.

This PR allows users to register the type handler against the common interface.
Please see the attached test case for how it works.

Cc-ing @gaohanghbut @liyuj @yxc023 @charlesluo2014 @Hubbitus @fengdh @Fayou @sskeater @jlkm2010
Thought you guys might be interested.

@harawata harawata added this to the 3.4.3 milestone Mar 15, 2017

@harawata harawata self-assigned this Mar 15, 2017

@harawata harawata merged commit f3bd219 into mybatis:master Mar 15, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@kazuki43zoo kazuki43zoo referenced this pull request in mybatis/spring-boot-starter Mar 15, 2017

Closed

about config enum type handler #150

kazuki43zoo added a commit to kazuki43zoo/mybatis-3 that referenced this pull request Mar 16, 2017

kazuki43zoo added a commit to kazuki43zoo/mybatis-3 that referenced this pull request Mar 16, 2017

@gaohanghbut

This comment has been minimized.

Show comment
Hide comment
@gaohanghbut

gaohanghbut Mar 20, 2017

@harawata thanks for your attribution

@harawata thanks for your attribution

@kazuki43zoo

This comment has been minimized.

Show comment
Hide comment
@kazuki43zoo

kazuki43zoo Apr 13, 2017

Member

Hi @harawata, I have one question.
I don't know how to convert to enum instance from result set value using this solution. I think that it need to set enum type to cutom TypeHandler for converting a enum instance. Could you tell me how to do it ?

Member

kazuki43zoo commented Apr 13, 2017

Hi @harawata, I have one question.
I don't know how to convert to enum instance from result set value using this solution. I think that it need to set enum type to cutom TypeHandler for converting a enum instance. Could you tell me how to do it ?

@harawata

This comment has been minimized.

Show comment
Hide comment
@harawata

harawata Apr 13, 2017

Member

@kazuki43zoo ,
I re-checked the code and you are right. This fix is incomplete :(
I'll create another PR soon.
Thank you for the review!

Member

harawata commented Apr 13, 2017

@kazuki43zoo ,
I re-checked the code and you are right. This fix is incomplete :(
I'll create another PR soon.
Thank you for the review!

harawata added a commit to harawata/mybatis-3 that referenced this pull request Apr 13, 2017

The last fix #947 was incomplete. Each enum should be mapped to a new…
… instance of the type handler that takes the enum type as a constructor argument.

@harawata harawata referenced this pull request Apr 14, 2017

Merged

Fixes incomplete PR #947. #976

harawata added a commit that referenced this pull request Apr 16, 2017

Merge pull request #976 from harawata/typehandler-for-enum-interface-…
…take2

Proper fix for #947 . When there is a type handler registered to a super interface of an enum, new instance of the type handler should be created with the enum type as a constructor argument.
@mahengyang

This comment has been minimized.

Show comment
Hide comment
@mahengyang

mahengyang Jul 20, 2017

the constractor of custom typehandler has some error

public HasValueEnumTypeHandler(Class<E> type) {
   if (type == null)
     throw new IllegalArgumentException("Type argument cannot be null");
   this.type = type;
   this.enums = type.getEnumConstants();

this.enums is aways null becase the parameter type is a interface

mahengyang commented Jul 20, 2017

the constractor of custom typehandler has some error

public HasValueEnumTypeHandler(Class<E> type) {
   if (type == null)
     throw new IllegalArgumentException("Type argument cannot be null");
   this.type = type;
   this.enums = type.getEnumConstants();

this.enums is aways null becase the parameter type is a interface

@harawata

This comment has been minimized.

Show comment
Hide comment
@harawata

harawata Jul 20, 2017

Member

@mahengyang

type is supposed to be an enum that implements HasValue interface, not the interface itself.

Member

harawata commented Jul 20, 2017

@mahengyang

type is supposed to be an enum that implements HasValue interface, not the interface itself.

@mahengyang

This comment has been minimized.

Show comment
Hide comment
@mahengyang

mahengyang Jul 21, 2017

@harawata if there is many enum,we need write every enum type handler in mybatis-config.xml, like this, Witch makes me feel a little verbose

<typeHandlers>
    <typeHandler javaType="com.qbike.eum.LeipaiOrderStatus" handler="com.qbike.mybatis.EnumTypeHandler"/>
    <typeHandler javaType="com.qbike.eum.TestStatus" handler="com.qbike.mybatis.EnumTypeHandler"/>
</typeHandlers>

the handler EnumTypeHandler

public class EnumTypeHandler<E extends Enum<E> & EnumCode> extends BaseTypeHandler<E> {
    private Class<E> type;
    private EnumCode[] enums;

    public EnumTypeHandler(Class<E> type) {
        this.type = type;
        this.enums = type.getEnumConstants();
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getCode());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return find(rs.getInt(columnName));
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return find(rs.getInt(columnIndex));
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return find(cs.getInt(columnIndex));
    }

    private E find(int status) {
        for (EnumCode enumCode : enums) {
            if (enumCode.getCode() == status) {
                return (E) enumCode;
            }
        }
        return null;
    }
}

mahengyang commented Jul 21, 2017

@harawata if there is many enum,we need write every enum type handler in mybatis-config.xml, like this, Witch makes me feel a little verbose

<typeHandlers>
    <typeHandler javaType="com.qbike.eum.LeipaiOrderStatus" handler="com.qbike.mybatis.EnumTypeHandler"/>
    <typeHandler javaType="com.qbike.eum.TestStatus" handler="com.qbike.mybatis.EnumTypeHandler"/>
</typeHandlers>

the handler EnumTypeHandler

public class EnumTypeHandler<E extends Enum<E> & EnumCode> extends BaseTypeHandler<E> {
    private Class<E> type;
    private EnumCode[] enums;

    public EnumTypeHandler(Class<E> type) {
        this.type = type;
        this.enums = type.getEnumConstants();
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getCode());
    }

    @Override
    public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return find(rs.getInt(columnName));
    }

    @Override
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return find(rs.getInt(columnIndex));
    }

    @Override
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return find(cs.getInt(columnIndex));
    }

    private E find(int status) {
        for (EnumCode enumCode : enums) {
            if (enumCode.getCode() == status) {
                return (E) enumCode;
            }
        }
        return null;
    }
}
@harawata

This comment has been minimized.

Show comment
Hide comment
@harawata

harawata Jul 21, 2017

Member

@mahengyang ,
Are you actually having a problem, or just reading the code?
this.enums being null should not be a problem because the instance registered against HasValue interface is not used when converting enums (a new instance is created and registered for each enum).

There is a working test case, so if you found a bug, please create a failing test case.
Thanks!

Note that there is a bug in 3.4.4 and you need to use 3.4.5-SNAPSHOT for now (I assumed you knew it seeing your comment on #976 ).

Member

harawata commented Jul 21, 2017

@mahengyang ,
Are you actually having a problem, or just reading the code?
this.enums being null should not be a problem because the instance registered against HasValue interface is not used when converting enums (a new instance is created and registered for each enum).

There is a working test case, so if you found a bug, please create a failing test case.
Thanks!

Note that there is a bug in 3.4.4 and you need to use 3.4.5-SNAPSHOT for now (I assumed you knew it seeing your comment on #976 ).

@michaelplavnik

This comment has been minimized.

Show comment
Hide comment
@michaelplavnik

michaelplavnik Dec 28, 2017

Implementation of the feature is still incomplete.
When used with XMLConfigBuilder.parse, eager instantiation of the defined handlers happens and each enum type need to be explicitly listed.

XMLConfigBuilder.parse is called by mybatis-spring project for example.

Implementation of the feature is still incomplete.
When used with XMLConfigBuilder.parse, eager instantiation of the defined handlers happens and each enum type need to be explicitly listed.

XMLConfigBuilder.parse is called by mybatis-spring project for example.

@kazuki43zoo

This comment has been minimized.

Show comment
Hide comment
@kazuki43zoo

kazuki43zoo Dec 28, 2017

Member

@michaelplavnik This PR is already merged. Please create a new issue as related this.

Member

kazuki43zoo commented Dec 28, 2017

@michaelplavnik This PR is already merged. Please create a new issue as related this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment