继 上篇博客的遗留问题:
- MySQL数据库,存储类型是VARCHAR(255),很容易超出上限。而且在实际项目中使用的是PostgreSQL数据库,有JSON格式的数据类型。
为什么要处理JSON格式的数据类型?
- 在项目中持久层框架使用的Mybatis,Mybatis并未提供直接处理JSON的相关类,所以需要我们手动创建处理JSON的类,继承BaseTypeHandler。
具体实现:
import com.gotrade.esop.common.JacksonSerializer;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgresql.util.PGobject;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* @author jason.tang
* @create 2019-01-29 11:27
* @description 自定义JsonTypeHandler处理PostgreSQL的JSON数据类型
*/
@MappedTypes({Object.class})
public class JsonTypeHandler extends BaseTypeHandler<Object> {
//引入PGSQL提供的工具类PGobject
private static final PGobject jsonObject = new PGobject();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
jsonObject.setType("json");
jsonObject.setValue(parameter.toString());
ps.setObject(i, jsonObject);
}
@Override
public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
return JacksonSerializer.parseObject(rs.getString(columnName), Object.class);
}
@Override
public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return JacksonSerializer.parseObject(rs.getString(columnIndex), Object.class);
}
@Override
public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return JacksonSerializer.parseObject(cs.getString(columnIndex), Object.class);
}
}
注意事项:
- 一开始使用如果报错找不到PGobject类,请检查pom文件,将runtime注释掉:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<!-- <scope>runtime</scope> -->
</dependency>
- 在上篇文章中,我是先将需要监控的对象转成JSON字符串,所以这里的 setNonNullParameter方法直接setValue即可,如果是先直接传入对象,在自定义处理JSON数据类型的类中处理如下:
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
jsonObject.setType("json");
jsonObject.setValue(JacksonSerializer.toJSONString(parameter));
ps.setObject(i, jsonObject);
}
- 这里用到了JSON字符串与对象的相互转换工具类,请看这里
在Mybatis的xml中使用
<insert id="addAuditLog" parameterType="com.gotrade.autitlog.model.AuditLog">
<selectKey resultType="java.lang.Integer" order="BEFORE" keyProperty="logNum">
SELECT nextval('seq_audit_log'::regclass) AS logNum
</selectKey>
INSERT INTO audit_log (
log_num, log_table_name, log_type, log_data, src_num, create_dt
) VALUES (
#{logNum}, #{logTableName}, #{logType},
#{logData, typeHandler=com.gotrade.autitlog.common.JsonTypeHandler},
#{srcNum}, #{createDateTime}
)
</insert>
- 这里的log_data在PostgreSQL数据库的类型为JSON类型
- 在对于的值后面加上typeHandler=com.gotrade.autitlog.common.JsonTypeHandler即可,这就是刚刚自定义处理JSON数据类的全限定名。
网友评论