Java MyBatis перечисление строковое значение
Я чувствую, что это простая проблема, но ни одна из вещей, которые я пробовал, не работает для меня. У меня есть перечисление, причина, по которой у меня есть строковый конструктор, заключается в том, что Java не позволяет перечислению быть числовым..Я попробовал AA, AB, 2C напрямую без строкового конструктора, но это дает ошибку. Обратите внимание, что для существующего перечисления я добавляю C("2C").
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 mapper, который делает слияние, это существует, и один из параметров к mapper - TestEnum. До сих пор это работало нормально, так как перечисление значение и строковое значение одинаковы, но я добавил C("2C"). Теперь я хочу вставить 2C в таблицу, используя mybaits, но он всегда вставляет 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 ()}, который дал мне нет геттера для имени свойства toString () ошибка. Я попробовал #{testEnum.дисплей} и #{testEnum.name} оба они все еще вставляют C, тогда как я хочу, чтобы он вставил 2C. вы, ребята, знаете более простой способ обработки этого?
Я не хочу менять объект модели на передайте строку, а не TestEnum, потому что этот объект используется во многих places.Is есть способ, которым это можно сделать в MyBatis mapper без изменения объекта модели?
Спасибо за помощь :)
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)); } }
Наконец, зарегистрируйте свой TypeHandler в xml-файле mybatis:
<typeHandlers> <typeHandler handler="blah.blah.TestEnumTypeHandler "/> </typeHandlers>
В дополнение к @Malt ответ:
Причина, по которой то, что вы пытаетесь, не работает, это MyBatis
EnumTypeHandler
по умолчанию устанавливаетname()
значение метода и помечаетсяfinal
, поэтому вы не можете переопределить его:EnumTypeHandler.класс (строки 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); }
Таким образом, определенно, вам нужно использовать специальный typeHandler для обработки вашего перечисления, которое имеет специфическое поведение, но я бы
extends
непосредственноEnumTypeHandler
в конкретных обработчиках типа enum, а неBaseTypeHandler
(ответ Malt), потому что вы можете повторно использовать некоторые функции (не в вашем случае, но, возможно, в других), поэтому он обрабатывает общее поведение enum.
Вам не нужно писать никаких пользовательских
Единственное, что вам нужно сделать, это указать имя метода getter в вашей вставке MyBatis.TypeHandler
, Если вы хотите вставить значение вашего перечисления.Пример:
SQL:
CREATE TABLE demo ( id BIGINT, value VARCHAR(10), status CHAR(1) );
MyBatis mapper:
@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; } }
В вашем случае вы можете использовать
src = #{testEnum.display}
в своем SQL.