作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要序列化和反序列化Set<MyEnum>
使用mybatis。序列化时效果很好,但得到 Set<String>
反序列化时。这是我的代码:
mybatis-config.xml:
<typeHandlers>
<typeHandler handler="com.my.JsonTypeHandler" javaType="com.my.MyEnum"/>
<typeHandler handler="com.my.JsonTypeHandler" javaType="java.util.Set"/>
</typeHandlers>
我的枚举:
@Getter
@AllArgsConstructor
public enum MyEnum {
MILEAGE(1),
DRIVE_DURATION(2)
;
private int value;
@JsonCreator
public static MyEnum fromName(String name) {
return MyEnum.valueOf(name);
}
}
mapper.xml:
<select id="queryByParam" parameterType="com.my.DaoQueryParam" resultType="com.my.model.Product">
select * from product
<where>
product_id = #{assetProductId}
</where>
</select>
<insert id="insert" parameterType="com.my.model.Product">
insert into product
(some code here)
</insert>
产品:
@Data // lombok
public class Product {
private Set<MyEnum> myEnums;
}
JsonTypeHandler:
public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {
private static final ObjectMapper mapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
private Class<T> clazz;
public JsonTypeHandler(Class<T> clazz) {
if (clazz == null) throw new IllegalArgumentException("Type argument cannot be null");
this.clazz = clazz;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
ps.setString(i, this.toJson(parameter));
}
@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
return this.toObject(rs.getString(columnName), clazz);
}
@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return this.toObject(rs.getString(columnIndex), clazz);
}
@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return this.toObject(cs.getString(columnIndex), clazz);
}
private String toJson(T object) {
try {
return mapper.writeValueAsString(object);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private T toObject(String content, Class<?> clazz) {
if (content != null && !content.isEmpty()) {
try {
return (T) mapper.readValue(content, clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
return null;
}
}
}
mysql中myEnums列对应的类型是VARCHAR。序列化时,我得到满意的结果,例如。 ["MILEAGE"]
。反序列化时,它不会抛出任何错误,但 myEnums
领域 Product
结果是Set<String>
实际上。我尝试修改mybatis-config.xml:
<typeHandlers>
<typeHandler handler="com.my.JsonTypeHandler" javaType="java.util.Set<MyEnum>"/>
</typeHandlers>
但发生错误并表示 javaType 中不允许使用“<”字符。我是mybatis新手,这个问题困扰了我几个小时。有人可以帮忙吗?
最佳答案
我认为,你能做的最好的事情就是编写一个 JsonSetTypeHandler
。
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Set;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonSetTypeHandler extends BaseTypeHandler<Set<?>> {
private static final ObjectMapper mapper = new ObjectMapper()
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
private final JavaType javaType;
public JsonSetTypeHandler(Class<?> clazz) {
if (clazz == null)
throw new IllegalArgumentException("Type argument cannot be null");
this.javaType = mapper.getTypeFactory()
.constructCollectionType(Set.class, clazz);
}
@Override
public void setNonNullParameter(PreparedStatement ps,
int i, Set<?> parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, this.toJson(parameter));
}
@Override
public Set<?> getNullableResult(ResultSet rs,
String columnName) throws SQLException {
return this.toSet(rs.getString(columnName));
}
@Override
public Set<?> getNullableResult(ResultSet rs,
int columnIndex) throws SQLException {
return this.toSet(rs.getString(columnIndex));
}
@Override
public Set<?> getNullableResult(CallableStatement cs,
int columnIndex) throws SQLException {
return this.toSet(cs.getString(columnIndex));
}
private String toJson(Object object) {
try {
return mapper.writeValueAsString(object);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private Set<?> toSet(String content) {
if (content != null && !content.isEmpty()) {
try {
return mapper.readValue(content, javaType);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
return null;
}
}
}
并且您可能需要为每个参数/结果映射指定 typeHandler
,而不是全局注册类型处理程序 [1]。
<resultMap type="com.my.model.Product" id="productRM">
<id property="id" column="id" />
<result property="myEnums" column="my_enums"
typeHandler="com.my.JsonSetTypeHandler" javaType="com.my.MyEnum" />
</resultMap>
<select id="queryByParam" resultMap="productRM">
select * from product where ...
</select>
<insert id="insert">
insert into product (id, my_enums) values (#{id},
#{myEnums,typeHandler=com.my.JsonSetTypeHandler,javaType=com.my.MyEnum})
</insert>
关于java - 如何在mybatis中为Set<MyEnum>指定typeHandler?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56593722/
我是一名优秀的程序员,十分优秀!