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

news2024/11/16 19:04:40

我写了一个 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();
        }
    }
}

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【蓝桥杯嵌入式】RTC——实时时钟

一、RTC简介 RTC RTC—real time clock&#xff0c;实时时钟&#xff0c;主要包含日历、闹钟和自动唤醒这三部分的功能&#xff0c;其中的日历功能我们使用的最多。日历包含两个32bit的时间寄存器&#xff0c;可直接输出时分秒&#xff0c;星期、月、日、年。 从Cubemx里的配置…

【OpenCV】图像算术操作

1 前言 介绍图像算术操作&#xff0c;以及其可以实现的图像亮度、对比度调整效果。相关API&#xff1a; add() subtract() multiply() divide() addWeighted() 2 代码及内容 #include "iostream" #include "opencv2/opencv.hpp"using namespace std…

成都源聚达:抖音小店押金收费标准

在数字浪潮中&#xff0c;抖音小店如星辰般熠熠生辉&#xff0c;吸引了无数商家和创业者。然而&#xff0c;想要在这片星海中畅游&#xff0c;首先得了解其押金的收费标准。正如古人言&#xff1a;“无规矩不成方圆”&#xff0c;明确规则是成功的关键一步。 抖音小店的押金制度…

java爬虫入门程序

<!--爬虫仅支持1.8版本的jdk--> <!-- 爬虫需要的依赖--> <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.2</version> </dependency><!-- 爬虫需…

vue2+element-ui 实现OSS分片上传+取消上传

遇到问题&#xff1a;项目中需要上传500MB以上的视频。一开始使用上传组件el-upload&#xff0c;调用后台接口&#xff0c;但是出现了onprogress显示百分百后接口一直pending&#xff0c;过了很多秒后接口才通&#xff0c;如果遇到大文件的话&#xff0c;接口就会报超时。 解决…

批量复制空白文件夹,轻松管理文件,高效办公新选择

在繁忙的办公环境中&#xff0c;文件管理是提升工作效率的关键。想象一下&#xff0c;你需要为每一个新项目、新任务或新客户创建一个新的文件夹来整理和存储相关文件。手动一个一个地创建文件夹不仅耗时&#xff0c;而且容易出错。现在&#xff0c;我们为你带来一个全新的解决…

R语言中的常用数据结构

目录 R对象的基本类型 R对象的属性 R的数据结构 向量 矩阵 数组 列表 因子 缺失值NA 数据框 R的数据结构总结 R语言可以进行探索性数据分析&#xff0c;统计推断&#xff0c;回归分析&#xff0c;机器学习&#xff0c;数据产品开发 R对象的基本类型 R语言对象有五…

[leetcode] 25. K 个一组翻转链表

给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改变节点内部的值…

老板们注意了,AI可能在悄悄威胁你的工作

前天,科技新闻大佬The Register发了一篇文章,说的是AI在科研领域的管理角色越来越大,可能会让管理岗位变得过时,听起来是不是有点儿疯狂? ESMT Berlin的研究小伙伴们发现,AI能够以更大的规模和效率来管理研究项目,比如审查科学文献和预测创新化合物等等,而不是取代人类…

【Frida】【Android】 工具篇:ProxyPin抓包详解

&#x1f6eb; 系列文章导航 【Frida】【Android】01_手把手教你环境搭建 https://blog.csdn.net/kinghzking/article/details/136986950【Frida】【Android】02_JAVA层HOOK https://blog.csdn.net/kinghzking/article/details/137008446【Frida】【Android】03_RPC https://bl…

【JVM】JVM简介

文章目录 &#x1f334;简介&#x1f332;JVM发展史&#x1f338;Sun Classic VM&#x1f338;Exact VM&#x1f338;HotSpot VM&#x1f338;JRockit&#x1f338;J9 JVMTaobao JVM&#xff08;国产研发&#xff09; &#x1f333;JVM 运行流程⭕总结 &#x1f334;简介 JVM …

【项目启动执行指定代码】⭐️通过案例测试下常用的实现方式

目录 前言 1、监听 ApplicationContext事件 2、实现CommandLineRunner接口 3、实现ApplicationRunner接口 4、使用PostConstruct注解 章末 前言 为了保证程序在启动后的稳定性&#xff0c;需要执行初始化操作&#xff0c;像加载配置&#xff0c;建立数据库连接可以在项目启…

(2024)Ubuntu源码安装多个版本的opencv并切换使用

本人工作会用到x86_64的opencv和aarch64的opencv&#xff0c;所以写下来备忘自用 一、源码编译安装 依赖库安装&#xff1a; sudo apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev o…

简单介绍css及其代码样式

css简介 css用于前端开发&#xff0c;负责对界面进行美化。让页面更美观。 他可以改变html代码的样式&#xff0c;让html代码的网页不那么死板。 css代码格式 选择器 {属性:值; 属性:值&#xff1b;} css的模版架构 css代码放到<style>标签中。 而<style>通常是…

在单交换机局域网中,不同网段的主机通信探秘

在理解局域网中不同网段主机之间的通信之前&#xff0c;我们首先要明白网络的基本组成和工作原理。局域网&#xff08;LAN&#xff09;是一个封闭的网络环境&#xff0c;通常由交换机&#xff08;Switch&#xff09;作为核心设备连接网络中的各个主机。当我们谈论不同网段的主机…

【C#】yield使用

&#x1f4bb;代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks;namespace ConsoleApp15 {internal class Program{static void Main(string[] args){IEnumerable<int&…

如何回答孩子“为什么要过清明?”

清明&#xff0c;是中国人寻根问祖的时节。 为什么要过清明节&#xff1f; 不知道你是否认真想过&#xff0c;我们为什么要过清明节呢&#xff1f; 如果当孩子问起时&#xff0c;你又该如何作答呢&#xff1f; 也许&#xff0c;以下的总结可供你参考。 清明&#xff0c;让…

[蓝桥杯 2019 国 C] 数正方形

[蓝桥杯 2019 国 C] 数正方形 题目描述 在一个 N N N \times N NN 的点阵上&#xff0c;取其中 4 4 4 个点恰好组成一个正方形的 4 4 4 个顶点&#xff0c;一共有多少种不同的取法&#xff1f; 由于结果可能非常大&#xff0c;你只需要输出模 1 0 9 7 10^9 7 1097 的…

DasViewer中,像下图山坡是选择拟合平面还是自定义平面?还是其他的基准面?

问题如图 如若山坡是计算斜面的土方&#xff0c;可以选择用拟合平面模式&#xff0c;该模式适用斜坡。 DasViewer是由大势智慧自主研发的免费的实景三维模型浏览器,采用多细节层次模型逐步自适应加载技术,让用户在极低的电脑配置下,也能流畅的加载较大规模实景三维模型,提供方…

广州到菲律宾海运双清到门,菲律宾双清到门一站式物流

洗衣液出口菲律宾全程海运双清包税到门物流操作流程 为了便于中国的洗衣液产品出口至菲律宾&#xff0c;并实现海运双清包税到门的服务&#xff0c;我们提供一站式的中菲物流解决方案。我们的目标是在保证货物安全的前提下&#xff0c;为您完成从中国起运到菲律宾指定地址的所有…