2011-12-30 45 views
0

因此,我有一個文件schema.sql,其中包含數據庫的模式,我希望在部署應用程序時相應地創建表。(批處理)數據庫模式部署後的servlet上下文偵聽器

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; 

的錯誤是:

您的SQL語法錯誤;檢查與你的MySQL服務器版本相對應的手冊,在'SET AUTOCOMMIT = 0; START TRANSACTION;

所以它在我看來好像它不接受一個鏡頭中的多個命令。什麼是正確的方式來使它工作?使用一個單獨的schema.sql勢在必行。

回答

1

我沒有足夠的環境來測試這個,但是您是否嘗試過使用addBatch(schema)executeBatch()作爲批處理?

否則,您可能會堅持使用schema.split(";")分割命令並一次執行一個。如果你這樣做,一定要不要讓循環開啓。

祝你好運。

+0

The tran? 'addBatch()'和'executeBatch()'不起作用:( – Flavius 2011-12-30 18:35:08

+0

對不起。至於tran,我的意思是說,一旦你做了'START TRANSACTION',盡一切努力確保交易完成。在過去有一些問題留在一個公開的事務中,特別是在連接池環境中會做很不愉快的事情。 – 2011-12-30 20:46:11

+0

謝謝。分裂思想雖然工作,但接受。 – Flavius 2011-12-30 22:23:11

相關問題