目录
场景
比如:用户的状态:0为可用,1为被禁止,-1为被删除。
-
数据库存储的是整形。
这样的:
-
如果要代码的可读性,我们可以使用
Enum
或者单独一个类来实现。我本身采用的是Enum
的方式来实现的,不优雅,但是还可以吧。/** * @author 青韵 * @date 2020/10/12 - 20:28 */ public enum AccountEnableTypeEnum { /** * 正常使用 */ OK((byte) 1), /** * 被禁止了 */ FORBIDDEN((byte) 0), /** * 用户已注销 */ DELETE((byte) -1); private Byte value; AccountEnableTypeEnum(Byte value) { this.value = value; } public Byte getValue() { return value; } /** * 在做类型转换可以用上 **/ public static AccountEnableTypeEnum getInstance(Byte value) { for (AccountEnableTypeEnum accountEnableTypeEnum : AccountEnableTypeEnum.values()) { if (accountEnableTypeEnum.getValue().equals(value)) { return accountEnableTypeEnum; } } return null; } }
-
由于
Enum
默认采用的是名字的方式来实现的,所以我们存储的(-1, 0, 1)无法转换为相应的对象。public class EnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> { @Override public E getNullableResult(ResultSet rs, String columnName) throws SQLException { String s = rs.getString(columnName); return s == null ? null : Enum.valueOf(type, s); } }
这里我们有两个办法:
-
我们知道:**枚举类型会有顺序的,通过.ordinal()**来获取,例如:
AccountEnableTypeEnum.DELETE.ordinal()就是2
。 -
由于我们设置了1对应可以使用,0表示被禁止,-1表示账户已经删除。而且我们设置了value。
所以我们可以 自定义转换器,淦他。
-
要实现自定义的转换器,可以
先实现TypeHandler
接口或者继承BaseTypeHandler
等。
实现TypeHandler
接口,实现内部的方法:
public interface TypeHandler<T> {
/**
* 设置参数时用,表示将Java类型转换为对应的数据库类型
**/
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
/**
* 下面三个都是:从数据库获取数据时,转换为相应的对象时的方法
**/
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
继承BaseTypeHandler
官方帮我们写好了一些流程,按照思路帮我们实现了那几个接口,以及对于异常的处理,把需要实现的具体定义为了对应的方法,只需要处理转换的部分即可,何乐而不为呢?
public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
+ "Cause: " + e, e);
}
} else {
try {
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different configuration property. "
+ "Cause: " + e, e);
}
}
}
@Override
public T getResult(ResultSet rs, String columnName) throws SQLException {
try {
return getNullableResult(rs, columnName);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column '" + columnName + "' from result set. Cause: " + e, e);
}
}
@Override
public T getResult(ResultSet rs, int columnIndex) throws SQLException {
try {
return getNullableResult(rs, columnIndex);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column #" + columnIndex + " from result set. Cause: " + e, e);
}
}
@Override
public T getResult(CallableStatement cs, int columnIndex) throws SQLException {
try {
return getNullableResult(cs, columnIndex);
} catch (Exception e) {
throw new ResultMapException("Error attempting to get column #" + columnIndex + " from callable statement. Cause: " + e, e);
}
}
/**
* 实现下列这些就可以了
**/
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
}
我是这么做的
public class AccountTypeEnumHandler extends BaseTypeHandler<AccountEnableTypeEnum> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i, AccountEnableTypeEnum parameter, JdbcType jdbcType) throws SQLException {
ps.setByte(i, parameter.getValue());
}
@Override
public AccountEnableTypeEnum getNullableResult(ResultSet rs, String columnName) throws SQLException {
return AccountEnableTypeEnum.getInstance(rs.getByte(columnName));
}
@Override
public AccountEnableTypeEnum getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return AccountEnableTypeEnum.getInstance(rs.getByte(columnIndex));
}
@Override
public AccountEnableTypeEnum getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return AccountEnableTypeEnum.getInstance(cs.getByte(columnIndex));
}
}
接下来就是配置,总体来说有两种方式,我个人推荐第一种,因为有提示,不易出错。
两种方式都需要先在mybatis
的配置文件去配置类型转换器。
ps:类型转换器是你自己的,我这块写的是我的类型转换器,不代表是你的
方式一:在类上加注解
MappedJdbcTypes
:表示数据库对应的类型是什么,填你自己的MappedTypes
:表示要处理的类型转换是哪个,填你自己的
方式二:在xml配置文件中加上两个参数
恭喜,大功告成