2017-04-21 74 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}