2017-04-21 238 views
3

我觉得这是一个简单的问题,但我试过的东西都不适合我。我有一个枚举,我有字符串构造函数的原因是因为Java不允许枚举数字..我直接尝试AA,AB,2C没有字符串构造函数,但是,这给出了一个错误。请注意,对于现有的枚举,我将添加C(“2C”)。Java MyBatis枚举字符串值

public enum TestEnum{ 
     AA("AA"), AB("AB"), C("2C"); 
     private String display; 
    private TestEnum(String display) { 
      this.display = display; 
     } 
    public String toString() { 
      return display; 
     } 
    public String getDisplay() { 
      return display; 
     } 
    public void setDisplay(String display) { 
      this.display = display; 
     } 
    public String getName() { 
      return display; 
     } 

现在我有一个MyBatis的映射器,它确实这是现有的和参数去映射器之一是TestEnum合并。直到现在这工作得很好,因为枚举值和字符串值是相同的,但我加了C(“2C”)。现在,我想用mybaits插入2C表,但它总是插入C.

merge into text t 
     using (select #{id} as id from dual) d on (d.id = t.id) 
     when matched then 
     update set 
     appId = #{applId}, 
     src = #{testEnum} 

testEnum插入C,所以我改变了对#{testEnum.toString()},它给了我一个不存在的getter为属性名称toString()错误。我试过#{testEnum.display}和#{testEnum.name},它们仍然插入C,而我希望它插入2C。你们知道一个更简单的方法来处理这个问题吗?

我不想改变模型对象来传递字符串而不是TestEnum,因为这个对象正在很多地方使用。是否有一种方法可以在mybatis映射器中完成而无需更改模型对象?

感谢您的帮助:)

回答

3

你需要的是一个TypeHandler

首先,添加一个静态方法您TestEnum返回一个TestEnum给定的显示字符串:

public static TestEnum fromDisplay(String display){ 
    for (TestEnum v : TestEnum.values()){ 
     if (v.getDisplay().equals(display)){ 
      return v; 
     } 
    } 
    return null; 
} 

然后用它来创建你的TypeHandler:

import java.sql.CallableStatement; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

import org.apache.ibatis.type.BaseTypeHandler; 
import org.apache.ibatis.type.JdbcType; 

public class TestEnumTypeHandler extends BaseTypeHandler<TestEnum> { 

    @Override 
    public void setNonNullParameter(PreparedStatement ps, int i, TestEnum parameter, JdbcType jdbcType) 
      throws SQLException { 
     ps.setString(i, parameter.getDisplay()); 
    } 

    @Override 
    public TestEnum getNullableResult(ResultSet rs, String columnName) throws SQLException { 
     return TestEnum.fromDisplay(rs.getString(columnName)); 
    } 

    @Override 
    public TestEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 
     return TestEnum.fromDisplay(rs.getString(columnIndex)); 
    } 

    @Override 
    public TestEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 
     return TestEnum.fromDisplay(cs.getString(columnIndex)); 
    } 
} 

最后,注册类型处理器在MyBatis的XML:

<typeHandlers> 
    <typeHandler handler="blah.blah.TestEnumTypeHandler "/> 
</typeHandlers> 
+0

太棒了,正是我需要的。非常感谢你 –

2

除了@Malt答:

为什么你正在尝试不适用它的默认值设置name()值是MyBatis的EnumTypeHandler原因和标有final的方法的,所以你不能重写它:

EnumTypeHandler.class(线38至44):

@Override 
    public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException { 
    if (jdbcType == null) { 
     ps.setString(i, parameter.name()); 
    } else { 
     ps.setObject(i, parameter.name(), jdbcType.TYPE_CODE); // see r3589 
    } 
    } 

否则,枚举是从方法valueOf(type, name)创建的,该方法也使用枚举的名称。

@Override 
    public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException { 
    String s = rs.getString(columnIndex); 
    return s == null ? null : Enum.valueOf(type, s); 
    } 

    @Override 
    public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { 
    String s = cs.getString(columnIndex); 
    return s == null ? null : Enum.valueOf(type, s); 
    } 

所以肯定,你需要使用特定的一个类型控制器来处理你的枚举它具有特定的行为,但我会extends在特定枚举类型处理器直接EnumTypeHandler,而不是BaseTypeHandler(麦芽答案),因为你可以重用一些功能(不是在你的情况,但可能在其他),所以它处理一般的枚举行为。

+0

有道理..谢谢你的解释 –

0

如果您想要插入Enum的值,则不需要编写任何自定义的TypeHandler

您需要做的唯一一件事就是在您的MyBatis插入中指定getter方法的名称。

例子:

SQL:

CREATE TABLE demo 
(
    id BIGINT, 
    value VARCHAR(10), 
    status CHAR(1) 
); 

MyBatis的映射器:

@Update("UPDATE demo SET status = #{status.value} WHERE id= #{uuid}") 
    long updateStatus(@Param("status") Status status, @Param("uuid") String uuid); 

和Java枚举:

public enum Status { 
    ACTIVE("A"), 
    INACTIVE("I"); 

    Status(final String value) { 
     this.value = value; 
    } 

    public String getValue() { 
     return value; 
    } 
} 

就你而言,你可以在SQL中使用src = #{testEnum.display}