Java将树型结构的Excel表格数据导入数据库(遇到的若干问题汇总)

1. 安装数据库(文章中使用的为MySQL)

2. 安装配置Java的jdk

3. 下载Java的数据库jar包

https://dev.mysql.com/downloads/windows/installer/8.0.html
使用Platform independent 下载任意一个都可
在这里插入图片描述
解压并将其jar文件放入项目lib文件夹下(没有可以自己创建一个)
并在项目配置的库中加入对该jar文件的依赖

4. 前期准备结束,接下来开始写代码

5. 首先准备一个Excel表,并将其转为.csv格式

6. 将该csv表转为utf-8编码,不修改编码将会出现乱码

此处Office用户可以直接通过另存为修改编码
WPS用户在进行表格编码修改时较为麻烦(WPS不提供该功能)
可以先另存为.csv文件,之后将其后缀改为.txt(不显示后缀的可以自行百度)
通过记事本打开,在另存为时,修改编码为utf-8
之后再修改后缀为.csv

7. 读取Excel文件

        List<List<String>> data=new ArrayList<List<String>>();
        //读取excel指定sheet中的各行数据,存入二维数组,不包括首行
        try {
            BufferedReader read = new BufferedReader(new FileReader("E:\\data.csv"));//换成你的文件名
            String line = read.readLine();//首行标题不要
            int index=0;
            while((line=read.readLine())!=null){
                String item[] = line.split(",");//CSV格式文件为逗号分隔符文件,这里根据逗号切分
                if(item.length<10){
                    String ret[]=new String[10];
                    for(int i=0;i<item.length;i++){
                        ret[i]=item[i];
                    }
                    for(int i=item.length;i<10;i++){
                        ret[i]="null";
                    }
                    item=ret;
                }
                if(item.length>10){
                    System.out.println(1);
                }
                if(data.size()==2610){
                    System.out.println(1);
                }
                data.add(Arrays.asList(item));
                index++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

注意:此处曾遇到两个问题:
(1)表格中数据包含逗号,而此处采用逗号分隔
解决办法:将表格中的逗号转为中文逗号,而split参数使用英文逗号
(2)表格中可能由于数据原因,会出现空的格子
解决办法:在

String item[] = line.split(",");

后添加对数组长度的判断,并补齐

                if(item.length<10){
                    String ret[]=new String[10];
                    for(int i=0;i<item.length;i++){
                        ret[i]=item[i];
                    }
                    for(int i=item.length;i<10;i++){
                        ret[i]="null";
                    }
                    item=ret;
                }

8. 将数据处理为树型数据(注意此处每一级都有两个数据项,因此width变量值为2,该数据可以更改)

        // 定义主键id 对应数据库中主键
        Short index = 1;
        Short parentId = null;//定义父id,第一级数据的父id为0
        String levelName = null;//分类名称
        String code=null;//分类对应数据
        // tempMap为临时变量,记录那些已经添加过了 key为CatName+层级 value 为记录对象,用于查询非第一级数据的parentId
        Map<Integer, Category> tempMap = new HashMap<>();
        // 记录最终需要插入数据库的数据
        List<DataItem> insertDatas = new ArrayList<DataItem>();
        DataItem level = null;
        int allCols = datas.get(0).size();//获取导入数据的列数
        int width=2;
        for (int column = 0; column < allCols; column+=width)
        {//先对每一层级遍历
            for (int i = 0; i < datas.size(); i++)
            {//对该层级的每一项遍历,找到不同的项
                Integer key1;
                List<String> rows = datas.get(i);
                //设置层级的关联关系,用于获取parentId
                if (column == 0)
                {
                    // 如果是第一列,parentid 默认为0
                    parentId = (short) 0;
                }
                else
                {
                    // 如果不是一列,则在tempMap中寻找对应的父类id作为parentid
                    String key=rows.get(column-width) + "_" + String.valueOf(column/2);
                    key1=key.hashCode();
                    parentId = tempMap.get(key1.intValue()).getCodeId();
                }
                code = rows.get(column);
                levelName=rows.get(column+1);
                //tempMap中没有记录过则表示是要插入的数据
                String key=code + "_" + (column + width)/2;
                Integer a=key.hashCode();
                if (!tempMap.containsKey(a.intValue()))//没有该数据
                {
                    level = new Category();
                    level.setCodeId(index++);
                    level.setLevelName(levelName);
                    level.setCode(code);
                    level.setParentId(parentId);
                    level.setGrade(Byte.valueOf(String.valueOf((column + width)/2)));
                    a=key.hashCode();
                    tempMap.put(a.intValue(), level);
                    //添加到最终要导入的列表中
                    insertDatas.add(level);
                }
            }
        }
        //批量插入数据库中
        insertJDBC(insertDatas);
    static class DataItem{//代码中使用的类,用于存储数据项
        Short codeId;
        String code;
        String name;
        Short parentId;
        int grade;
        public short getCodeId() {
            return codeId;
        }
        public void setCodeId(Short aShort) {
            this.codeId=aShort;
        }
        public void setLevelName(String levelName) {
            this.name=levelName;
        }
        public void setParentId(Short parentId) {
            this.parentId=parentId;
        }
        public void setGrade(Byte valueOf) {
            this.grade=valueOf;
        }
        public void setCode(String code) {
            this.code=code;
        }
    }

注意:此处遇到的问题有:
(1)Map的containsKey不起作用
出错原因:需要重写equal和hashCode
解决方法:
1 重写equal和hashCode(比较麻烦)
2(代码中使用的是第二种,推荐这种)利用String的hashCode函数获取字符串的hashCode,并将intValue值作为key,屏蔽底层,可以正常使用containsKey

String key=rows.get(column-width) + "_" + String.valueOf(column/2);
key1=key.hashCode();
parentId = tempMap.get(key1.intValue()).getCodeId();

9. 将数据导入数据库

    static void insertJDBC(List<Category> list){
        Connection con;
        //jdbc驱动
        String driver="com.mysql.cj.jdbc.Driver";
        //数据库接口3306,数据库名为icd
        String url="jdbc:mysql://localhost:3306/icd?&useSSL=false&serverTimezone=UTC";
        String user="root";//登录用户名
        String password="********";//密码
        try {
            //注册JDBC驱动程序
            Class.forName(driver);
            //建立连接
            con = DriverManager.getConnection(url, user, password);
            if (!con.isClosed()) {
                System.out.println("数据库连接成功");
            }
            Statement stmt= con.createStatement();
            for(int k=0;k<list.size();k++) {
                int codeId = list.get(k).codeId;
                String code = list.get(k).code;
                String name = list.get(k).name.replace("\'","\'"+"\'");
                Short parentId = list.get(k).parentId;
                int grade = list.get(k).grade;
                String sql = "insert into icdnine VALUES(" + codeId +",'"+ code +"','"+ name +"',"+ (int)parentId +","+ grade + ")";
                boolean ret = stmt.execute(sql);
            }
            con.close();
        } catch (ClassNotFoundException e) {
            System.out.println("数据库驱动没有安装");

        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("数据库连接失败");
        }
    }

此处遇到的问题有:
(1)sql语句中需要使用字符串变量
解决方法:
在字符串变量前后加单引号’,再进行字符串拼接
即+" ’ " +string+" ’ "+

String sql = "insert into table VALUES(" + codeId +",'"+ code +"','"+ name +"',"+ (int)parentId +","+ grade + ")";

(2) 数据中有单引号,导致sql语句出错
解决方法:
将单引号replace为两个单引号
因为在sql语句中,两个单引号将被读为单引号

String name = list.get(k).name.replace("\'","\'"+"\'");

参考链接:
https://blog.csdn.net/zyq1084577627/article/details/78727623/

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值