Mybatis-spring配置文件
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- datasource --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${admin.datasource.url}" /> <property name="username" value="${admin.datasource.username}" /> <property name="password" value="${datasource.password}" /> <property name="maxActive" value="${admin.datasource.maxActive}" /> <property name="maxWait" value="${admin.datasource.maxWait}" /> <property name="initialSize" value="1" /> <property name="minIdle" value="1" /> <property name="timeBetweenEvictionRunsMillis" value="3000" /> <property name="minEvictableIdleTimeMillis" value="300000" /> <property name="validationQuery" value="SELECT 'x'" /> <property name="testWhileIdle" value="true" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <!-- <property name="poolPreparedStatements" value="false" /> --> <property name="maxPoolPreparedStatementPerConnectionSize" value="500" /> </bean> <!-- sqlSessionFactory,mybatis --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 生成的所有Mapper --> <property name="configLocation" value="classpath:application-entity.xml" /> <!-- 自定义Mapper.xml --> <property name="mapperLocations"> <list> <value>classpath:batchtest/*.xml</value> </list> </property> <!-- 扫描model包 --> <property name="typeAliasesPackage" value="com.momix.dbao.dao.entity,com.momix.heda.model.entity" /> <property name="plugins"><!--分页插件 --> <array> <bean class="com.github.pagehelper.PageHelper"> <property name="properties"> <value> dialect=mysql reasonable=true </value> </property> </bean> </array> </property> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> </bean> <!-- scann mapper --> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.momix.dbao.dao.mapper,com.momix.heda.dao" /> <property name="properties"> <value> mappers=com.momix.dbao.dao.core.MyBatisBaseMapper </value> </property> </bean> <!-- transaction --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="get*" propagation="SUPPORTS" /> <tx:method name="find*" propagation="SUPPORTS" /> <tx:method name="create*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="del*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true" expose-proxy="true"> <aop:pointcut id="dbao" expression="execution(* com.momix.dbao.service..*(..))" /> <aop:advisor pointcut-ref="dbao" advice-ref="txAdvice" /> </aop:config> <!-- scan service --> <context:component-scan base-package="com.momix.dbao.service,com.momix.heda.service,com.momix.basedao,com.momix.dbao.dao.sqlxml"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> </context:component-scan> </beans>
Mybatis3批量插入
配置文件Sql语句:
<?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"> <mapper namespace="com.momix.dbao.dao.mapper.sqlxml.BatchTestMapper"> <!-- 批量新增Sql --> <insert id="batchInsert" parameterType="java.util.List"> insert into batch_test (name,sex,birthday,mobile) values <foreach collection="list" item="item" index="index" separator="," > (#{item.name},#{item.sex},#{item.birthday},#{item.mobile}) </foreach> </insert> <!-- 批量修改Sql --> <update id="batchUpdate" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";"> update batch_test set name = #{item.name},sex = #{item.sex},birthday = #{item.birthday},mobile = #{item.mobile} where id = #{item.id} </foreach> </update> <select id="getCount" resultType="Integer"> select count(*) from batch_test </select> <delete id="deleteData"> delete from batch_test </delete> </mapper>
Mapper方法:
package com.momix.dbao.dao.mapper.sqlxml;
import java.util.List;
import com.momix.dbao.dao.core.MyBatisBaseMapper;
import com.momix.dbao.dao.entity.sqlxml.BatchTest;
public interface BatchTestMapper extends MyBatisBaseMapper<BatchTest> {
/**
* 批量插入方法
*
* @param params
* 插入集合
*/
void batchInsert(List<BatchTest> params);
/**
* 批量修改方法
*
* @param params
* 修改集合
*/
void batchUpdate(List<BatchTest> params);
/**
* 删除数据
*
* @return 删除行数
*/
int deleteData();
/**
* 获取数据库所有行数
*/
int getCount();
}
测试代码:
采用TestNG进行测试
package com.momix.test.batch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.momix.dbao.dao.dto.sqlxml.BatchTestDTO;
import com.momix.dbao.dao.entity.sqlxml.BatchTest;
import com.momix.dbao.dao.mapper.sqlxml.BatchTestMapper;
import com.momix.dbao.service.test.TestOneService;
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class BatchTestMain extends AbstractTestNGSpringContextTests {
@Autowired
private TestOneService testOneService;
@Autowired
private BatchTestMapper batchTestMapper;
private List<BatchTest> paramsMapper;
// 每次测试插入行数
int size = 0;
// 所有测试案例
List<Integer> sizes = new ArrayList<Integer>();
@BeforeTest
public void initData() {
sizes.add(100);
sizes.add(300);
sizes.add(500);
sizes.add(800);
sizes.add(1000);
sizes.add(1500);
sizes.add(2000);
sizes.add(3000);
sizes.add(5000);
sizes.add(8000);
sizes.add(10000);
sizes.add(30000);
sizes.add(50000);
sizes.add(100000);
}
public void printData(List<Map<String, Long>> infos) {
System.out
.println("***********************************************************************");
for (int i = 0; i < infos.size(); i++) {
Map<String, Long> info = infos.get(i);
System.out.println("测试插入行数 : " + info.get("a") + " 实际插入行数: "
+ info.get("b") + " 删除行数 : " + info.get("d") + " 耗时 : "
+ info.get("c"));
}
System.out
.println("***********************************************************************");
}
@Test(enabled = true)
public void testBatchInsertMapper() {
List<Map<String, Long>> infos = new ArrayList<Map<String, Long>>();
try {
long start = 0l;
long end = 0l;
int b = 0;
int d = 0;
Map<String, Long> info = null;
for (int i = 0; i < sizes.size(); i++) {
info = new HashMap<String, Long>();
// 当前插入行数
size = sizes.get(i);
// 当前测试插入数据
paramsMapper = this.getDataMapper();
System.out.println(paramsMapper.size());
// 开始时间
start = System.currentTimeMillis();
// 批量插入开始
testOneService.batchTestInsertMapper(paramsMapper);
// 结束时间
end = System.currentTimeMillis();
b = batchTestMapper.getCount();
d = batchTestMapper.deleteData();
info.put("a", (long) size); // 应当插入行数
info.put("b", (long) b);// 实际插入行数
info.put("c", (end - start)); // 耗时
info.put("d", (long) d); // 删除行数
infos.add(info);
}
} catch (Exception e) {
e.printStackTrace();
}
printData(infos);
}
private List<BatchTest> getDataMapper() {
List<BatchTest> tests = new ArrayList<BatchTest>();
BatchTest test = null;
for (int i = 0; i < size; i++) {
test = new BatchTest();
test.setName(String.valueOf(i));
test.setSex(0);
tests.add(test);
}
return tests;
}
}
通过org.mybatis.spring.SqlSessionTemplate进行批量操作,分步提交
Sql配置文件
<?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">
<mapper namespace="com.momix.dbao.dao.dto.sqlxml.BathcTest">
<!-- 批量新增Sql -->
<insert id="batchInsertBatchTest" useGeneratedKeys="true" keyProperty="id" parameterType="com.momix.dbao.dao.dto.sqlxml.BatchTestDTO">
insert into batch_test (name,sex,birthday,mobile)
values (#{name},#{sex},#{birthday},#{mobile})
</insert>
<!-- 批量修改Sql -->
<insert id="batchUpdateBatchTest" parameterType="com.momix.dbao.dao.dto.sqlxml.BatchTestDTO">
update batch_test set
name = #{name},sex = #{sex},birthday = #{birthday},mobile = #{mobile}
where id = #{id}
</insert>
</mapper>
底层代码:
BaseDao代码
package com.momix.basedao;
import java.util.List;
import javax.annotation.Resource;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
public abstract class BaseDao<O> {
@Resource
private SqlSessionTemplate sqlSessionTemplate;
/**
* 获取当前xml的namespace
* @return String
*/
protected abstract String getNameSpace();
/**
* 批量修改 分步提交
*
* @param statementName
* ID
* @param data
* 数据集合
*/
protected void batchUpdate(String statementName, List<O> data) {
// 当前方法没有用Spring事务
SqlSession session = sqlSessionTemplate.getSqlSessionFactory()
.openSession();
try {
int size = data.size();
for (int i = 0; i < size; i++) {
O param = data.get(i);
session.update(getNameSpace() + "." + statementName, param);
if (size % 100 == 0) {
// 每200条提交
session.commit();
// 清楚缓存,防止溢出
session.clearCache();
}
}
} catch (Exception e) {
// 出现异常,回滚还没有提交的数据
session.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/**
* 批量插入 分步提交
*
* @param statementName
* ID
* @param data
* 数据集合
*/
protected void batchInsert(String statementName, List<O> data) {
// 当前方法没有用Spring事务
SqlSession session = sqlSessionTemplate.getSqlSessionFactory()
.openSession();
try {
int size = data.size();
for (int i = 0; i < size; i++) {
O param = data.get(i);
session.update(getNameSpace() + "." + statementName, param);
if (size % 100 == 0) {
// 每200条提交
session.commit();
// 清楚缓存,防止溢出
session.clearCache();
}
}
} catch (Exception e) {
// 出现异常,回滚还没有提交的数据
session.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
Dao代码:
package com.momix.dbao.dao.sqlxml;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.momix.basedao.BaseDao;
import com.momix.dbao.dao.dto.sqlxml.BatchTestDTO;
@Repository
public class BatchTestDao extends BaseDao<BatchTestDTO> {
@Override
protected String getNameSpace() {
return "com.momix.dbao.dao.dto.sqlxml.BathcTest";
}
public void batchInsert(List<BatchTestDTO> params) {
super.batchInsert("batchInsertBatchTest", params);
}
public void batchUpdate(List<BatchTestDTO> params) {
super.batchUpdate("batchUpdateBatchTest", params);
}
}
测试代码:
package com.momix.test.batch;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.momix.dbao.dao.dto.sqlxml.BatchTestDTO;
import com.momix.dbao.dao.entity.sqlxml.BatchTest;
import com.momix.dbao.dao.mapper.sqlxml.BatchTestMapper;
import com.momix.dbao.service.test.TestOneService;
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class BatchTestMain extends AbstractTestNGSpringContextTests {
@Autowired
private TestOneService testOneService;
@Autowired
private BatchTestMapper batchTestMapper;
private List<BatchTestDTO> paramsDao;
// 每次测试插入行数
int size = 0;
// 所有测试案例
List<Integer> sizes = new ArrayList<Integer>();
@BeforeTest
public void initData() {
sizes.add(100);
sizes.add(300);
sizes.add(500);
sizes.add(800);
sizes.add(1000);
sizes.add(1500);
sizes.add(2000);
sizes.add(3000);
sizes.add(5000);
sizes.add(8000);
sizes.add(10000);
sizes.add(30000);
sizes.add(50000);
sizes.add(100000);
}
@Test(enabled = false)
public void testBatchInsertDao() {
long start = 0l;
long end = 0l;
int b = 0;
int d = 0;
List<Map<String, Long>> infos = new ArrayList<Map<String, Long>>();
Map<String, Long> info = null;
for (int i = 0; i < sizes.size(); i++) {
info = new HashMap<String, Long>();
// 当前插入行数
size = sizes.get(i);
// 当前测试插入数据
paramsDao = this.getDataDao();
// 开始时间
start = System.currentTimeMillis();
// 批量插入开始
testOneService.batchTestInsertDao(paramsDao);
// 结束时间
end = System.currentTimeMillis();
b = batchTestMapper.getCount();
d = batchTestMapper.deleteData();
info.put("a", (long) size); // 应当插入行数
info.put("b", (long) b);// 实际插入行数
info.put("c", (end - start)); // 耗时
info.put("d", (long) d); // 删除行数
infos.add(info);
}
printData(infos);
}
public void printData(List<Map<String, Long>> infos) {
System.out
.println("***********************************************************************");
for (int i = 0; i < infos.size(); i++) {
Map<String, Long> info = infos.get(i);
System.out.println("测试插入行数 : " + info.get("a") + " 实际插入行数: "
+ info.get("b") + " 删除行数 : " + info.get("d") + " 耗时 : "
+ info.get("c"));
}
System.out
.println("***********************************************************************");
}
private List<BatchTestDTO> getDataDao() {
List<BatchTestDTO> tests = new ArrayList<BatchTestDTO>();
BatchTestDTO test = null;
for (int i = 0; i < size; i++) {
test = new BatchTestDTO();
test.setName(String.valueOf(i));
test.setSex(0);
tests.add(test);
}
return tests;
}
}
测试结果:
总结:
通过jdbc循环分步提交,耗时较长,但比较稳定。
通过Mybatis用foreach进行批量操作,耗时较短,但数据量过大会出现异常
选择哪种方式,只能视业务场景而定。
转载于:https://blog.51cto.com/10960988/1791607