aloplop85
aloplop85

Reputation: 922

MyBatis retrieve Integer as Enum from MySql DB

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.

Upvotes: 6

Views: 13300

Answers (2)

faizan
faizan

Reputation: 690

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.

Upvotes: 4

Larry.Z
Larry.Z

Reputation: 3724

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;
    }

}

Upvotes: 4

Related Questions