一、前言
最近在开发需求时,需要将json类型的表字段插入数据库,而针对postgresql数据库,如果直接插入json字符串会报错,那么针对这种情况,在不使用xml语句使用函数CAST强转情况下,想要实现插入json类型的数据,那么就可以在java 字段上加入自定义json处理器,就可以实现了。

二、如何实现?

1.在定义的entity对象中,针对json类型字段添加注解实现自定义json处理器,例如:

@Data
public class SyncLog implements Serializable {
    @TableId(type= IdType.INPUT)
    private Long id;

  
    @TableField(value = "content",typeHandler = JsonTypeHandler.class)
    private Object content;

    /**
     * 创建时间
     */
    private Date createTime;

    private static final long serialVersionUID = 1L;
}

其中content在数据库中是json类型。

2.JsonTypeHandler类实现如下:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.postgresql.util.PGobject;

import java.sql.*;

public class JsonTypeHandler extends BaseTypeHandler<Object> {

    private static final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
        String jsonString;
        try {
            if(parameter instanceof String){
                jsonString = (String) parameter;
            }else {
                jsonString = objectMapper.writeValueAsString(parameter);
            }
        } catch (JsonProcessingException e) {
            throw new SQLException("JsonTypeHandler JSON serialization error", e);
        }
        // 获取数据库类型
        Connection connection = ps.getConnection();
        DatabaseMetaData metaData = connection.getMetaData();
        String databaseProductName = metaData.getDatabaseProductName().toLowerCase();

        if (databaseProductName.contains("postgresql")) {
            PGobject pgObject = new PGobject();
            pgObject.setType("json"); // 或者 "jsonb" 根据需求
            pgObject.setValue(jsonString);
            ps.setObject(i, pgObject);
        } else {
            //其他数据库处理逻辑
            ps.setString(i, jsonString);
        }
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseJson(rs.getString(columnName));
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseJson(rs.getString(columnIndex));
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseJson(cs.getString(columnIndex));
    }

    private Object parseJson(String json) throws SQLException {
        if (json == null) {
            return null;
        }
        try {
            return objectMapper.readTree(json);
        } catch (Exception e) {
            throw new SQLException("JsonTypeHandler JSON deserialization error", e);
        }
    }
}

3.接下来定义一个DAO。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface SyncLogDao extends BaseMapper<SyncLog> {
}

4.然后插入一条数据,如果可以插入这条json数据,表明自定义的JsonTypeHandler已生效。

@RunWith(SpringRunner.class)
@SpringBootTest(classes= AIAssetExternalApplication.class)
public class IntegrationTest {
     @Autowired
     SyncLogDao syncLogDao;

     @Test
     public void sync() throws Exception {
          SyncLog syncLog = new SyncLog();
          syncLog.setId(1L);
          String jsonStr="{\"size\": 3474046}";
          syncLog.setContent(jsonStr);
          syncLogDao.insert(syncLog);
     }
}

结果插入成功,自定义的JsonTypeHandler生效。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐