postgresql提供了很多数据类型,某些特殊的类型无法同java数据类型映射。
MyBatis 类型转换器
Mybatis提供了一些默认的TypeHandler,但不包含诸如数组、json这些类型在内。为了使用pgsql的这些类型,我们可以自己添加一些特定的typehandler,注册后就可以标注使用了。
数组typehandler教程很多,这里直接贴代码:
package com.xxxxx.xxxxx.config;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.TypeException;
import java.sql.*;
@MappedJdbcTypes(JdbcType.ARRAY)
public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
private static final String TYPE_NAME_VARCHAR = "varchar";
private static final String TYPE_NAME_INTEGER = "integer";
private static final String TYPE_NAME_BOOLEAN = "boolean";
private static final String TYPE_NAME_NUMERIC = "numeric";
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter, JdbcType jdbcType) throws SQLException {
String typeName = null;
if (parameter instanceof Integer[]) {
typeName = TYPE_NAME_INTEGER;
} else if (parameter instanceof String[]) {
typeName = TYPE_NAME_VARCHAR;
} else if (parameter instanceof Boolean[]) {
typeName = TYPE_NAME_BOOLEAN;
} else if (parameter instanceof Double[]) {
typeName = TYPE_NAME_NUMERIC;
if (typeName == null) {
throw new TypeException("ArrayType2Handler parameter typeName error, your type is " + parameter.getClass().getName());
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter);
ps.setArray(i, array);
@Override
public Object[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
return getArray(resultSet.getArray(s));
@Override
public Object[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
return getArray(resultSet.getArray(i));
@Override
public Object[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return getArray(callableStatement.getArray(i));
private Object[] getArray(Array array) {
if (array == null) {
return null;
try {
return (Object[]) array.getArray();
} catch (Exception e) {
return null;
代码中定义了“读写”的处理
具体使用:
entity中标注类型处理类
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("pd_product")
public class ProductAttribute extends OrgEntity {
private static final long serialVersionUID = 1L;
private Long productId;
private String name;
@TableField(typeHandler = com.xxxxx.xxxxx.config.ArrayTypeHandler.class)
private String[] attributes;
在mapper或xml文件中自定义的sql包含该数据时,需要指明该项所应用的类型转换
xml中的相关语法:
<resultMap id="xxxxxxx" type="Product">
<result property="id" column="id"/>
<result property="state" column="state"/>
<result property="name" column="name"/>
<collection property="characteristics" ofType="ProductAttribute">
<id property="id" column="pc_id"/>
<result property="name" column="pc_name"/>
<result property="attributes" column="pc_attrs" typeHandler="com.jundax.product.config.ArrayTypeHandler"/>
</collection>
</resultMap>
<select id="XXXXXX" resultType="com.XXXXX.XXXXX.config.ArrayTypeHandler">
SELECT attributes FROM pd.product WHERE id=#{id}
</select>
<update id="XXXXXXXXXXX">
UPDATE pd.product SET update_time=now(), attributes = #{attrs,typeHandler=com.xxxxx.xxxxx.config.ArrayTypeHandler}
WHERE id=#{id}
</update>
</mapper>
json的转换相对复杂一点,坑也很多,只给出本菜鸟实测通过的一种,如有问题,多多指正。本例数据库中json存储的是一个对象数组,对象用AttrModel.class存储
package com.xxxxx.xxxxx.config;
import com.alibaba.fastjson.JSON;
import com.xxxxx.xxxxx.model.AttrModel;
import lombok.SneakyThrows;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
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;
@MappedTypes(AttrModel[].class)
@MappedJdbcTypes(JdbcType.OTHER)
public class JSONTypeHandlerPg extends BaseTypeHandler<AttrModel[]> {
private static final PGobject jsonObject = new PGobject();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, AttrModel[] parameter, JdbcType jdbcType) throws SQLException {
jsonObject.setType("json");
jsonObject.setValue(JSON.toJSONString(parameter));
ps.setObject(i, jsonObject);
@SneakyThrows
@Override
public AttrModel[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
AttrModel[] object = JSON.parseObject(rs.getString(columnIndex), AttrModel[].class);
return object;
@SneakyThrows
@Override
public AttrModel[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
AttrModel[] object = JSON.parseObject(cs.getString(columnIndex), AttrModel[].class);
return object;
@SneakyThrows
@Override
public AttrModel[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
AttrModel[] object = JSON.parseObject(rs.getString(columnName), AttrModel[].class);
return object;
可依据需要解析json,例如普通对象,可如下解析
@MappedJdbcTypes(JdbcType.OTHER)
public class JSONTypeHandlerPgMap extends BaseTypeHandler<Map<String,Object>> {
private static final PGobject jsonObject = new PGobject();
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Map<String,Object> parameter, JdbcType jdbcType) throws SQLException {
jsonObject.setType("json");
jsonObject.setValue(JSON.toJSONString(parameter));
ps.setObject(i, jsonObject);
@SneakyThrows
@Override
public Map<String,Object> getNullableResult(ResultSet rs, String columnName) throws SQLException {
Map<String,Object> object = JSON.parseObject(rs.getString(columnName), new TypeReference<Map<String, Object>>() {});
return object;
使用方法同数组类型转换类似。
趟过的坑:
- PGobject出错,依赖如下,runtime scope会导致此问题
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>compile</scope>
</dependency>
有些类型是不需要注册即可使用的,有些类型在未注册时BaseTypeHandler.class的处理会跳过ResultSet中的该字段,具体可自行调试查看。
mybatis-plus:
type-handlers-package: com.xxxxx.xxxxx.config
使用mybatis注册
mybatis:
type-handlers-package: com.xxxxx.xxxxx.config
Jackson 是 Spring Boot 官方推荐的默认库,教程也很详细,完全能满足我的需求,但一直报错,菜鸟找不到原因,干脆换一个。。
Fastjson的使用也非常方便,教程很多。
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.25</version>
</dependency>
相关文章:
postgresql----JSON和JSONB类型
MyBatis中自定义typeHandler映射PostgreSQL中json类型字段
使用mybatis中的自定义TypeHandler处理PostgreSQL中的Json类型
Fastjson Obejct/Map/JSON/String 互转
Jackson教程
JSON解析-Jackson
postgresql----JSON和JSONB类型MyBatis中自定义typeHandler映射PostgreSQL中json类型字段使用mybatis中的自定义TypeHandler处理PostgreSQL中的Json类型JSON解析-Jackson
lines json[],
methodofpayment character varying(15),
modeofdelivery character varying(15),
CONSTRAINT tah_pkey.
postgreSql:
name: public
url: jdbc:postgresql://127.0.0.1:5432/test_db?&allowMultiQueries=true&autoReconnect=true&stringtype=unspecified
2、实体类配置
@TableName
加上 autoR.
目前单位对接的是生产类的系统,导致在业务上非常复杂。于是总有库存数量出错的时候,但是迟迟不找到原因,消耗了大量人力。于是想到添加额外的 log 记录,引出了一个未接触过的问题,如何在 postgreSQL 中添加 json 类型的数据,因为 java 的数据类型并不能映射。
找了很多文章,最后找到了解决办法。
参考文章:PgSQL数组及json类型在Mybatis项目中的类型转换_ymzhao-CSDN博客_mybatis pgsql 数组
我需要存储的 json 结果,如图是比较特殊
insert into student(student_names) values ('{阿离,小奏}')
-- 方式二 使用 array
insert into student(student_names) VALUES (array['韩信','关羽','张飞'])
关于PostgreSQL中Json数据类型的操作,可以参考官网。
应用场景介绍
将TCP发过来的数据包(通过消息队列发过来)解析出数据(一个数据包含有多帧,一帧中含有多条信息),并和本地规则表的格式对应起来。以JsonLineMsg实体类代表对应的一帧数据:
package tsdb.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.N
出现的问题
Mybatis只能是将java中的字段与数据库的字段做映射,字段的类型需要匹配才能完成数据映射。
但是Mybatis中没有json或者jsonb的的type的。所以要操作PostgreSQL中json或者jsonb数据,需要自己写一个支持JsonbTypeHandler。
Connection connection = null;
// 预编译对象 PreparedStatement
PreparedStatement preparedStatement = null;
// 结果集
ResultSet resultSet = null;
try {
// 加载驱动
Class.forName(“org.postgresql.Driver”);
// 获取连接对象
如果你要向PostgreSQL中的JSON数组添加元素,可以使用`jsonb_insert()`和`jsonb_build_array()`函数来实现。以下是一个示例:
UPDATE mytable SET mycolumn = jsonb_insert(mycolumn, '{myarray}', mycolumn->'myarray' || jsonb_build_array('new_element')) WHERE id = 1;
这个例子假设你有一个名为`mycolumn`的JSONB列,其中包含一个名为`myarray`的JSON数组。你想要向这个数组添加一个名为`new_element`的新元素,那么可以使用上述语句。其中,`jsonb_build_array('new_element')`用于将字符串`'new_element'`构建为一个JSON数组,`||`运算符用于连接原有的`myarray`数组与新元素构成的数组。最后,`jsonb_insert()`函数用于将新数组插入到原有的JSONB对象中。
需要注意的是,如果`myarray`数组不存在,那么上述语句会抛出一个错误。如果你想要在数组不存在的情况下创建一个新数组,可以使用如下语句:
UPDATE mytable SET mycolumn = jsonb_insert(mycolumn, '{myarray}', jsonb_build_array('new_element')) WHERE id = 1;
这个语句中,`jsonb_insert()`函数的第三个参数为一个新的JSON数组,如果`myarray`数组不存在,则会将这个新数组插入到原有JSONB对象中。