mybatis字段映射枚举类型

在底层使用mybatis的时候,我们可能会需要把表里的字段映射到Java里面的枚举类,现总结下工作中的用法:

sku表里一个status_type字段为int类型。(这里是postgresql的脚本)

status_type int4 NULL

Java里面对应生成的枚举类为:

 

public enum SkuStatusType implements DbEnum, LocalString {

    PRODUCT(0, false, "masterdata.skuStatus.product"), 
    BUYING(1, false, "masterdata.skuStatus.buying"), 
    SALE(2, false, "masterdata.skuStatus.sale");


    private int dbConstant;
    private String messageKey;

    private OrderState(int dbConstant, boolean hasBeenDispatched, String messageKey) {
        this.dbConstant = dbConstant;
        this.hasBeenDispatched = hasBeenDispatched;
        this.messageKey = messageKey;
    }

    @Override
    public Integer getConstant() {
        return this.dbConstant;
    }

    @Override
    public String messageKey() {
        return this.messageKey;
    }
}

在配置xml文件之前我们需要为自己的项目建一个工具类:

package com.lcc.util;

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;

import com.lcc.api.domain.DbEnum;

public class DbEnumTypeHandler extends BaseTypeHandler<DbEnum> {
    
    private Class<DbEnum> type; 
    
    public DbEnumTypeHandler(Class<DbEnum> type){
        this.type = type;
    }
    
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i,
            DbEnum parameter, JdbcType jdbcType) throws SQLException {
        ps.setInt(i, parameter.getConstant());
    }

    @Override
    public DbEnum getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        int constant = rs.getInt(columnName);
        if(rs.wasNull()){    
            return null;
        }
        else{
            return convert(constant);
        }
    }

    @Override
    public DbEnum getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        int constant = rs.getInt(columnIndex);
        if(rs.wasNull()){    
            return null;
        }
        else{
            return convert(constant);
        }
    }

    @Override
    public DbEnum getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        int constant = cs.getInt(columnIndex);
        if(cs.wasNull()){    
            return null;
        }
        else{
            return convert(constant);
        }
    }
    
    private DbEnum convert(int constant) {
        DbEnum[] dbEnums = type.getEnumConstants();
        for (DbEnum dbEnum : dbEnums) {
            if(dbEnum.getConstant().equals(constant)){
                return dbEnum;
            }
        }
        return null;
    }
    
    
}

util class里面的DbEnum domain 和 Localisable domain:(一般项目里的枚举实现这两个domain interface

package com.lcc.api.domain;

import java.io.Serializable;

public interface DbEnum extends Serializable {

    public Integer getConstant();
}
package com.lcc.api.domain;

public interface Localisable {

    String messageKey();
}

 

看下mybatis的xml文件配置:

<result column="status_type" property="statusType"
                typeHandler="com.lcc.util.StringEnumTypeHandler" />

 

此时表字段映射枚举类就大功告成了,看完之后你可以自己上手试一下。

这只是其中的一种方法,还有其他的方法可以在度娘和谷哥上面搜索一下。 

转载于:https://www.cnblogs.com/cc-java/p/6593589.html

<think>嗯,我现在要介绍MyBatis如何映射枚举类型。首先,我需要回忆一下MyBatis的基本处理机制。MyBatis在处理Java枚举类型时,默认会使用EnumTypeHandler,这个处理器会把枚举实例转换其名称的字符串形式,也就是调用name()方法得到的值。比如,一个枚举Status有ACTIVE和INACTIVE两个值,存入数据库时会变"ACTIVE"和"INACTIVE"。但用户可能需要不同的存储方式,比如使用ordinal()的值,或者自定义的某个字段。这时候可能需要换用EnumOrdinalTypeHandler,或者自定义TypeHandler。 接下来,我应该分步骤说明不同的处理方式。首先是默认的EnumTypeHandler,举例子说明存入的是枚举的名称。然后,如果用户想存序号,可以用EnumOrdinalTypeHandler,这时候存入的是0、1这样的数字。但用户可能有更复杂的需求,比如数据库中存的是其他值,比如代码或者描述,这时候就需要自定义TypeHandler了。需要详细说明如何创建自定义的TypeHandler,实现TypeHandler接口或者继承BaseTypeHandler,重写四个方法:setParameter、getResult等。然后,在映射文件中配置这个处理器,或者在MyBatis的配置文件中注册。 另外,可能还要提到在MyBatis配置文件中如何全局配置TypeHandler,或者在resultMap或具体的字段上通过typeHandler属性指定。还需要注意,当使用注解方式时,如何在@Result注解中指定typeHandler。同时,可能会遇到枚举类型数据库字段类型不匹配的问题,需要确保数据库字段的类型与TypeHandler处理的类型一致,比如VARCHAR对应字符串,INT对应序号等。 还需要考虑枚举类型的转换在查询时的处理,MyBatis如何从结果集中读取数据并转换对应的枚举实例。例如,当数据库存的是代码'A',自定义TypeHandler需要根据这个代码找到对应的枚举实例。举一个具体的例子,比如用户状态枚举UserStatus,包含ACTIVE('A')和INACTIVE('I'),数据库中的字段是CHAR(1),这时候自定义TypeHandler需要将'A'映射到ACTIVE,反之亦然。 另外,可能需要注意在MyBatis 3.4.5及以上版本中,对枚举处理的支持是否有变化,或者是否有更简便的方式。例如,是否可以使用@EnumValue注解(如果有的话),或者结合其他框架如MyBatis-Plus的增强功能。 总结步骤应该是:1. 默认处理方式;2. 使用内置的序号处理器;3. 自定义处理器的实现和配置;4. 示例演示;5. 常见问题和注意事项。需要确保结构清晰,逐步引导用户理解如何根据需求选择合适的映射方式,并提供代码示例帮助理解。</think>MyBatis 映射枚举类型的实现方式可分为以下步骤,通过不同处理器满足多样化需求: --- ### 一、默认处理方式:`EnumTypeHandler` MyBatis **默认使用`EnumTypeHandler`处理枚举**,将枚举值转换为`name()`的字符串形式。 **示例**: ```java public enum Status { ACTIVE, INACTIVE } // 数据库字段类型:VARCHAR // Java属性:Status status; // INSERT时,"ACTIVE"或"INACTIVE"被存入数据库 ``` --- ### 二、使用序号处理器:`EnumOrdinalTypeHandler` 若需存储枚举的**序号**(即`ordinal()`值),改用`EnumOrdinalTypeHandler`。 **配置方式**: ```xml <typeHandlers> <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.example.Status"/> </typeHandlers> <!-- 或在字段映射中指定 --> <result column="status" property="status" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/> ``` **示例**: ```java // 数据库字段类型:INT // Status.ACTIVE.ordinal() = 0,Status.INACTIVE.ordinal() = 1 ``` --- ### 三、自定义处理器:实现`TypeHandler`接口 当需要**复杂映射**(如存储枚举的某个字段)时,需自定义`TypeHandler`。 #### 步骤 1:定义枚举类 ```java public enum UserStatus { ACTIVE("A"), INACTIVE("I"); private final String code; UserStatus(String code) { this.code = code; } public String getCode() { return code; } // 根据code获取枚举实例 public static UserStatus fromCode(String code) { return Arrays.stream(values()) .filter(e -> e.code.equals(code)) .findFirst() .orElse(null); } } ``` #### 步骤 2:实现自定义TypeHandler ```java public class UserStatusTypeHandler implements TypeHandler<UserStatus> { @Override public void setParameter(PreparedStatement ps, int i, UserStatus parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.getCode()); // 存储code到数据库 } @Override public UserStatus getResult(ResultSet rs, String columnName) throws SQLException { return UserStatus.fromCode(rs.getString(columnName)); // 从结果集解析 } @Override public UserStatus getResult(ResultSet rs, int columnIndex) throws SQLException { return UserStatus.fromCode(rs.getString(columnIndex)); } @Override public UserStatus getResult(CallableStatement cs, int columnIndex) throws SQLException { return UserStatus.fromCode(cs.getString(columnIndex)); } } ``` #### 步骤 3:注册TypeHandler **方式 1:全局注册(mybatis-config.xml)** ```xml <typeHandlers> <typeHandler handler="com.example.handler.UserStatusTypeHandler" javaType="com.example.enums.UserStatus"/> </typeHandlers> ``` **方式 2:局部指定(Mapper XML)** ```xml <resultMap id="userResultMap" type="User"> <result column="status" property="status" typeHandler="com.example.handler.UserStatusTypeHandler"/> </resultMap> ``` --- ### 四、注解方式配置 在`@Result`注解中直接指定: ```java @Results({ @Result(column = "status", property = "status", typeHandler = UserStatusTypeHandler.class) }) User selectUserById(Integer id); ``` --- ### 五、注意事项 1. **类型一致性**:确保数据库字段类型与处理器逻辑匹配(如`VARCHAR`对应字符串,`INT`对应序号)。 2. **性能影响**:频繁的自定义转换可能影响性能,建议在复杂场景下使用。 3. **空值处理**:在`TypeHandler`中需处理`null`值,避免`NullPointerException`。 4. **枚举更新同步**:若枚举定义变更(如修改code),需同步更新数据库历史数据。 --- ### 六、完整示例 **数据库表**: ```sql CREATE TABLE user ( id INT PRIMARY KEY, name VARCHAR(50), status CHAR(1) -- 存储'A'或'I' ); ``` **Java实体类**: ```java public class User { private Integer id; private String name; private UserStatus status; // Getters & Setters } ``` **Mapper XML**: ```xml <insert id="insertUser" parameterType="User"> INSERT INTO user (id, name, status) VALUES (#{id}, #{name}, #{status, typeHandler=com.example.handler.UserStatusTypeHandler}) </insert> <select id="selectUser" resultMap="userResultMap"> SELECT * FROM user WHERE id = #{id} </select> ``` 通过上述方式,MyBatis 可灵活处理枚举类型,适应不同存储需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值