6

I hava a POJO which contains an enum property.

[Speed.java]

public class SpeedEntry implements Serializable {

    [...]

    private int idSpeed;
    private SpeedStatus status; // enum Property

    [...]

[SpeedStatus.java]

public enum SpeedStatus {

[...]

VALID(1), INVALID(2), UNKNOWN(0);   // Possible values.

private int value;

// Default constructor
private SpeedStatus(final int pValue) {
    this.value = pValue;
}
[...]

And I would like to store and retrieve the Speed object and get its properties filled as usual with MyBatis. The column assigned to SpeedStatus was created as an INT(11).

In this case, doing the INSERT was quite direct accessing its internal value property with:

#{status.value}

However, retrieving the object and getting its enum value filled from the integer stored in the database has not been as easier as inserting it. I tried, without luck, using a resultMap:

[speedMapper.xml]

<resultMap id="speedMap" type="Speed">
        <result property="idSpeed" column="idSpeed" />
        <result column="status" property="status.value" 
            typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
</resultMap>

So...it is possible to achieve what I am looking for? Is there any simple clarifying example around there?

What is the best alternative? Should I change the type stored in the database to "enum" ?

Thanks in advance.

2 Answers 2

4

In your insert statement you direct access its internal value by

#{status.value}

By this way, you insert VALID by value 1, INVALID by value 2, NUKNOWN by the value 0. But in your retrival statements, you using the resultMap defined by

typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"

That means you map the table int(11) field to Enum POJO property using the

SpeedStatus.ordinal()

Enum value will be mapped by the order defined in SpeedStatus. So in select statements table field value 0 mapped to VALID, 1 mapped to INVALID, 2 mapped to UNKNOWN.

If you still want to use EnumOrdinalTypeHandler you should defined the Enum value equal to its ordinal() value.

public enum SpeedStatus {

    UNKNOWN(0), VALID(1), INVALID(2); 

    private int value;

    private SpeedStatus(final int pValue) {
        this.value = pValue;
    }

}

Sign up to request clarification or add additional context in comments.

4 Comments

Sorry, I forgot to mention that the option typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" gives me an error while loading the JAR --> java.lang.RuntimeException: Failed invoking constructor for handler class org.apache.ibatis.type.EnumOrdinalTypeHandler. I am currently using MyBatis-Spring and I am not loading any _ mybatis-config.xml _ file.
I have written a Unit Test just now using org.apache.ibatis.type.EnumOrdinalTypeHandler. I have got the result I want to. I need more info to check the problem
I've got the problem <result column="type" property="status" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>. property="status", not "status.value". Please read my answer again. Retriving mapping needs to change the SpeedStatus definition。
It seems there was some name mismatching...the key was to assign a diferent value for column and property attributes of the result label inside the resultMap: <result column="statusValue" property="status" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/> With your advice it works correctly ;) Thanks again.
4

If you want to convert your int to Enum you can define your own EnumHandler.

public class SpeedStatusTypeHandler implements TypeHandler<SpeedStatus> {

public SpeedStatus getResult(ResultSet rs, String param) throws SQLException {
return SpeedStatus.getEnum(rs.getInt(param));
}

public SpeedStatus getResult(CallableStatement cs, int col) throws SQLException {
return SpeedStatus.getEnum(cs.getInt(col));
}

public void setParameter(PreparedStatement ps, int paramInt, SpeedStatus paramType, JdbcType jdbctype)
    throws SQLException {
ps.setInt(paramInt, paramType.getId());
}
}

Now just add this typeHandler to your my batis config file,

 <typeHandlers> 
        <typeHandler javaType='SpeedStatus' handler='SpeedStatusTypeHandler' /> 
</typeHandlers>

You wont even have to mention your typeHandler in your resultMap,mybatis will take care of it whenever it comes across a SpeedStatus Enum in your Pojo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.