【问题标题】:Howto IMPORT Java objects with relationship from .csv file into MySQL database?如何将具有关系的 Java 对象从 .csv 文件导入 MySQL 数据库?
【发布时间】:2016-12-18 15:39:58
【问题描述】:

假设我们有 2 个实体:

  1. Person 实体 - 有 2 个属性 person_id(手动输入)和 firstname
  2. 地址实体 - 有 2 个属性 address_id(自动递增)和 streetname

每个人都有一个地址(OneToOne 关系)。所以地址实体将有一个外键(person_id)指向其关联的人。 你会建议如何解决这个问题?

到目前为止,我只找到了一种在没有关系管理的情况下将单个实体导入 mysql 的方法:

LOAD DATA INFILE 'c:/tmp/file.csv' 
INTO TABLE person 
FIELDS TERMINATED BY ',' 
ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS;

【问题讨论】:

  • 我假设人有一个自动递增的键,它需要匹配地址表中的 user_id 之类的东西?
  • 您好 FrankerZ,感谢您抽出宝贵时间。我非常抱歉没有以简洁的方式表达自己。 Person 实体的 pk (id) 将手动给出,但 Address (id) 的 pk 将自动递增。正如您所预料的,user_id 将是 Address 表中的 fk。现在我已经编写了一个 Java 方法来读取 csv 文件以创建对象,然后将它们持久化到数据库中。我想知道在 mysql 本身的功能中是否有更有效的方法。
  • 没问题。这就是 cmets 的作用 =)
  • 我已经用另一个解决方案更新了我的答案。如果您对回复感到满意,请将答案标记为已接受,否则请告诉我,我可以提供进一步帮助。
  • 刚刚试过你的建议,确实解决了我的问题!这是要走的路。再次感谢您的时间和精力。干杯 =)

标签: java mysql hibernate csv import


【解决方案1】:

好的,不幸的是,这将是一个艰难的答案,但可能这是不修改表格以进行插入的唯一方法(强烈不推荐)。

  1. 创建临时表
    CREATE TEMPORARY TABLE `import` (
        `person_name` varchar(300) CHARACTER SET latin1 NOT NULL,
        `person_age` varchar(300) CHARACTER SET latin1 NOT NULL,
        `address1` varchar(300) CHARACTER SET latin1 NOT NULL,
        `city` varchar(300) CHARACTER SET latin1 NOT NULL
    ) ENGINE=MEMORY DEFAULT CHARSET=utf8;
  1. 批量加载(如您在问题中所示)

  2. 从导入表中进行选择,然后遍历每一行

  3. 插入地址表,获取last_insert_id,然后以最后一个插入id插入用户表

  4. 删除您的临时表:DROP TEMPORARY TABLE `import`;

如果您考虑放弃自动递增的 id,而改为使用 UUID(),您可以使用 3 个查询来完成此操作。

  1. 创建临时表
    CREATE TEMPORARY TABLE `import` (
        `uuid` char(36) CHARACTER SET latin1 NOT NULL,
        `person_name` varchar(300) CHARACTER SET latin1 NOT NULL,
        `person_age` varchar(300) CHARACTER SET latin1 NOT NULL,
        `address1` varchar(300) CHARACTER SET latin1 NOT NULL,
        `city` varchar(300) CHARACTER SET latin1 NOT NULL
    ) ENGINE=MEMORY DEFAULT CHARSET=utf8;
  1. 批量加载:
    LOAD DATA INFILE 'c:/tmp/file.csv' 
    INTO TABLE person 
    (@dummy, person_name, person_age, address1, city)
    SET uuid = UUID()
    FIELDS TERMINATED BY ',' 
    ENCLOSED BY '"'
    LINES TERMINATED BY '\n'
    IGNORE 1 ROWS;
  1. 插入:
    INSERT INTO address (id, address1, city)
    SELECT uuid, address1, city
    FROM `import`;

    INSERT INTO person (address_id, person_name, person_age)
    SELECT uuid, person_name, person_age
    FROM `import`;
  1. 使用以下命令删除临时表:DROP TEMPORARY TABLE import;

【讨论】:

  • 您好 FrankerZ。老实说,我对 MySQL 还很陌生。昨天我的脑袋里满是废话;看不透你推荐的步骤。但是现在我又看了你的建议,现在我突然明白了。总结一下,事先我需要将 Person 和 Address 的数据合并到一个表中,然后我需要为每一行执行 2 次不同的插入:首先是 Person,然后是 Address 以及它的 last_insert_id关联的人。这样一来,一切听起来都很合理,对吧?再次感谢你的帮助! :D
  • 是的。一切的问题只是那个自动递增的 ID。因为地址上有一个,所以插入多个表非常困难,因为您需要先获取该 ID,然后再执行任何操作。因为您无法直接在该表上加载数据,所以您必须使用脚本循环并提取数据以获取那些插入 ID(一次一个)。
  • 哇,你的速度非常快。我只是想知道您使用这种快速键入和附加解决方案代码的速度有多快。耶稣,我想你一定是在这个领域工作了很长一段时间的专业人士。此外,美国的工作态度还塑造了你的工作习惯。你有我所有的尊重!
猜你喜欢
  • 2011-06-16
  • 2013-10-15
  • 2013-07-28
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多