專案需一次性導入上萬筆資料至 Oracle,採用批量插入提升效能。Oracle 不支援 MySQL 的 VALUES (...), (...), ... 語法,需使用 INSERT INTO ... SELECT ... FROM DUAL UNION ALL SELECT ... FROM DUAL 形式。
public class AccountInfo {
private Long id;
private String userName;
private String password;
private String gender;
private String email;
private Date createDate;
// Getter/Setter/toString 省略
}
public interface AccountInfoMapper {
List<AccountInfo> queryAllAccountInfo();
int batchInsertAccountInfo(List<AccountInfo> accountInfoList);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd">
<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>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<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>
<!-- 批量插入:Oracle 專用 union all 寫法 -->
<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>
關鍵點:
parameterType="java.util.List" 對應介面方法的 List 參數。collection="list":單參數為 List 時固定值;若為陣列用 array;多參數需封裝 Map。separator="UNION ALL":各 SELECT 之間以 UNION ALL 連接。FROM DUAL (Oracle 虛擬表)。public class MybatisTest {
public static void main(String[] args) throws Exception {
String resource = "config/mybatis-configuration.xml";
InputStream is = Resources.getResourceAsStream(resource);
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
AccountInfoMapper mapper = session.getMapper(AccountInfoMapper.class);
// 查詢驗證
List<AccountInfo> list = mapper.queryAllAccountInfo();
list.forEach(System.out::println);
// 批量插入
mapper.batchInsertAccountInfo(generateData());
session.commit(); // 別忘了提交事務!
}
static List<AccountInfo> generateData() {
List<AccountInfo> result = new ArrayList<>();
// 構造 3 筆測試資料...
return result;
}
}