参考文章:https://blog.csdn.net/java_collect/article/details/80946303
最近的项目有用到mybatis和PostgreSQL,牵扯到数据类型转换的问题,在参考了之前的ibatis做法和网上的大佬的文章之后,解决了问题。
1. typeHandler的实现
mybatis默认是没有实现jsonb类型字段对应的TypeHandler,所以一般我们需要自定义mybatis的TypeHandler的一个简单实现:
package com.demo.common.utils; 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 org.apache.ibatis.type.MappedTypes; import org.postgresql.util.PGobject; @MappedTypes({Object.class}) public class JsonbTypeHandler extends BaseTypeHandler{ @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { if (ps != null) { PGobject ext = new PGobject(); ext.setType("jsonb"); ext.setValue(parameter.toString()); ps.setObject(i, ext); } } @Override public Object getNullableResult(ResultSet resultSet, String s) throws SQLException { return resultSet.getObject(s); } @Override public Object getNullableResult(ResultSet resultSet, int i) throws SQLException { return resultSet.getObject(i); } @Override public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException { return callableStatement.getObject(i); } }
json类型的TypeHandler的简单实现:
package com.demo.common.utils; 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 org.apache.ibatis.type.MappedTypes; import org.postgresql.util.PGobject; @MappedTypes({Object.class}) public class JsonTypeHandler extends BaseTypeHandler{ @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { if (ps != null) { PGobject ext = new PGobject(); ext.setType("json"); ext.setValue(parameter.toString()); ps.setObject(i, ext); } } @Override public Object getNullableResult(ResultSet resultSet, String s) throws SQLException { return resultSet.getObject(s); } @Override public Object getNullableResult(ResultSet resultSet, int i) throws SQLException { return resultSet.getObject(i); } @Override public Object getNullableResult(CallableStatement callableStatement, int i) throws SQLException { return callableStatement.getObject(i); } }
2.insert和update时定义的dto:
package com.demo.entity.vo; import com.demo.common.dto.BaseDto; import lombok.Getter; import lombok.Setter; import java.math.BigDecimal; @Getter @Setter public class ProductSynchronizationVo extends BaseDto { private static final long serialVersionUID = -2987872121583341460L; private String productCode; private String interestRule; private String redeemRule; }
interestRule和redeemRule都是JSON字符串
mapper.xml文件中的配置
update table_test where product_code = #{productCode,jdbcType=VARCHAR} <if test="interestRule != null"> interest_rule = #{interestRule,jdbcType=OTHER,typeHandler=com.demo.common.utils.JsonbTypeHandler}, if> <if test="redeemRule != null"> redeem_rule = #{redeemRule,jdbcType=OTHER,typeHandler=com.demo.common.utils.JsonbTypeHandler}, if>
3.读取并解析数据时dto:
package com.demo.entity.dto; import com.demo.common.dto.BaseDto; import lombok.Getter; import lombok.Setter; import java.math.BigDecimal; import java.util.Date; import java.util.List; @Getter @Setter public class ProductDetailsDto extends BaseDto{ private static final long serialVersionUID = -295788347367434359L; private Object interestRule; private Object redeemRule; }
mapper.xml文件中的配置
java代码中解析转换,会自动转换为相应的List或者Map类型:
@Override public ProductDetailsDto getProductDetails(ProductDetailsVo productDetailsVo) { ProductDetailsDto dto = productMapper.getProductDetails(productDetailsVo); dto.setInterestRule(JSON.parse(dto.getInterestRule()+"")); dto.setRedeemRule(JSON.parse(dto.getRedeemRule()+"")); return dto; }