1. 程式人生 > >程式設計式Mybatis獲取oracle表建立表語句

程式設計式Mybatis獲取oracle表建立表語句

寫在前面
Mybatis之前使用過一段時間,當然只是粗糙地使用,而且配合Spring有一部分Mybatis管理的內容都交給了Spring,加上一段時間沒用到又開始忘了,剛好今天碰到一個要求,Oracle的A庫的若干表需要在B庫裡面創建出來,看上去是挺簡單地,通過plsqldeveloper往表名上右鍵就可以很快檢視建立表的DDL語句,或者匯出使用者物件也是可以。但是由於某些原因,現在需要獲取目標表的CREATE語句再到B庫執行。假如需要建立的表有幾十上百個,這樣子一個個右鍵檢視複製就很繁瑣,匯出使用者物件也要在列表找好久,因此剛好藉著mybatis來實現獲取表CREATE語句儲存為SQL檔案。這次選擇程式設計式來使用mybatis,不與Spring搭配使用。

(1)首先Oracle本身提供了工具包來獲取某一個表的建立表語句

SELECT DBMS_METADATA.GET_DDL('TABLE', 'YOUR_TABLE_NAME','TABLE_OWNER') CREATE_STR FROM DUAL

有了該基礎就可以通過Mybatis查詢某一個使用者下所屬表的CREATE語句。

接下來就是著手Mybatis的環境搭建,使用maven來整。
專案大體結構

pom.xml檔案一覽

<?xml version="1.0" encoding="UTF-8"?>
<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>cn.cgy.code</groupId> <artifactId>RmisHelper</artifactId>
<version>1.0-SNAPSHOT</version> <properties> <mybatis.version>3.4.6</mybatis.version> <mave.compiler.version>3.7.0</mave.compiler.version> <oracle.jdbc.version>11.2.0.3</oracle.jdbc.version> </properties> <dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>${oracle.jdbc.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${mave.compiler.version}</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> </build> </project>

MAVEN裡面<build>標籤元素指定了專案編譯及使用的JDK環境為1.8,同時指定MAVEN打包時包含src/main/java下所有xml檔案,src/main/resources下所有xml及properties檔案,這是為了防止Mybatis的mapper檔案沒有被找到而出現FileNotFound錯誤。
Maven裡面內容不多,依賴了mybatis核心jar包及oracle驅動jar(由於某些原因,maven現在貌似不提供oracle驅動包,但是oracle驅動jar包是可以在oracle環境下找到的,一般路徑為oracle_home/jdbc/lib/ojdbcx.jar,你可以將該jar包弄到本地倉庫中,這樣子往後就能繼續以maven方式引入而不用手動新增jar包依賴)。

jdbc.properties屬性檔案

driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@your_ip:1521:orcl
username=your_username
password=your_password

mybatis-config.xml檔案

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 引入配置檔案 -->
    <properties resource="jdbc.properties"/>
    <!-- 配置環境,預設為開發環境 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 使用相對於類路徑的資源引用 -->
    <mappers>
        <mapper resource="cn/cgy/mapper/HelperMapper.xml"/>
    </mappers>
</configuration>

HelperMapper.xml檔案內容

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 如果獲取的表是屬於當前連線使用者,可以省略owner引數,因此SQL工具類只有兩個引數 -->
<mapper namespace="cn.cgy.mapper.HelperMapper">
    <select id="qryCreateSqlByName" resultType="java.util.Map">
        SELECT DBMS_METADATA.GET_DDL('TABLE', #{tableName}) CREATE_STR FROM DUAL
    </select>
</mapper>

MyDbHelper.java內容

/**
 * 獲取資料庫表的CREATE語句
 * @author CGYDAWN
 * @date 2018-09-12
 */
public class MyDbHelper {
    private static SqlSession session;
    private static final String TARGET_PATH = System.getProperty("user.dir")+File.separator+"config"+File.separator+"target"+File.separator;

    public MyDbHelper() {
        String resource = "mybatis-config.xml";
        try (InputStream is = Resources.getResourceAsStream(resource)) {
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            session = sqlSessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一個數據表的SQL檔案
     *
     * @param rptName
     */
    private void generateOneTblCreateSql(String rptName) throws Exception {
            oracle.sql.CLOB createSqlStr = getCreateSqlStr(tableName);
            String createSql = sqlClob2String(createSqlStr,tableName);
            generateFile(createSql,tableName);
    }

    /**
     * 獲取查詢結果
     * @param tableName
     * @return
     */
    private oracle.sql.CLOB getCreateSqlStr(String tableName) {
        ArrayList tableList = (ArrayList) session.selectList("cn.cgy.mapper.HelperMapper.qryCreateSqlByName",tableName);
        HashMap<String,oracle.sql.CLOB> record = (HashMap<String,oracle.sql.CLOB>)tableList.get(0);
        return record.get("CREATE_STR");
    }

    /**
     * CLOB型別轉為String
     * @param clob clob物件
     * @param tableName 表名
     * @return 建表語句
     * @throws Exception
     */
    private String sqlClob2String(oracle.sql.CLOB clob,String tableName) throws Exception {
        Reader reader = clob.getCharacterStream();
        BufferedReader br = new BufferedReader(reader);
        String s = br.readLine();
        StringBuffer sb = new StringBuffer();
        int i = 0;
        while(s != null) {
            //多餘部分丟棄,保留欄位部分(該部分視乎實際獲取的內容修改)
            if(s.indexOf("CONSTRAINT")!=-1) {
                break;
            }
            //丟棄帶有使用者名稱的 CREATE TABLE "USER".TABLENAME這一行,改為 CREATE TABLE TABLENAME
            else if(s.indexOf(tableName)!=-1){
                sb.append("CREATE TABLE "+tableName);
                sb.append("\n");
                s = br.readLine();
            } else {
                sb.append(s);
                sb.append("\n");
                s = br.readLine();
            }
        }
        String rawStr = sb.toString();
        String newStr = rawStr.substring(0,rawStr.lastIndexOf(","));
        return newStr+"\n"+")";
    }

    /**
     * SQL語句儲存.sql檔案
     * @param createSql CREATE語句
     * @param tableName 表名
     * @throws Exception
     */
    private void generateFile(String createSql,String tableName) throws Exception {
        File file = new File(TARGET_PATH+tableName+".sql");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(createSql.getBytes());
        fos.close();
    }


    public static void main(String[] args) throws Exception {
        MyDbHelper helper = new MyDbHelper();
        //如果需要批量獲取創表語句,迴圈呼叫下面方法即可
        helper.generateOneTblCreateSql("YOUR_TABLE_NAME");
    }
}

執行main方法後,程式碼將通過mybatis來獲取建立表語句,然後經過一些字串處理,丟棄一些不太需要的語句部分,保留下純淨的CREATE語句,當然如果需要主鍵之類的部分則可以進一步修改,視乎具體需要。最後生成的檔案儲存在專案config/target目錄下。

生成好sql檔案後,可以在plsqldeveloper下一次性將所有sql檔案執行,達到一次性建立表的要求,省時省力。具體方法可以看我這篇文章Oracle plsqldeveloper中一次執行多個SQL指令碼