首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java MyBatis枚举字符串值

Java MyBatis枚举字符串值
EN

Stack Overflow用户
提问于 2017-04-22 04:08:03
回答 3查看 10.8K关注 0票数 7

我觉得这是一个简单的问题,但我尝试的东西对我来说都不起作用。我有一个枚举,我有字符串构造函数的原因是因为Java不允许枚举是数值型的,我尝试了AA,AB,2C,没有字符串构造函数,但这给出了一个错误。注意,对于现有的枚举,我添加了C("2C")。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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()没有getter。我尝试了#{testEnum.display}和#{testEnum.name},它们仍然插入C,而我希望它插入2C。你们知道更简单的处理方法吗?

我不想将模型对象更改为传递String而不是TestEnum,因为这个对象在许多places.Is中都在使用,有没有一种方法可以在mybatis映射器中完成,而不需要更改模型对象?

感谢您的帮助:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-04-22 04:37:02

你需要的是一个TypeHandler

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

代码语言:javascript
复制
public static TestEnum fromDisplay(String display){
    for (TestEnum v : TestEnum.values()){
        if (v.getDisplay().equals(display)){
            return v;
        }
    }
    return null;
}

然后使用它创建您的TypeHandler:

代码语言:javascript
复制
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中注册TypeHandler:

代码语言:javascript
复制
<typeHandlers>
  <typeHandler handler="blah.blah.TestEnumTypeHandler "/>
</typeHandlers>
票数 4
EN

Stack Overflow用户

发布于 2017-10-30 06:24:03

如果要插入枚举的值,则不需要编写任何自定义TypeHandler

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

示例:

SQL:

代码语言:javascript
复制
CREATE TABLE demo
(
    id BIGINT,
    value VARCHAR(10),
    status CHAR(1)
);

MyBatis映射器:

代码语言:javascript
复制
@Update("UPDATE demo SET status = #{status.value} WHERE id= #{uuid}")
    long updateStatus(@Param("status") Status status, @Param("uuid") String uuid);

和Java Enum:

代码语言:javascript
复制
public enum Status {
    ACTIVE("A"),
    INACTIVE("I");

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

    public String getValue() {
        return value;
    }
}

在您的例子中,您可以在SQL中使用src = #{testEnum.display}

票数 4
EN

Stack Overflow用户

发布于 2017-04-22 18:17:54

除了@Malt Answer:

您尝试的方法不起作用的原因是MyBatis EnumTypeHandler默认设置方法的name()值,并标记为final,因此您不能覆盖它:

EnumTypeHandler.class (第38到44行):

代码语言:javascript
复制
  @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)创建枚举,该方法也使用枚举的名称。

代码语言:javascript
复制
@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,而不是BaseTypeHandler (Malt ),因为您可以重用一些功能(不是在您的情况下,但可能在其他情况下),以便它处理一般的枚举行为。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43551201

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档