java - 部署时 servlet 上下文监听器中的(批量)数据库架构

标签 java mysql sql database jdbc

因此,我有一个文件 schema.sql,其中包含数据库架构,我想在部署应用程序时相应地创建表。

ServletContextListener 看起来像这样

/**
 * This class doesn't really belong to the Ui package, but it does depend on
 * servlet technology like all the other classes here, so I've just put it here for the moment.
 * 
 * The class may be moved in the future
 * 
 * When the application is deployed and started, this class connects to the database,
 * checks if the environment is compatible, checks various other things like whether
 * Core.User.HASH_ALGO or Core.User.STRING_ENCODING are supported (see Core.User for
 * details).
 */
package Ui;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContext;

import com.mysql.jdbc.Driver;
import java.sql.*;

import java.io.*;
import java.net.URL;

/**
 * Web application lifecycle listener.
 */
public class AppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        ServletContext s = sce.getServletContext();
        String db_uri = s.getInitParameter("DB_HOST");
        String db_user = s.getInitParameter("DB_USERNAME");
        String db_pass = s.getInitParameter("DB_PASSWORD");
        try {
          Connection connection = DriverManager.getConnection(db_uri, db_user, db_pass);
          //TODO check if version is compatible ;-), set app as unusable if necessary
          s.setAttribute("db", connection);
          Statement st = null;
          if(null != connection) {
              st = connection.createStatement();
              String schema = null;
              try {
                InputStream str = s.getResourceAsStream("/WEB-INF/sql/schema.sql");
                schema = readStream(str);

              }
              catch(Exception e) {
                  //TODO set global application state as unusable, with a message
              }
              finally {
                int i = st.executeUpdate(schema);
             }
          }
        } catch(SQLException e) {
            //TODO set global application state as unusable, with a message
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //TODO disconnect from the DB
    }

    protected String readStream(InputStream stream) {
        BufferedInputStream bis = new BufferedInputStream(stream);
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        try {
            int result = bis.read();
            while(result != -1) {
              byte b = (byte)result;
              buf.write(b);
              result = bis.read();
            }
        }
        catch(IOException e) {
            return null;
        }
        finally {
            return buf.toString();
        }

    }
}

架构如下:

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT=0;
START TRANSACTION;
SET time_zone = "+00:00";

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL,
  `username` varchar(20) COLLATE utf8_bin DEFAULT NULL,
  `password` varchar(40) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
COMMIT;

错误是:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SET AUTOCOMMIT=0; START TRANSACTION;

所以在我看来它好像不接受一次性接受多个命令。让它发挥作用的正确方法是什么?使用一个单独的 schema.sql 是势在必行的。

最佳答案

我没有足够的环境来测试这一点,但是您是否尝试过使用 addBatch(schema)executeBatch() 批量执行此操作?

否则,您可能会陷入使用 schema.split(";") 拆分命令并一次执行一个命令的困境。如果您这样做,请确保在您脱离循环时不要让 tran 打开。

祝你好运。

关于java - 部署时 servlet 上下文监听器中的(批量)数据库架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8681273/

相关文章:

java - 我该如何初始化它?

jquery - 当用户关闭页面时更改mysql上的数据

sql - 连接具有重复项的 SQL Server 表

java - 如何将结构作为参数传递给 java 函数或从 jni 返回 java

java - 我可以在纯 Java 项目中使用使用 Kotlin 协程构建的库吗?

mysql - 如何为多源复制删除 mariaDB 指定的 Connection_name

MySQL 连接来自另一个表的计数匹配记录,但我也需要零值

mysql - 复杂的查询逻辑

mysql - 如果有特定值则获取sql数据

java - 我通过kafka- Producer多线程发送消息,但出现消息丢失