首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

MyBatis 批量插入 Oracle 實戰:foreach 拼裝 UNION ALL 方案

     編輯:Java 相關知識

前言

Oracle 不支持 MySQL 的 VALUES (...), (...), ... 多行插入語法。MyBatis 批量插入 Oracle 的標準做法是:INSERT INTO ... SELECT ... FROM DUAL UNION ALL SELECT ... FROM DUAL。本文給出完整工程示例,含實體、Mapper、XML、測試代碼。

一、表結構

CREATE TABLE ACCOUNT_INFO (
    ID NUMBER(12) NOT NULL,
    USERNAME VARCHAR2(64),
    PASSWORD VARCHAR2(64),
    GENDER CHAR(1),
    EMAIL VARCHAR2(64),
    CREATE_DATE DATE
);

二、實體類

public class AccountInfo {
    private Long id;
    private String userName, password, gender, email;
    private Date createDate;
    // getter/setter/toString
}

三、Mapper 接口

public interface AccountInfoMapper {
    List queryAllAccountInfo();
    int batchInsertAccountInfo(List accountInfoList);
}

四、MyBatis 配置

4.1 mybatis-configuration.xml

<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
                <property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
                <property name="username" value="xxx"/>
                <property name="password" value="xxx"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="config/AccountInfoMapper.xml"/>
    </mappers>
</configuration>

4.2 AccountInfoMapper.xml —— 核心批量插入 SQL

<mapper namespace="com.oracle.mapper.AccountInfoMapper">
    <resultMap id="BaseResultMap" type="com.oracle.entity.AccountInfo">
        <id column="ID" property="id" jdbcType="DECIMAL"/>
        <result column="USERNAME" property="userName" jdbcType="VARCHAR"/>
        <result column="PASSWORD" property="password" jdbcType="VARCHAR"/>
        <result column="GENDER" property="gender" jdbcType="CHAR"/>
        <result column="EMAIL" property="email" jdbcType="VARCHAR"/>
        <result column="CREATE_DATE" property="createDate" jdbcType="DATE"/>
    </resultMap>

    <select id="queryAllAccountInfo" resultMap="BaseResultMap">
        SELECT ID, USERNAME, PASSWORD, GENDER, EMAIL, CREATE_DATE FROM ACCOUNT_INFO
    </select>

    <insert id="batchInsertAccountInfo" parameterType="java.util.List">
        INSERT INTO ACCOUNT_INFO (ID, USERNAME, PASSWORD, GENDER, EMAIL, CREATE_DATE)
        (
            <foreach collection="list" item="accountInfo" separator="UNION ALL">
                SELECT #{accountInfo.id}, #{accountInfo.userName}, #{accountInfo.password},
                       #{accountInfo.gender}, #{accountInfo.email}, #{accountInfo.createDate}
                FROM DUAL
            </foreach>
        )
    </insert>
</mapper>

關鍵點:

  • collection="list":MyBatis 自動將 List 參數包裝為 {list: [...]}。
  • separator="UNION ALL":生成 SELECT ... FROM DUAL UNION ALL SELECT ... FROM DUAL。
  • 每行 SELECT ... FROM DUAL 是 Oracle 單行插入標準寫法。

五、測試代碼

public class MybatisTest {
    public static void main(String[] args) throws Exception {
        SqlSessionFactory sf = new SqlSessionFactoryBuilder()
            .build(Resources.getResourceAsStream("config/mybatis-configuration.xml"));
        try (SqlSession session = sf.openSession()) {
            AccountInfoMapper mapper = session.getMapper(AccountInfoMapper.class);
            
            List data = generateData(); // 構造 3 條測試數據
            int rows = mapper.batchInsertAccountInfo(data);
            System.out.println("批量插入行數: " + rows);
            session.commit();
        }
    }
    static List generateData() { ... }
}

六、性能與大數據量優化

場景方案
數據量 < 1000單次 UNION ALL 即可,SQL 長度可控
數據量 1000-10000分批提交(如 500 條/批),避免 SQL 過長超過 Oracle 64KB 限制
數據量 > 100001. 臨時表 + INSERT /*+ APPEND */ 直寫數據塊 2. SQL*Loader / 外部表 3. Oracle 批量綁定 PreparedStatement.addBatch() 繞過 MyBatis

七、常見坑點

  1. 日期類型:java.sql.Date 對應 Oracle DATE,java.util.Date/LocalDateTime 需配置類型處理器。
  2. 主鍵衝突:ID 業務生成需保證唯一,或用序列 SEQ.NEXTVAL 在 SQL 中賦值。
  3. 事務控制:批量插入必須在同一事務,session.commit() 統一提交。
  4. 參數名:#{accountInfo.id} 中的 accountInfo 必須與 foreach item="accountInfo" 一致。

八、總結

MyBatis foreach + UNION ALL 是 Oracle 批量插入的標準模式,代碼簡潔、類型安全、易維護。大數據量場景分批提交或轉用臨時表/直路徑載入,根據業務量級選擇最優方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved