Mybatis-spring配置文件



	
	
	
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
	
	
	
		
		
		
		
		
			
				classpath:batchtest/*.xml
			
		
		
		
		
			
				
					
						
							dialect=mysql
							reasonable=true
						
					
				
			
		
	

	
		
	
	
	
	
		
		
			
				mappers=com.momix.dbao.dao.core.MyBatisBaseMapper
			
		
	
	
	
	
		
	
	
		
			
			
			
			
			
			
		
	
	
		
		
	

	
	
		
	


Mybatis3批量插入


配置文件Sql语句:




	 
	 
	 
	 	insert into batch_test (name,sex,birthday,mobile) values
	 	  
         	(#{item.name},#{item.sex},#{item.birthday},#{item.mobile}) 
   		
	 
	 
	 
	 
	 	
			update batch_test set 
		 		name = #{item.name},sex = #{item.sex},birthday = #{item.birthday},mobile = #{item.mobile}
		 	where id = #{item.id}
	   
	 
	 
	 
	 	select count(*) from batch_test
	 
	 
	 
	 	delete from batch_test
	 

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 {

	/**
	 * 批量插入方法
	 * 
	 * @param params
	 *            插入集合
	 */
	void batchInsert(List params);

	/**
	 * 批量修改方法
	 * 
	 * @param params
	 *            修改集合
	 */
	void batchUpdate(List 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 paramsMapper;

	// 每次测试插入行数
	int size = 0;
	// 所有测试案例
	List sizes = new ArrayList();

	@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> infos) {
		System.out
				.println("***********************************************************************");
		for (int i = 0; i < infos.size(); i++) {
			Map 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> infos = new ArrayList>();
		try {
			long start = 0l;
			long end = 0l;
			int b = 0;
			int d = 0;
			Map info = null;
			for (int i = 0; i < sizes.size(); i++) {
				info = new HashMap();
				// 当前插入行数
				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 getDataMapper() {
		List tests = new ArrayList();

		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配置文件




	 
	 
	 
	 	insert into batch_test (name,sex,birthday,mobile)
	 		values (#{name},#{sex},#{birthday},#{mobile})
	 
	 
	 
	 
	 	update batch_test set 
	 		name = #{name},sex = #{sex},birthday = #{birthday},mobile = #{mobile}
	 	where id = #{id}
	 
	 


底层代码:

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 {

	@Resource
	private SqlSessionTemplate sqlSessionTemplate;
	
	/**
	 * 获取当前xml的namespace
	 * @return String
	 */
	protected abstract String getNameSpace();

	/**
	 * 批量修改 分步提交
	 * 
	 * @param statementName
	 *            ID
	 * @param data
	 *            数据集合
	 */
	protected void batchUpdate(String statementName, List 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 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 {

	@Override
	protected String getNameSpace() {
		return "com.momix.dbao.dao.dto.sqlxml.BathcTest";
	}

	public void batchInsert(List params) {
		super.batchInsert("batchInsertBatchTest", params);
	}

	public void batchUpdate(List 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 paramsDao;

	// 每次测试插入行数
	int size = 0;
	// 所有测试案例
	List sizes = new ArrayList();

	@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> infos = new ArrayList>();
		Map info = null;
		for (int i = 0; i < sizes.size(); i++) {
			info = new HashMap();
			// 当前插入行数
			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> infos) {
		System.out
				.println("***********************************************************************");
		for (int i = 0; i < infos.size(); i++) {
			Map info = infos.get(i);
			System.out.println("测试插入行数 : " + info.get("a") + "   实际插入行数: "
					+ info.get("b") + "  删除行数 : " + info.get("d") + "  耗时 : "
					+ info.get("c"));
		}
		System.out
				.println("***********************************************************************");
	}

	private List getDataDao() {
		List tests = new ArrayList();

		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;
	}
}


测试结果:

Mybatis批量操作与JDBC批量操作效率测试_第1张图片

总结:

  1. 通过jdbc循环分步提交,耗时较长,但比较稳定。

  2. 通过Mybatis用foreach进行批量操作,耗时较短,但数据量过大会出现异常

  3. 选择哪种方式,只能视业务场景而定。