当前位置:   article > 正文

不指定insert into 字段入全表_insert into 整个表

insert into 整个表

一次业务场景需要,得把一个数据库中的数据导入另一个数据库,2个数据库类型不同,当时采用的方式为:

        把数据库A的表中的数据导出成dat文件(这个数据库导出的文件就是dat文件),一行一条记录,字段顺序按照建表字段顺序,各个字段中间用欧元符号分隔,在数据库B中建表,表结构与数据库中的表结构完全一致,最后再增加一个ids自增字段。dat文件存放在文件服务器指定目录,程序通过ssh连接服务器,并获取dat文件流来获取文件,一行一行读取文件内容然后批量入B库。文件名称中的编码字符可以确定这个文件入哪个表。持久层框架用的是mybatis。

        总共十几+个表,表的字段也都很多,既然文件格式有约定,那入B库时的sql不计划指定字段插入,太多太麻烦。

  1. #指定字段插入数据
  2. insert into tableB (field1,field2) values (#{i1},#{i2});
  3. #不指定字段插入数据,需要按顺序给出全部字段的值
  4. insert into tableB values (#{i1} ... );

最终处理流程是:

1.通过BufferedReader的readLine()方法一行一行读数据;

2.将读出的数据按照字段分隔符(此处为€)分隔成字符串数组,再将字符串数组转成List line,再用ArrayList 包装一下;

List lineList=new ArrayList(Arrays.asList(line.split(dataFileSeparator)));

那么这个lineList里的数据就为一行数据的各个字段值。

为什么要用ArrayList再包装下呢?因为Arrays.asList()返回的对象是 Arrays的内部类,继承了AbstractList,AbstractList中的set, add, remove 抽象方法中都是直接throw new UnsupportedOperationException(); 但内部类 ArrayList 并未重写父类的 add,remove方法,所以我们不能再对存放各个字段值的List不能增加删除,如果不涉及增加其他字段值或删除字段值的操作,可以直接使用,不用包装。对Arrays.asList 再包装一层,生成的List对象就是我们熟知的 ArrayList了。

 3.在循环外层定义一个ArrayList datas,用来存放一行一行数据的List lineList;

4.将datas作为参数传给mapper中的入库方法,xml这么写的:

  1. <insert id="insertModelData">
  2. insert into ${tableName} values
  3. <foreach collection="list" item="line" separator=",">
  4. (
  5. <foreach collection="line" item="item" separator=",">
  6. #{item}
  7. </foreach>
  8. )
  9. </foreach>
  10. </insert>

表名根据文件名称映射,第一层foreach取出一行一行的所有数据,第二层foreach取出每行的各个字段。

就这样,不用写一大堆sql,一个方法就可以满足此任务的所有表的数据入库操作。但是要注意${}、#{}的区别,有需要要额外处理${}字段。

此任务中其他需要注意的问题

1.BufferedReader的readLine()读出的字符串中不包含结尾的"\r","\n"

2.BufferedReader的readLine()相关源码如下:

  1. public String readLine() throws IOException {
  2. return readLine(false);
  3. }
  4. String readLine(boolean ignoreLF) throws IOException {
  5. StringBuffer s = null;
  6. int startChar;
  7. synchronized (lock) {
  8. ensureOpen();
  9. boolean omitLF = ignoreLF || skipLF;
  10. bufferLoop:
  11. for (;;) {
  12. if (nextChar >= nChars)
  13. fill();
  14. if (nextChar >= nChars) { /* EOF */
  15. if (s != null && s.length() > 0)
  16. return s.toString();
  17. else
  18. return null;
  19. }
  20. boolean eol = false;
  21. char c = 0;
  22. int i;
  23. /* Skip a leftover '\n', if necessary */
  24. if (omitLF && (cb[nextChar] == '\n'))
  25. nextChar++;
  26. skipLF = false;
  27. omitLF = false;
  28. charLoop:
  29. for (i = nextChar; i < nChars; i++) {
  30. c = cb[i];
  31. if ((c == '\n') || (c == '\r')) {
  32. eol = true;
  33. break charLoop;
  34. }
  35. }
  36. startChar = nextChar;
  37. nextChar = i;
  38. if (eol) {
  39. String str;
  40. if (s == null) {
  41. str = new String(cb, startChar, i - startChar);
  42. } else {
  43. s.append(cb, startChar, i - startChar);
  44. str = s.toString();
  45. }
  46. nextChar++;
  47. if (c == '\r') {
  48. skipLF = true;
  49. }
  50. return str;
  51. }
  52. if (s == null)
  53. s = new StringBuffer(defaultExpectedLineLength);
  54. s.append(cb, startChar, i - startChar);
  55. }
  56. }
  57. }

可以看出该方法可以设置跳过LF,但是该方法访问权限为default,不支持继承该类重写方法,而且其他方法也不支持我们设置修改变量,所以我们没办法控制readLine()是读到\r 换行还是 \n换行还是\r\n换行,我们没法指定特定换行符来让它读一行,所以文件中有^M时需要留意,有可能它读了半行就返回了。

在windows平台下,换行符是\r\n,而在linux下是\n,这多出来的\r被vim解释成了^M。

 windowslinuxMacBook
换行符\r\n\n\r
ASCII0x0d0a0x0a0x0d

  其中:

  • "\r"在ASCII中表示“换行(LF)”
  • "\n"在ASCII中表示“回车(CR)”
访问控制修饰符
 privatedefaultprotectedpublic
同一类中的成员
同一包中其他类 
不同包中的子类  
不同包中非子类   

笔者当时就遇到^M这个问题,返回半行,入库时mysql报字段不匹配的错误,当然了,少字段嘛。当时时间紧而且是临时需求 ,过一段时间就不用了,所以没有通过程序解决,采用的方式是替换文件中的^M符号。通过程序的话貌似得用read方法,这个就有点复杂了,到指定的换行符才停,逻辑有点小复杂,没时间呀~这里mark一下,有空研究,也欢迎有经验的朋友分享心得。

以下内容来自:Linux下去掉^M的4种方法

第一种方法:

cat -A filename 就可以看到windows下的断元字符 ^M

要去除他,最简单用下面的命令:

dos2unix filename

第二种方法:

1

2

sed -i ‘s/^M//g' filename

#注意:^M的输入方式是 Ctrl + v ,然后Ctrl + M

第三种方法: 

1

2

3

#vi filename

:1,$ s/^M//g

^M 输入方法: ctrl+V ,ctrl+M

第四种方法:

1

2

#cat filename |tr -d ‘/r' > newfile

#^M 可用 /r 代替

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/840372
推荐阅读
相关标签
  

闽ICP备14008679号