【问题标题】:Java/Mysql How would you inject an entire SQL file to a mysql server?Java/Mysql 如何将整个 SQL 文件注入 mysql 服务器?
【发布时间】:2012-04-25 22:15:12
【问题描述】:

您将如何从 java 程序将 .sql 文件加载到 mysql 数据库中?我尝试从自包含的 jar 中提取一个 sql 资源文件,我尝试使用 processBuilder 来定位和运行外部 shell 命令。我已经尝试了所有方法,但似乎没有一种方法是正确的。

所以要查看我遇到的问题,只需这样做:

在任何数据库上执行 mysqldump:mysqldump -uroot --routines myDB > ~/Desktop/myDB.sql

现在让我们尝试从 java/jdbc api 重新创建整个数据库。如何正确、正确地使用我们的 mydB.sql 文件?

认为您创建了一个很好的 jdbc 语句来循环您的数据库文件可能会很好,但是当您确实获得这样的转储部分时,它会变得丑陋和笨拙

下面会遇到问题:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `DOG`
--

DROP TABLE IF EXISTS `DOG`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `DOG` (
  `DOG_ID` mediumint(9) NOT NULL,
  `OWNER_ID` mediumint(9) NOT NULL,
  PRIMARY KEY (`DOG_ID`),
  KEY `CHANNEL_FK1` (`OWNER_ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

这是jdbc的局限吗?是否有一些不错的 api 我可以调用,例如 mysql.createDatabase(myDB.sql)。

【问题讨论】:

  • 它对你有用吗,你只是问一下这种方式的正确性还是它从来没有用过?如果没有,那么请说出问题所在:它是否在 jar 中定位文件?还是它在 ProcessBuilder 中运行文件?还是两者兼而有之?
  • @A.J.查看我刚刚发布的编辑。我一直在摸索试图让它发挥作用,但我从来不觉得它是一种专业的方法。我正在做一个黑客工作方法,我想看看正确的方法

标签: java mysql


【解决方案1】:

Flyway 具有高级 SQL 解析器,可以开箱即用地处理 mysql 转储。为您的用例配置它应该很简单。

【讨论】:

    【解决方案2】:

    我不确定这是最好的方法,但在我需要在运行时创建数据库的类似情况下,它对我有用:

    首先定义如下变量:

    private static final String BASE_MYSQL_COMMAND_LINE_STR = "mysql -uUSER -pPASSWORD -h localhost < ";
    

    如果您不想硬编码,请将“USER”和“PASSWORD”替换为真实的用户名和密码,或者只动态构造字符串。只是在 -u、-p 和实际值之间不要有空格。

    还定义以下函数:

    private static void executeCommandInLinuxShell(String command) throws Exception {
                String[] cmd = {"/bin/sh", "-c", command};  
                Process proc = Runtime.getRuntime().exec(cmd);
                BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                String line;
                while ((line = bufferedreader.readLine()) != null);
                bufferedreader.close();
                proc.waitFor();
    
        }
    

    然后,假设在您的程序中有一个指向“mydB.sql”数据库文件的文件对象“sqlFile”:

    String scmd = BASE_MYSQL_COMMAND_LINE_STR + sqlFile.getAbsolutePath();
    executeCommandInLinuxShell(scmd);
    

    【讨论】:

    • 是的,我也做过这个方法。我认为这是一项 hack 工作,并且觉得必须有一种更简单的方法来通过 jdbc 驱动程序
    • 我不认为有一种方法可以在 jdbc 驱动程序中运行脚本文件而不像其他答案中的其他成员所建议的那样解析文件。至少我在开发代码时没有找到。但是,如果您想这样做,您可以使用现有代码,这样您就不必处理所有解析来知道命令的位置。检查以下帖子中接受的答案:stackoverflow.com/questions/1044194/…
    【解决方案3】:

    如果它不能通过 JDBC 工作,那么我推荐这个。

    通常我将 ANT 用于此类任务(如执行 mysql 转储文件):

    <exec command="mysql -u ${db.user} --password=${db.password} 
                         --database=${db.name}">
        <redirector input="${sql.file}"/>
    </exec>
    

    基本上,您可以从代码中构造和调用 ant 任务(如果您将必要的 ant 依赖项添加到您的类中。

    【讨论】:

      【解决方案4】:
      1. 确保 mysql 连接器位于您的类路径中,例如 java -cp mysql-connector-java-5.1.13-bin.jar 或者如果您使用 ant 或 NetBeans 构建项目,请确保 mysql 连接器位于作为库包含在内,这样当您构建项目时, java -jar YourApplication.jar 应该会找到 lib/mysql-connector-java-5.1.13-bin.jar 或其他任何内容。
      2. 在您的源代码中,加载驱动程序:Class.forName("com.mysql.jdbc.Driver").newInstance();
      3. 加载您的 .sql 文件:String sql = new Scanner(new File("yourfile.sql")).useDelimiter("\Z").next();
      4. 连接到您的数据库:Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/database",username,password);
      5. 执行你的sql:Statement st = conn.createStatement();st.execute(sql);

      以上假设您的 .sql 文件包含 SQL 语句。

      【讨论】:

      • 我理解您的建议,但这并不完全是一个好的解决方案。某些 SQL 可能具有指向尚不存在的表的外键 :) 它们位于表的末尾 :) 并且您无法执行这些语句...(您甚至无法使用 mysqlworkbench 执行这些转储文件。 . 你必须使用命令行)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-06
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 2018-03-10
      相关资源
      最近更新 更多