{"id":659,"date":"2025-10-21T15:38:47","date_gmt":"2025-10-21T07:38:47","guid":{"rendered":"https:\/\/fugary.com\/?p=659"},"modified":"2025-10-21T15:38:47","modified_gmt":"2025-10-21T07:38:47","slug":"h2%e6%95%b0%e6%8d%ae%e5%ba%93%e8%bf%81%e7%a7%bb%e5%88%b0mysql","status":"publish","type":"post","link":"https:\/\/fugary.com\/?p=659","title":{"rendered":"H2\u6570\u636e\u5e93\u8fc1\u79fb\u5230MySQL"},"content":{"rendered":"<p>\u6700\u8fd1\u5728\u4f7f\u7528<code>simple-api-doc<\/code>\u9879\u76ee\u65f6\uff0c\u6ca1\u6709\u6ce8\u610f\u628a\u6570\u636e\u5e93\u7c7b\u578b\u5730\u5740\u6539\u6210<code>MySQL<\/code>\uff0c\u4f7f\u7528\u4e86\u9ed8\u8ba4\u7684<code>H2<\/code>\u4e0a\u7ebf\u4f7f\u7528\u4e86\u4e00\u6bb5\u65f6\u95f4\u4e4b\u540e\u624d\u53d1\u73b0\uff0c<code>H2<\/code>\u6ca1\u6709<code>MySQL<\/code>\u65b9\u4fbf\u7ba1\u7406\uff0c\u56e0\u6b64\u9700\u8981\u8fc1\u79fb\uff0c\u627e\u4e86\u4e0d\u5c11\u8fc1\u79fb\u5de5\u5177\u53d1\u73b0\u90fd\u4e0d\u662f\u5f88\u597d\u7528\uff0c\u5c24\u5176\u662f\u6570\u636e\u7c7b\u578b\u7b49\u95ee\u9898\uff0c\u9020\u6210\u8fc1\u79fb\u5931\u8d25\u6216\u8005\u6570\u636e\u4e3a\u7a7a\u3002\u5176\u5b9e<code>JDBC<\/code>\u5c31\u652f\u6301\u5bfc\u5165\uff0c\u56e0\u6b64\u81ea\u5df1\u5199\u4e86\u4e2a\u6d4b\u8bd5\u4ee3\u7801\u6765\u5b9e\u73b0\u8fc1\u79fb\u6570\u636e\u3002<\/p>\n<h3>\u65b0\u5efa\u8868<\/h3>\n<ol>\n<li>\u6700\u597d\u5148\u628a\u8868\u5efa\u8d77\u6765\uff0c<code>H2<\/code>\u6570\u636e\u5e93\u548c<code>MySQL<\/code>\u7684\u5b57\u6bb5\u7684\u7c7b\u578b\u5e76\u4e0d\u4e00\u6837\uff0c\u4e0d\u5efa\u8bae\u6839\u636e<code>H2<\/code>\u7684\u8868\u7ed3\u6784\u81ea\u52a8\u5efa<code>MySQL<\/code>\u8868\u3002<\/li>\n<li>\u6211\u4eec\u4f7f\u7528<code>flyway<\/code>\u7ba1\u7406<code>schema<\/code>\u7684\u7ed3\u6784\uff0c\u56e0\u6b64\u4e5f\u5df2\u7ecf\u5efa\u597d\u4e86\u8868\uff0c\u800c\u4e14\u90e8\u5206\u8868\u4e0d\u80fd\u8fc1\u79fb\u3002<\/li>\n<\/ol>\n<h3>\u8fc1\u79fb\u8868<\/h3>\n<p>\u6570\u636e\u8868\u5217\u8868\u53ef\u4ee5\u901a\u8fc7<code>meta<\/code>\u83b7\u53d6\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u9700\u8981\u7684\u8868\u8fc1\u79fb\uff0c\u9700\u8981\u6ce8\u610f\u54ea\u4e9b\u8868\u4e0d\u7528\u8fc1\u79fb\uff0c\u9632\u6b62\u6570\u636e\u8986\u76d6\uff1a<\/p>\n<pre><code class=\"language-java\">@Slf4j\npublic class H2ToMySQLAuto {\n    private static final String H2_URL = &quot;jdbc:h2:D:\\\\20250915\\\\apidoc-db&quot;;\n    private static final String H2_USER = &quot;user&quot;;\n    private static final String H2_PASSWORD = &quot;12345678&quot;;\n\n    private static final String MYSQL_URL = &quot;jdbc:mysql:\/\/xx.xx.xx.xx:3306\/api_doc?characterEncoding=utf8&amp;useUnicode=true&amp;serverTimezone=UTC&quot;;\n    private static final String MYSQL_USER = &quot;user&quot;;\n    private static final String MYSQL_PASSWORD = &quot;12345678&quot;;\n\n    private static final boolean TRUNCATE = true;\n\n    public static void main(String[] args) throws Exception {\n        List&lt;String&gt; tables = Arrays.asList(\n                &quot;T_API_DOC&quot;, &quot;T_API_DOC_HISTORY&quot;, &quot;T_API_DOC_SCHEMA&quot;, &quot;T_API_LOG&quot;,\n                &quot;T_API_FOLDER&quot;, &quot;T_API_GROUP&quot;, &quot;T_API_PROJECT&quot;,\n                &quot;T_API_PROJECT_INFO&quot;, &quot;T_API_PROJECT_INFO_DETAIL&quot;,\n                &quot;T_API_PROJECT_SHARE&quot;, &quot;T_API_PROJECT_TASK&quot;, &quot;T_API_USER&quot;, &quot;T_API_USER_GROUP&quot;\n        );\n        try (Connection h2Conn = DriverManager.getConnection(H2_URL, H2_USER, H2_PASSWORD);\n             Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD)) {\n            mysqlConn.setAutoCommit(false);\n            for (String table : tables) {\n                migrateTable(h2Conn, mysqlConn, table);\n            }\n            mysqlConn.commit();\n            log.info(&quot;\u5168\u90e8\u8868\u8fc1\u79fb\u5b8c\u6210&quot;);\n        }\n    }\n\n    private static void migrateTable(Connection h2Conn, Connection mysqlConn, String table) throws SQLException {\n        log.info(&quot;\u5f00\u59cb\u8fc1\u79fb\u8868: {}&quot;, table);\n        \/\/ \u8bfb\u53d6\u8868\u5b57\u6bb5\n        DatabaseMetaData meta = h2Conn.getMetaData();\n        ResultSet rsCols = meta.getColumns(null, null, table, null);\n        List&lt;String&gt; columns = new ArrayList&lt;&gt;();\n        while (rsCols.next()) {\n            columns.add(rsCols.getString(&quot;COLUMN_NAME&quot;));\n        }\n        rsCols.close();\n        if (columns.isEmpty()) {\n            log.info(&quot;\u672a\u627e\u5230\u8868\u7ed3\u6784: {}&quot;, table);\n            return;\n        }\n        String colNames = String.join(&quot;, &quot;, columns);\n        String placeholders = String.join(&quot;, &quot;, Collections.nCopies(columns.size(), &quot;?&quot;));\n        String mysqlTable = getMySqlTable(table);\n        String selectSql = &quot;SELECT &quot; + colNames + &quot; FROM &quot; + table;\n        String truncateSql = &quot;TRUNCATE TABLE &quot; + mysqlTable;\n        String insertSql = &quot;INSERT INTO &quot; + mysqlTable + &quot; (&quot; + colNames + &quot;) VALUES (&quot; + placeholders + &quot;)&quot;;\n        try (PreparedStatement psSelect = h2Conn.prepareStatement(selectSql);\n             PreparedStatement psInsert = mysqlConn.prepareStatement(insertSql);\n             ResultSet rs = psSelect.executeQuery()) {\n            if (TRUNCATE) {\n                mysqlConn.createStatement().execute(truncateSql);\n            }\n            ResultSetMetaData rsmd = rs.getMetaData();\n            int colCount = rsmd.getColumnCount();\n            while (rs.next()) {\n                for (int i = 1; i &lt;= colCount; i++) {\n                    Object value = rs.getObject(i);\n                    psInsert.setObject(i, value);\n                }\n                psInsert.addBatch();\n            }\n            psInsert.executeBatch();\n            log.info(&quot;\u8868 {} \u27a1 {} \u8fc1\u79fb\u5b8c\u6210&quot;, table, mysqlTable);\n        }\n    }\n\n    private static String getMySqlTable(String tableName) { \/\/ \u8868\u540d\u6620\u5c04\n        return tableName.toLowerCase();\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u6700\u8fd1\u5728\u4f7f\u7528simple-api-doc\u9879\u76ee\u65f6\uff0c\u6ca1\u6709\u6ce8\u610f\u628a\u6570\u636e\u5e93\u7c7b\u578b\u5730\u5740\u6539\u6210MySQL\uff0c\u4f7f\u7528\u4e86\u9ed8\u8ba4\u7684H2\u4e0a\u7ebf\u4f7f\u7528 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[4,14,2],"tags":[],"_links":{"self":[{"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/posts\/659"}],"collection":[{"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fugary.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=659"}],"version-history":[{"count":1,"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/posts\/659\/revisions"}],"predecessor-version":[{"id":660,"href":"https:\/\/fugary.com\/index.php?rest_route=\/wp\/v2\/posts\/659\/revisions\/660"}],"wp:attachment":[{"href":"https:\/\/fugary.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=659"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fugary.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=659"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fugary.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=659"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}