利用Mybatis向PostgreSQL中插入并查询JSON字段

目录
  • 应用场景介绍
  • 数据insert
  • 数据select
  • BATCH 批量插入

前言:

这里我使用的是TimescaleDB,加了一个时间戳字段,不过没差。关于PostgreSQL中Json数据类型的操作,可以参考官网

应用场景介绍

将TCP发过来的数据包(通过消息队列发过来)解析出数据(一个数据包含有多帧,一帧中含有多条信息),并和本地规则表的格式对应起来。以JsonLineMsg实体类代表对应的一帧数据:

package tsdb.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.sql.Timestamp;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class JsonLineMsg {
    private Timestamp timeStamp; // 时间戳

    private String keyAndRuleData; // key value,key为根据规则表生成的唯一标识,value为TCP解析出的对应的数据。这个字段对应数据库中的Json类型字段,String类型进入数据库还需转换为Json格式。
}

对应psql的表结构为:

上面JsonLineMsg实体类的一个对象就代表的一帧中的所有数据项many(key:value)keyAndRuleData字段用来存储所有数据项,在psql中对应一个类型为json(或jsonb)的字段。

数据insert

为了查询JSON中的字段,在insert的过程中有些注意事项,如果插入时JSON格式不正确,查询JSON字段是总返回null

记录一下:为了降低数据库打开关闭的耗时,每积累20帧持久化一次。

note:

  • foreach批量插入 、 mybatis ExecutorType.BATCH模式插入 、 for循环insert
  • 其实实际意义上来说,包括在程序里面for循环还是在sql里面for循环都不算是批量操作。只有将ExecutorType设置为BATCH模式才是真正意义上的批量操作。 并且事实证明在sql循环时设置batch与否其实执行时间差别不是很大,几乎可以忽略不计。所以其实如果不是特别要求性能。可以直接在sql中使用for循环即可 。谨慎使用batch,如果需要使用batch,请在需要的函数上面设置batch,不要全局使用。因为batch也是有副作用的。 比如在Insert操作时,在事务没有提交之前,是没有办法获取到自增的id,;此外,对于update、delete无法返回更新、插入条数。这在某型情形下是不符合业务要求的。上面的是搬运的,不过后来有看了看,还是应该用BATCH的Executor来批量导入,实际项目中foreach不可控,指不定啥时候就报错了,文章最后记录了ExecutorType为BATCH写法的关键部分) foreach的xml拼接sql是最不推荐的方式,使用时有大段的xml和sql语句要写,很容易出错,工作效率很低。更关键点是,虽然效率尚可,但是真正需要效率的时候你挂了,要你何用? 批处理执行是有大数据量插入时推荐的做法,使用起来也比较方便。
  • 关于批处理的方式的具体说明,可以参考推文强烈推荐MyBatis 三种批量插入方式的比较或者去StackOverFlow查一下,讲解的比较全面,总之,还是用ExecutorType为BATCH写法比较靠谱。

一帧中包含多条信息,一条信息对应一个key:value,所以每次从规则表生成的key和TCP解析出的value都要加到一个代表一帧所有数据的JSON串中。

要注意的代码如下:

                 // 存储一帧的所有key:value
                StringBuilder json = new StringBuilder();
                json.append("{");
                // frmLen 帧中信息个数
                for (int j = 0; j < frmLen; j++) {
                    StatRule stat = frm.getStat(j);
                    assert stat != null;
                    // 一条stat的key和value
                    int key = stat.getKey();
                    long value = System.nanoTime();
//                    String value = ParseStat.Parse(datas, stat);
                    json.append("\"");  // key左右必须加引号,key必为String类型
                    json.append(key);
                    json.append("\"");
                    json.append(":");
//                    json.append("\"");
                    json.append(value); // value左右不是必须加引号,若是String则加
//                    json.append("\"");
                    if ((j != statLen - 1)) {
                        json.append(",");
                    }
                }
                json.append("}");
                JsonLineMsg jsonLineMsg = new JsonLineMsg(new Timestamp(System.currentTimeMillis()), json.toString());

要注意的就是这个keyvalue加入数据库的类型如果为text(即java字符串)就要加引号,所以key两头必须加,value看情况。

对应的XML中的语句:

    <insert id="batchInsertJsonLineMsg"
            useGeneratedKeys="true" >
        insert into jsonlinemsg (timestamp ,keyandruledata ) values
        <foreach item="item" collection="list" separator="," close=";">
            (#{item.timeStamp},(#{item.keyAndRuleData})::json)
        </foreach>
    </insert>

这个::json就是将非json类型转为json类型,否则JAVA中String类型会对应其他的数据库字段类型,插入会报错。

note: psql 4种类型转换https://www.postgresql.org/docs/14/sql-syntax-lexical.html

  • type 'string' 只能用于字面常量转换、且不能用于数组中
  • typename ( 'string' ) 可用于运行时类型转换
  • 'string'::type 可用于数组,可用于运行时类型转换
  • CAST ( 'string' AS type ) 可用于数组,可用于运行时类型转换

插入后用Navicat查看:

如果查看到类似于 "{"1":"1_234"}"{\"1\":\"1_123\"}这样,格式就是不正确的,查询JSON中字段会返回null。

数据select

  <select id="selectValueData" resultType="String">
        select keyandruledata::json ->>#{key}  from jsonlinemsg where timestamp = (#{time}::timestamp)
    </select>

要注意的就是这个::json,至于 -> 还是 ->>可以参考开头的官网链接。

ps: timescaledb官网推荐用jsonb,但是我测试发现jsonb查询插入都比不上json,不知道为啥
ps: 发现了,原来是转换为tsdb时,索引没建立起来,重新建表又测试了一遍,确实jsonb读取快。

BATCH 批量插入

// 获取连接的方法,设置ExecutorType.BATCH以及关闭自动提交
    public static SqlSession getSessionForBatch(String xmlPath, Properties properties) throws IOException {
        return MybatisUtil.getSqlSessionFactory(xmlPath, properties).openSession(ExecutorType.BATCH,false);
    }
    public void update(List<PropUrl> propUrlLst) throws IOException {
        // ExecutorType.BATCH
        try (SqlSession session = MybatisUtil.getSessionForBatch(myBatisConfigXmlPath)) {
            InitTsdbUrlTableMapper mapper = (InitTsdbUrlTableMapper) session.getMapper(mapperClazz);

            for (int i = 0; i < propUrlLst.size(); i++) {
                mapper.updatePropMatchRule(propUrlLst.get(i));
                // 每50次提交一次防止内存溢出
                if ((i+1) % 50 == 0) {
                    session.commit();
                    session.clearCache();
                }
            }
            session.commit();
            session.clearCache();

            log.info("update successfully ->{}", propUrlLst);
        }
    }

到此这篇关于利用Mybatis向PostgreSQL中插入并查询JSON字段的文章就介绍到这了,更多相关Mybatis查询JSON字段内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 图文详解mybatis+postgresql平台搭建步骤

    从头开始搭建一个mybatis+postgresql平台 最近有个项目的数据库使用postgresql,使用原生态的mybatis操作数据,原生态的没什么不好,只不过国内有个tk.mybatis的工具帮助我们做了很多实用的事情,大多数情况下我们需要在原生态mybatis上加工的想法它基本上都已经有很好的实现,这篇将分享安装postgresql,配置tk.mybatis的详细步骤以及在这过程中可能遇到的一些小问题. 安装postgresql,执行下面的命令就可以安装了: 复制代码 代码如下: ap

  • mybatis plus实体类中字段映射mysql中的json格式方式

    目录 mybatis plus实体类中字段映射mysql中的json格式 1.实体类中有个属性是其他对象 2.那么取出时怎么进行映射呢,有分为两种情况 mybatis-plus 实体 json 处理 本文总共三个步骤 mybatis plus实体类中字段映射mysql中的json格式 1.实体类中有个属性是其他对象 或者是List:在数据库中存储时使用的是mysql的json格式,此时可以用mybatis plus的一个注解 @TableField(typeHandler = JacksonTy

  • mybatis postgresql 批量删除操作方法

    PostgreSQL是一种特性非常齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为基础的对象关系型数据库管理系统.POSTGRES的许多领先概念只是在比较迟的时候才出现在商业网站数据库中.PostgreSQL支持大部分的SQL标准并且提供了很多其他现代特性,如复杂查询.外键.触发器.视图.事务完整性.多版本并发控制等.同样,PostgreSQL也可以用许多方法扩展,例如通过增加新的数据类型.函数.操作符.聚集函数.索引方法.过程

  • Postgresql在mybatis中报错:操作符不存在:character varying == unknown的问题

    错误: 操作符不存在: character varying == unknown , Hint: 没有匹配指定名称和参数类型的操作符. 您也许需要增加明确的类型转换. 在Mybatis条件查询时,动态SQL的一个错误,sql写的也不多,没仔细看所以一直找不到错误,网上也找不到类似的错误,结果是低级错误... <div> <form:select path="finished" class="col-xs-12 form-control m-b"&g

  • Mybatis-Plus读写Mysql的Json字段的操作代码

    目录 前置条件 一.新建mysql表增加json字段 二.pojo类 三.测试类 前置条件 确保mysql的版本是5.7+ 一.新建mysql表增加json字段 二.pojo类 package com.cxstar.domain; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.

  • Mybatis调用PostgreSQL存储过程实现数组入参传递

    前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于PostgreSQL自带数组类型,所以有一个自定义函数的入参就是一个int数组,形如: 复制代码 代码如下: CREATE OR REPLACE FUNCTION "public"."func_arr_update"(ids _int4)... 如上所示,参数是一个int数组,Mybatis提供了对调用存储过程的支持,那么PostgreSQL独有的数组类型作为存储过程的参数又

  • MybatisPlus保存、读取MySQL中的json字段失败问题及解决

    目录 MybatisPlus保存.读取MySQL的json字段失败 场景 解决方案 Mybatis插入MySQL的json字段报错 解决办法 MybatisPlus保存.读取MySQL的json字段失败 场景 mybatis-plus保存mysql数据库,有字段为json,在java中定义字段为String,但是在保存的时候,json数据没有入库,为空,代码执行未报错. 解决方案 直接用对应的Object来做映射,然后增加对应的@TableField注解 @Data public class U

  • Spring Boot整合MybatisPlus逆向工程(MySQL/PostgreSQL)

    目录 一.创建表 二.创建Spring Boot工程 三.引入逆向工程依赖 四.代码中完成逆向工程配置 五.测试 MyBatis-Plus是MyBatis的增强工具,Generator通过MyBatis-Plus快速生成Entity.Mapper.Mapper XML.Service.Controller等模块的代码,方便快捷. 一.创建表 我们先创建数据库表:sys_log.sys_user CREATE TABLE `sys_log` ( `id` bigint(20) NOT NULL A

  • java mybatis如何操作postgresql array数组类型

    目录 我定义了几个基础数据类型的数组 java mybatis操作 postgresql array数组类型备忘 找了半天没有找到postgresql中关于array数组类型的字段如何对应到java中的数据类型,后来找到了mybatis的TypeHandler,只要实现一个自定义的TypeHandler就行了,如下, 我定义了几个基础数据类型的数组 public class ArrayTypeHandler extends BaseTypeHandler<Object[]> { private

  • 利用Mybatis向PostgreSQL中插入并查询JSON字段

    目录 应用场景介绍 数据insert 数据select BATCH 批量插入 前言: 这里我使用的是TimescaleDB,加了一个时间戳字段,不过没差.关于PostgreSQL中Json数据类型的操作,可以参考官网. 应用场景介绍 将TCP发过来的数据包(通过消息队列发过来)解析出数据(一个数据包含有多帧,一帧中含有多条信息),并和本地规则表的格式对应起来.以JsonLineMsg实体类代表对应的一帧数据: package tsdb.entity; import lombok.AllArgsC

  • 基于Java 利用Mybatis实现oracle批量插入及分页查询

    目录 1.单条数据insert 2.批量数据批量insert 3.创建序列 4.oracle分页查询 前端与后端交互,分页查询 后端海量数据导出,批量查询 1.单条数据insert <!--简单SQL--> insert into userinfo (USERID, USERNAME, AGE) values(1001,'小明',20); <!--Mybatis写法1,有序列,主键是自增ID,主键是序列--> <insert id="insert" par

  • 利用Java的MyBatis框架获取MySQL中插入记录时的自增主键

    第一步: 在Mybatis Mapper文件中添加属性"useGeneratedKeys"和"keyProperty",其中keyProperty是Java对象的属性名! <insert id="insert" parameterType="Spares" useGeneratedKeys="true" keyProperty="id"> insert into spares

  • 利用MyBatis实现条件查询的方法汇总

    SQL映射文件 Mybatis真正强大的是在于它的SQL映射语句,也是它的流弊之处. 它的功能强大,SQL映射文件的配置却比较简单. 使用SQL映射文件可以减少50%以上的代码量. Mybatis专注于SQL,对于开发人员来说可极大限度地进行SQL调优,以保证性能,下面是SQL映射文件的几个顶级元素配置 1.mapper 它是映射文件的根节点,只有一个属性就是 namespace(命名空间)它的作用是区分不同的mapper,里面的参数是全局唯一的,绑定DAO层接口,即面向接口编程 namespa

  • Java使用JDBC或MyBatis框架向Oracle中插入XMLType数据

    先来了解一下什么是XMLType类型. XMLType是Oracle从9i开始特有的数据类型,是一个继承了Blob的强大存在,可以用来存储xml并提供了相当多的操作函数.理论上可以保存2G大小的数据. 那怎么样通过java来插入XMLType类型的数据呢?项目当中采用的是Mybatis,总是出现莫名的异常,都搞不清楚到底是Mybatis的问题还是jdbc本身的问题,所以打算一步步来,先搞定jdbc,再解决Mybatis. JDBC 在折腾了半天之后,发现jdbc操作主要有3种方法: 一.在Jav

  • SQL行号排序和分页(SQL查询中插入行号 自定义分页的另类实现)

    (一)行号显示和排序 1.SQL Server的行号 A.SQL 2000使用identity(int,1,1)和临时表,可以显示行号 SELECT identity(int,1,1) AS ROWNUM, [DataID] INTO #1 FROM DATAS order by DataID; SELECT * FROM #1 B.SQL 2005提供一个很好用的函数row_number(), 可以直接用来显示行号,当然也可以使用SQL 2000的identity SELECT row_num

  • 利用MyBatis进行不同条件的like模糊查询的方法

    之前一直是用MyBatis进行SQL查询时,一般都是用Generator逆向生产的代码来进行查询. 现在遇到了一个业务问题,我们需要进行对不同的条件分别进行模糊查询,首先我想到的就是根据对需要进行模糊查询的字段进行判断,然后调用Example的方式进行查询条件的注入. 对于String类型的数据可以有Like查询这个方法,但是Integer或者Long这种数据类型的话就没有了,得需要自己动手写. 但是呢,我利用Generator生成的代码Example方式进行模糊查询时确无法实现,原因不太清楚,

  • Mybatis利用分页插件PageHelper快速实现分页查询

    目录 前言 首先创建一个Maven项目 数据库中创建一张表 设置Mybatis配置文件 编写pojo实体类和mapper接口和mapper映射文件 创建测试类 总结 前言 Mybatis算是对数据库操作的利器了.但是在处理分页的时候,Mybatis并没有什么特别的方法,一般需要自己去写limit子句实现,成本较高.好在有国内开发者写了一个PageHelper插件,可以帮助我们快速实现分页查询. 官网地址 首先创建一个Maven项目 导入相关依赖: <!-- 依赖列表--> <depend

  • MyBatis中的模糊查询语句

    其实就只有一条sql语句 <select id = "search" resultType = "material"> select material_id,material_num,material_name,material_type,material_model,id from material where material_name like '%${value}%' or material_num like '%${value}%' </

随机推荐