1. 程式人生 > >JAVA工程啟動時自動建立資料庫、資料表

JAVA工程啟動時自動建立資料庫、資料表

很多時候,我們會有這樣的需求:

  1. 系統首次部署時,自動建立資料庫、表
  2. 執行單元測試時,資料庫、表維持初始化狀態方便測試。

本文對這種需求的實現做了可行性驗證。

**** 注意這邊需要配置具有建庫建表許可權的資料庫使用者名稱、密碼*****
資料庫配置檔案 jdbc.properties

jdbc.driver   = com.mysql.jdbc.Driver
jdbc.password = root
jdbc.url      = jdbc:mysql://127.0.0.1:3306/jdbc-dbutils?useUnicode=true&characterEncoding=utf-8
jdbc.username = root

待執行初始化sql 指令碼 sql/init.sql ,可以多個

/*
Navicat MySQL Data Transfer

Source Server         : mysql
Source Server Version : 50559
Source Host           : localhost:3306
Source Database       : dbutils

Target Server Type    : MYSQL
Target Server Version : 50559
File Encoding         : 65001

Date: 2018-11-02 22:48:33
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'name_525', '48');
INSERT INTO `user` VALUES ('2', 'name_367', '33');
INSERT INTO `user` VALUES ('3', 'name_630', '23');
INSERT INTO `user` VALUES ('4', 'name_230', '34');
INSERT INTO `user` VALUES ('5', 'name_750', '50');
INSERT INTO `user` VALUES ('6', 'name_762', '26');
INSERT INTO `user` VALUES ('7', 'name_433', '38');
INSERT INTO `user` VALUES ('8', 'name_742', '44');
INSERT INTO `user` VALUES ('9', 'name_960', '37');

這裡只用到了Spring的JdbcTemplate ,故使用了只有單個jar包的 spring的早期版本。
pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>jdbc</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>jdbc</name>
	<url>http://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring</artifactId>
			<version>2.5.6</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.38</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.25</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.25</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.5</version>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

核心程式碼


import java.io.IOException;
import java.io.InputStream;
import java.util.ResourceBundle;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class JdbcTemplateTest
{
    private static final Logger logger = LoggerFactory.getLogger(JdbcTemplateTest.class);
    
    private static JdbcTemplate jdbcTemplate;
    
    static
    {
        try
        {
            // 建庫用臨時DataSource
            MysqlDataSource dataSource = new MysqlDataSource();
            ResourceBundle config = ResourceBundle.getBundle("jdbc");
            String jdbcUrl = StringUtils.substringBeforeLast(config.getString("jdbc.url"), "/");
            dataSource.setUrl(jdbcUrl);
            dataSource.setUser(config.getString("jdbc.username"));
            dataSource.setPassword(config.getString("jdbc.password"));
            jdbcTemplate = new JdbcTemplate(dataSource);
            logger.info("JdbcTemplate = {}", jdbcTemplate);
            
            // 取資料庫名
            String dataBase = StringUtils.substringAfterLast(config.getString("jdbc.url"), "/");
            dataBase = dataBase.contains("?") ? StringUtils.substringBefore(dataBase, "?") : dataBase;
            logger.info("★★★★ jdbcUrl = {}, dataBase = {}", jdbcUrl, dataBase);
            
            // 新建庫
            jdbcTemplate.execute(String.format("drop database if exists `%s`;", dataBase));
            jdbcTemplate.execute(String.format("create database `%s` character set utf8", dataBase));
        }
        catch (DataAccessException e)
        {
            logger.error(e.getMessage(), e);
        }
    }
    
    /**
     * 初始化表
     * 
     * @throws IOException
     * 
     */
    @Before
    public void initTable()
    {
        try (InputStream inputStream = getClass().getResourceAsStream("/sql/init.sql"))
        {
            MysqlDataSource dataSource = new MysqlDataSource();
            ResourceBundle config = ResourceBundle.getBundle("jdbc");
            dataSource.setUrl(config.getString("jdbc.url") + "&allowMultiQueries=true"); // 設定允許一次同時執行多條語句
            dataSource.setUser(config.getString("jdbc.username"));
            dataSource.setPassword(config.getString("jdbc.password"));
            jdbcTemplate = new JdbcTemplate(dataSource);
            logger.info("JdbcTemplate = {}", jdbcTemplate);
            String sqlText = IOUtils.toString(inputStream, "utf-8");
            logger.info("SQL = {}", sqlText);
            
            if (dataSource.getUrl().contains("allowMultiQueries=true"))
            {
                logger.info("開始執行當前的初始化語句塊");
                jdbcTemplate.execute(sqlText);
            }
            else
            {
                logger.info("開始分割執行當前的初始化語句塊");
                for (String sql : sqlText.split(";"))
                {
                    if (StringUtils.isNotBlank(sql))
                    {
                        jdbcTemplate.execute(sql);
                    }
                }
            }
            logger.info("★★★★ initTable success!!");
        }
        catch (DataAccessException | IOException e)
        {
            logger.error(e.getMessage(), e);
        }
    }
    
    /**
     * JdbcTemplate
     * 
     * @see [類、類#方法、類#成員]
     */
    @Test
    public void testTemplate()
    {
        String sql = "select 1 from dual";
        Object object = jdbcTemplate.queryForObject(sql, Integer.class);
        logger.info("Execute: {} ==> {}", sql, object);
    }
}

完整的專案程式碼請參考:
https://gitee.com/00fly/java-code-frame/tree/master/jdbc