【201】Java8读取JSON树形结构并插入到MySQL数据库表中

我写了一个 maven 项目的 Demo,用来演示 JAVA8 如何读取 JSON 文件树形结构,并将这种树形结构保存到 MySQL 中。

json文件 city.json

{
    "name": "山东省",
    "sub": [
        {
            "name": "青岛市",
            "sub": [
                {"name": "市南区"},
                {"name": "市北区"},
                {"name": "城阳区"},
                {"name": "李沧区"},
            ]
        },
        {
            "name": "济南市",
            "sub": [
                {"name": "市中区"},
                {"name": "历下区"},
                {"name": "天桥区"}
            ]
        },
        {
            "name": "淄博市",
            "sub": [
                {"name": "张店区"},
                {"name": "临淄区"},
            ]
        },
        {
            "name": "枣庄市"
        },
    ]
}

MySQL 数据库的 city 表结构:

CREATE TABLE `city` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `parent_id` int(10) NOT NULL COMMENT '父级ID',
  `name` varchar(50) NOT NULL COMMENT '名称',
  `del_flag` tinyint(1) NOT NULL COMMENT '0=未删除,1=已删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4

pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>zhangchao</groupId>
    <artifactId>Java8Json</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.10.1</version>   
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.3.0</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.15</version>
        </dependency>
    </dependencies>
</project>

mybatis 配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/CityMapper.xml"/>
    </mappers>
</configuration>

读取配置文件的类 DBFactory.java

package zhangchao.common.db;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class DBFactory {
    private static SqlSessionFactory sqlSessionFactory = null;

    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public static SqlSessionFactory getInstance(){
        return sqlSessionFactory;
    }

}

mybatis 的 mapper XML 文件 CityMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="zhangchao.addjsontree.CityMapper">


    <resultMap id="rm" type="zhangchao.addjsontree.City">
        <id property="id" column="c_id"/>
        <result property="parentId" column="parent_id"/>
        <result property="name" column="name"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>


    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO `test`.`city` (
            parent_id,
            `name`,
            del_flag
        )
        VALUES
        (
            #{parentId},
            #{name},
            #{delFlag}
        )
    </insert>
</mapper>

和数据库表对应的实体类 City.java

package zhangchao.addjsontree;

public class City {
    private Integer id;
    private Integer parentId;
    private String name;
    private Integer delFlag;
    

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getParentId() {
        return parentId;
    }

    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getDelFlag() {
        return delFlag;
    }

    public void setDelFlag(Integer delFlag) {
        this.delFlag = delFlag;
    }
}

和 JSON 对应的 DTO 文件 CityDto.java

package zhangchao.addjsontree;

import java.util.List;

public class CityDto {
    private Integer id;
    private Integer parentId;
    private String name;
    private List<CityDto> sub;

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("CityDto{");
        sb.append("id=").append(id);
        sb.append(", parentId=").append(parentId);
        sb.append(", name='").append(name).append('\'');
        sb.append(", sub=").append(sub);
        sb.append('}');
        return sb.toString();
    }

    public List<CityDto> getSub() {
        return sub;
    }

    public void setSub(List<CityDto> sub) {
        this.sub = sub;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getParentId() {
        return parentId;
    }

    public void setParentId(Integer parentId) {
        this.parentId = parentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

CityMapper.java

package zhangchao.addjsontree;

public interface CityMapper{

    int insert(City city);
}

整个程序的主方法,演示了具体插入数据库的算法。

先调用 getJSon() 方法,从 JSON 文件中获取 JSON 字符串,然后通过 GSON 转换成 CityDto 对象。

然后使用了树的宽度优先算法遍历树形结构,currentLevel 列表保存当前层节点,nextLevel 列表保存下一层节点。

每次循环把当前层节点插入数据库,并且在插入数据库后,获取数据库 ID(这里把表主键设置成整数自增)。对子节点做是否为空的检查,并且把 NULL 子节点删除掉。把数据库 ID 保存到子节点的 parentId 成员变量中。

把非空子节点加入到 nextLevel 列表中,然后让 currentLevel 引用指向 nextLevel。

package zhangchao.addjsontree;

import com.google.gson.Gson;
import org.apache.ibatis.session.SqlSession;
import zhangchao.common.db.DBFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author zhangchao 
 */
public class TestAddJsonTree {

    private static String getJSon(){
        File f = new File(
                "E:\\ws\\zc\\Java8Json\\src\\main\\resources\\JsonFile\\city.json"
        );
        StringBuilder sb = new StringBuilder();
        FileInputStream fis = null;
        BufferedReader br = null;
        try {
            fis = new FileInputStream(f);
            br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
            String str = br.readLine();
            while(str != null) {
                sb.append(str);
                str = br.readLine();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
                if (br != null) {
                    br.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String json = sb.toString();
        return json;
    }

    private static void dtoToDomain(CityDto dto, City domain) {
        domain.setName(dto.getName());
        domain.setParentId(dto.getParentId());
        domain.setDelFlag(0);
    }

    public static void main(String[] args) {
        String json = getJSon();
        Gson gson = new Gson();
        CityDto cityDto = gson.fromJson(json, CityDto.class);
        if (cityDto == null) {
            return;
        }
        cityDto.setParentId(-1);
        List<CityDto> currentLevel = new ArrayList<>();
        currentLevel.add(cityDto);
        SqlSession sqlSession = DBFactory.getInstance().openSession(false);
        try {
            CityMapper cityMapper = sqlSession.getMapper(CityMapper.class);
            while (currentLevel != null && !currentLevel.isEmpty()) {
                List<CityDto> nextLevel = new ArrayList<>();
                for (CityDto dto : currentLevel) {
                    City domain = new City();
                    dtoToDomain(dto, domain);
                    cityMapper.insert(domain);
                    List<CityDto> sub = dto.getSub();
                    if (sub != null && !sub.isEmpty()) {
                        for (Iterator<CityDto> iterator = sub.iterator(); iterator.hasNext();) {
                            CityDto item = iterator.next();
                            if (item == null) {
                                iterator.remove();
                            } else {
                                item.setParentId(domain.getId());
                            }
                        }
                        nextLevel.addAll(sub);
                    }
                }
                currentLevel = nextLevel;
            }
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
            sqlSession.rollback();
        } finally {
            sqlSession.close();
        }
    }
}

最后插入数据库的效果如下:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/521585.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java | Leetcode Java题解之第14题最长公共前缀

题目&#xff1a; 题解&#xff1a; class Solution {public String longestCommonPrefix(String[] strs) {if (strs null || strs.length 0) {return "";}int minLength Integer.MAX_VALUE;for (String str : strs) {minLength Math.min(minLength, str.length…

汇川PLC学习Day4:电机参数和气缸控制参数

汇川PLC学习Day4&#xff1a;伺服电机参数和气缸控制参数 一、伺服电机参数二、气缸参数1. 输入IO映射&#xff08;1&#xff09;输入IO映射&#xff08;2&#xff09; 输入IO触摸屏标签显示映射 2. 输出IO映射&#xff08;1&#xff09;输出IO映射&#xff08;2&#xff09; …

摄影杂记一

摄影小白&#xff0c;最近买了一台微单&#xff0c;型号是佳能R10&#xff0c;加上18-150套机镜头和佳能RF 50 F1.8定焦镜头。开始学习摄影。 PS&#xff1a;摄影穷三代&#xff0c;单反毁一生。嘿嘿。 一、分镜头拍摄四步提升法 B站&#xff1a;六斤 拍视频三件事&#xff1…

4.2.k8s的pod-标签管理、镜像拉取策略、容器重启策略、资源限制、优雅终止

一、标签管理 1.标签在k8s中极其重要&#xff0c;大多数资源的相互关联就需要使用标签&#xff1b;也就是说&#xff0c;资源的相互关联大多数时候&#xff0c;是使用标签进行关联的&#xff1b; 2.其他作用&#xff0c;在k8s集群中&#xff0c;node节点的一些操作比如污点及污…

【Java设计模式】创建型——工厂方法模式

目录 背景/问题解决方案思路方案 图解简单工厂模式/静态工厂模式工厂方法模式 代码示例&#xff1a;图形工厂意图主要解决何时使用如何解决关键代码 工厂模式的优点工厂模式的缺点使用场景注意事项 背景/问题 在软件设计中&#xff0c;我们经常遇到需要创建不同类型对象的情况…

NzN的数据结构--栈的实现

在前面我们已经学习了哪些线性数据结构呢&#xff1f;大家一起来回顾一下&#xff1a;C语言学过的数组&#xff0c;数据结构中的线性表和顺序表和链表。那我们今天再来介绍数据结构里的两个线性结构--栈和队列。 目录 一、栈的概念及结构 二、用数组实现栈 1. 栈的初始化和…

linux--进程创建

执行了3次ps -f ,ps -f的父进程的ID(PPID)都是一样的,即bash. 实际上Linux上这个bash就是不断的复制自身,然后把复制出来的用exec替换成想要执行的程序(比如ps); 运行ps,发现ps是bash的一个子进程;原因就是bash把自己复制一份,然后替换成ps; 替换,这里就体现了写时拷贝的意义,…

ETL中如何自定义规则

一、ETL中的规则 在使用规则之前我们先来了解一下什么是规则&#xff0c;ETL中规则在很多组件中都能看见&#xff0c;可以理解为按照事前约定好的逻辑去执行&#xff0c;规则可以使得数据更加的规范统一&#xff0c;同时也不需要去纵向的修改底层代码&#xff0c;只需要动态编…

自动驾驶汽车关键技术_感知

自动驾驶汽车关键技术|感知 附赠自动驾驶学习资料和量产经验&#xff1a;链接 两套标准 分别由美国交通部下属的国家高速路安全管理局(NationalHighwayTraffic Safety Administration &#xff0c;NHSTA) 和国际汽车工程师协会&#xff08;Societyof Automotive Engineers&am…

复现chatgpt_ros,需要openapi key

&#xff11;&#xff0e; 前置工作&#xff1a; 现在&#xff55;buntu系统是20.04ros1&#xff0c;现在用docker新建并安装ros2&#xff1a; 最简单的&#xff0c;用大佬的一键安装&#xff1a; wget http://fishros.com/install -O fishros && . fishros 其次自己装…

代码随想录刷题——5双指针法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言5.1 移除元素&#xff08;3.30&#xff09;5.2 翻转字符串&#xff08;3.30&#xff09;5.3 替换数字&#xff08;3.30&#xff09;5.4 翻转字符串里的单词(3.3…

FlutterFlame游戏实践#08 | 打砖块 -关卡设计

theme: cyanosis 本文为稀土掘金技术社区首发签约文章&#xff0c;30天内禁止转载&#xff0c;30天后未获授权禁止转载&#xff0c;侵权必究&#xff01; Flutter\&Flame 游戏开发系列前言: 该系列是 [张风捷特烈] 的 Flame 游戏开发教程。Flutter 作为 全平台 的 原生级 渲…

SQL注入---POST注入

文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 一. POST提交概述 在Webshell文章中介绍过post提交和get提交的区别&#xff0c;这里不再赘述 post提交和get提交的区别&#xff1a; get方式提交URL中的参数信息&#xff0c;post方式则是将信…

【学习分享】小白写算法之选择排序篇

【学习分享】小白写算法之选择排序篇 前言一、什么是选择排序算法二、选择排序算法如何实现三、C语言实现算法四、复杂度计算五、算法稳定性六、小结 前言 简单排序有三种&#xff0c;冒泡排序&#xff0c;插入排序和选择排序。这三种排序的算法算是入门级别的&#xff0c;打好…

UART设计

一、UART通信简介 通用异步收发器&#xff0c; 特点&#xff1a;串行、异步、全双工通信 优点&#xff1a;通信线路简单&#xff0c;传输距离远 缺点&#xff1a;传输速度慢 数据传输速率&#xff1a;波特率&#xff08;单位&#xff1a;baud&#xff0c;波特&#xff09; …

解决IDEA下载mysql驱动太慢

下载驱动 下载页 解压后&#xff0c;提取**.jar**文件&#xff0c;放到一个目录下(你自己决定这个目录) 打开IDEA项目&#xff0c;点击右侧的数据库选项卡 在打开的页面&#xff0c;点击号 依次选择&#xff1a;数据源->MySQL 在弹出的页面&#xff0c;依次选择&#…

注解式 WebSocket - 构建 群聊、单聊 系统

目录 前言 注解式 WebSocket 构建聊天系统 群聊系统&#xff08;基本框架&#xff09; 群聊系统&#xff08;添加昵称&#xff09; 单聊系统 WebSocket 作用域下无法注入 Spring Bean 对象&#xff1f; 考虑离线消息 前言 很久之前&#xff0c;咱们聊过 WebSocket 编程式…

华为ensp中高级acl (控制列表) 原理和配置命令 (详解)

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月6日23点18分 高级acl&#xff08;Access Control List&#xff09;是一种访问控制列表&#xff0c;可以根据数据包的源IP地址、目标IP地址、源端口、目标端口、协议…

【ARM 嵌入式 C 常用数据结构系列 25.1 -- linux 双向链表 list_head 使用详细介绍】

请阅读【嵌入式开发学习必备专栏 】 文章目录 内核双向链表双向链表的数据结构初始化双向链表在双向链表中添加元素遍历双向链表链表使用示例注意事项 内核双向链表 在Linux内核中&#xff0c;双向链表是一种广泛使用的数据结构&#xff0c;允许从任意节点高效地进行前向或后向…

STM32F407-SRAM

SRAM—> 内存 Flash–>硬盘 外置SRAM 可以存储1M数据 地址线&#xff1a;A0-A18&#xff1b;2^18次方&#xff1b;512K个数据块 每个数据块是2字节&#xff1b; 数据线&#xff1a;D0-D15 UB/LB 掩码&#xff1b;低电平有效 UB -》低电平-》数据高字节有效 LB-》低电平…