1.问题
在使用MyBatis向PostgreSQL数据库动态更新数据,参数为表名和json(列:值),为了避免对列进行类型校验,在mybatis中统一将值作为字符串处理(数据库对sql中类型检查减弱,如向int类型的列插入值时写成'1',仍然能够插入成功,向Date类型的列插入'2020-01-01'字符串也是OK的)。
mapper接口如下:
/**
* 根据条件更新数据
* @param schema schema值
* @param tableName 表名
* @param dataMap 更新数据的值
* @param conditionMap 更新条件
* @return 操作结果
*/
int updateProperty(@Param("schema") String schema,
@Param("tableName") String tableName,
@Param("dataMap")Map<String,Object> dataMap,
@Param("conditionMap") Map<String,Object> conditionMap);
对应mapper.xml中的写法如下:
<update id="updateProperty">
update ${schema}.${tableName} set
<foreach collection="dataMap.keys" item="key" separator=",">
${key} = #{dataMap[${key}]}
</foreach>
<where>
<foreach collection="conditionMap.keys" item="key" separator="and">
${key} = #{conditionMap[${key}]}
</foreach>
</where>
</update>
使用postman对数据进行请求,请求体如下:
{
"condition": "{'objectid':1866}",
"details": "{'fzsj':'2019-09-26'}",
"layerName": "fz"
}
fzsj是Date类型
在执行时数据库报错,错误信息如下:
column “fzsj” is of type timestamp without time zone but expression is of type character varying
2.解决方案
在最初实现该功能时考虑过使用Java代码拼接成sql,这样能够根据查询到的数据表列的字段类型来动态拼接,也能有使用一些数据库函数,在遇到该问题的时候也想使用这种方式解决,但时间日期类型的字符串格式多种多样,在使用一些数据库函数将字符串转成日期时需要指定其格式,这样的话就需要对日期字符串做各种格式的校验和转换。
在配置文件对jdbc配置时只需要如下配置即可
jdbc:postgresql://localhost:5432/dbname?stringtype=unspecified
stringtype=unspecified即自动格式化数据。
此配置对于一些数据库的操作也会有一些影响,官方文档中有说明
https://www.postgresql.org/message-id/[email protected]