【问题标题】:Mybatis enum select by idMybatis enum select by id
【发布时间】:2017-08-20 11:13:43
【问题描述】:

我的 MyBatis 代码没有加载枚举类型(版本:3.4.4)。

在 MySQL 数据库中,我有一个带有“cartype”字段的表,它是一个 INT(11) 类型。 在 Java 中,我创建了一个用于处理汽车类型的 ENUM:

public enum CarType {
    SEDAN(1), LIMUSIN(2), WAGON(3);

    private int id;

    CarType(int id) {
        this.id = id;
    }

    public int getId() {
        return this.id;
    }
}

汽车映射器 xml 看起来像这样(不包含所有数据):

<select id="selectCar" parameterType="Car" resultMap="carResultMap">
SELECT * FROM Cars WHERE car_name="#{carName}";
</select>

<resultMap id="carResultMap" type="Car">
    <id property="id" column="car_name"/>
    <result property="carType" column="cartype"/>
</resultMap>

最后我的 bean 如下所示:

public class Car {
    private Integer id;
    private CarType carType;
}

bean 也包含 getter 和 setter。

当我尝试在 java 中获取 Car 时,它会抛出以下异常:

Caused by: java.lang.IllegalArgumentException: No enum constant org.data.bean.CarType.1
    at java.lang.Enum.valueOf(Enum.java:238)
    at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:49)
    at org.apache.ibatis.type.EnumTypeHandler.getNullableResult(EnumTypeHandler.java:26)
    at org.apache.ibatis.type.BaseTypeHandler.getResult(BaseTypeHandler.java:66)

【问题讨论】:

  • 您可以尝试在这里构建和链接一个最小的、完整的示例,其中包含 -for example- h2 数据库(在内存中)和 maven,以便它可以轻松运行。我也认为这是枚举的名称(例如,需要存储在数据库中的“SEDAN”,而不是 id)
  • 感谢它使用枚举名称而不是 id。在 select 语句中应该使用 UPPER() 方法作为名称,这对于解决方案来说有点加分。

标签: java enums mybatis


【解决方案1】:

试试这个

http://www.mybatis.org/mybatis-3/configuration.html#Handling_Enums

<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
    javaType="java.math.RoundingMode"/>
</typeHandlers>

根据你的情况

<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler"
    javaType="org.data.bean.CarType"/>
</typeHandlers>

【讨论】:

    【解决方案2】:

    需要存入数据库的是枚举名,而不是id。

    看看here。默认的 EnumTypeHandler 需要一个 varchar:

    VARCHAR 任何字符串兼容类型,因为代码被存储(不是索引)。

    如果您想要或必须存储 id,您将需要自定义 TypeHandler。像这样的:

    public class CarTypeTypeHandler implements TypeHandler<CarType> {
    
       public void setParameter(PreparedStatement ps, int paramInt, CarType paramType, JdbcType jdbctype)
             throws SQLException {
          ps.setInt(paramInt, paramType.getId());
       }
    
       @Override
       public CarType getResult(ResultSet rs, String param) throws SQLException {
          return CarType.get(rs.getInt(param));
       }
    
       @Override
       public CarType getResult(CallableStatement cs, int col) throws SQLException {
          return CarType.get(cs.getInt(col));
       }
    }
    

    在你的枚举中也有一个查找方法会很方便:

    public static CarType get(int code) { 
       for(CarType s : values()) {
          if(s.id == code) return s;
       }
       return null;
    }
    

    您可能还需要在映射器中明确指出枚举类型。像这样添加一个 javaType 参数(我还包括一个示例类型处理程序定义):

    <result property="carType" 
      column="cartype" javaType="path.to.package.CarType" 
      typeHandler="path.to.package.CarTypeTypeHandler"/>
    

    【讨论】:

    • 感谢它使用枚举名称而不是 id。在 select 语句中应该使用 UPPER() 方法作为名称,这对于解决方案来说有点加分。
    • 如何使用 Spring Boot MyBatis 的注解告诉 MyBatis 使用枚举类型处理程序?
    猜你喜欢
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2011-05-26
    • 2011-04-06
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多