- 浏览: 394696 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (760)
- 股票日志 (26)
- Selenium (0)
- selenium 2 环境的搭建 (1)
- 并发 (7)
- 框架开发 (1)
- 动态代理 (2)
- Struts2 (2)
- POI (2)
- jdk (3)
- maven (31)
- spring (35)
- mysql (31)
- 工作机会 (3)
- xtream (1)
- oracle dbms_metadata GET_DDL (0)
- SSI (1)
- DB (61)
- powermock (4)
- java 基础 (25)
- 多线程 (11)
- 高手 (2)
- java 底层 (2)
- 专业网站 (1)
- 开发联想 (1)
- 开发联想 (1)
- bat文件 (2)
- 清queue 语句 (1)
- 清queue 语句 (1)
- jquery (7)
- html5 (1)
- Jenkins (10)
- Linux (17)
- 工作issue (2)
- tomcat log (3)
- jvm (23)
- 项目细节 (0)
- oracle (41)
- 泛型 (3)
- 新知识点 (1)
- 数据库ddl 语句 (0)
- AQ (2)
- jms (0)
- 网络资源 (6)
- github (6)
- Easymock (1)
- Dom 解析XML (1)
- windows命令 (2)
- java (7)
- 正则表达式 (5)
- sequence (1)
- oracle 表meta信息 (1)
- 小工具技巧 (1)
- 辅助工具 (1)
- Junit (1)
- 泛型 generic (2)
- Java程序设计 (1)
- cglib (2)
- 架构师之路 (1)
- 数据库连接池 (5)
- c3p0 (1)
- eclipse使用 (1)
- oracle sql plus (1)
- 码农人生 (3)
- SVN (15)
- sqlplus (2)
- jsoup (1)
- 网络爬虫 (2)
- 新技能 (1)
- zookeeper (4)
- hadoop (1)
- SVNKIT (1)
- 从工具到知识点的整理 (1)
- log4j (13)
- 读文件 (0)
- 转义字符 (1)
- command (1)
- web service (3)
- 锁 (1)
- shell 脚本 (1)
- 遇到的错误 (2)
- tomcat (14)
- 房产 (5)
- bootstrap jquery ui (1)
- easyui (2)
- 个人征信 (1)
- 读写分离 (1)
- 备份 (1)
- rmi (6)
- webservice (1)
- JMX (4)
- 内存管理 (3)
- java设计 (1)
- timer (1)
- lock (2)
- concurrent (2)
- collection (1)
- tns (1)
- java基础 (15)
- File (1)
- 本机资源 (1)
- bat (1)
- windows (4)
- 数据结构 (3)
- 代码安全 (1)
- 作用域 (1)
- 图 (2)
- jvm内存结构 (1)
- 计算机思想 (1)
- quartz (6)
- Mongo DB (2)
- Nosql (4)
- sql (5)
- 第三方Java 工具 jar 项目 (2)
- drools (1)
- java swing (2)
- 调用console (1)
- runtime (1)
- process (1)
- swing (2)
- grouplayout (1)
- dubbo (0)
- bootstrap (0)
- nodejs (2)
- SVN hooks (1)
- jdbc (3)
- jdbc error (1)
- precedure (1)
- partition_key (1)
- active mq (1)
- blob (2)
- Eclipse (6)
- web server (1)
- bootstrapt (2)
- struts (1)
- ajax (1)
- js call back (1)
- 思想境界拓展 (1)
- JIRA (1)
- log (1)
- jaxb (3)
- xml java互相转换 (1)
- 装修 (2)
- 互联网 (2)
- threadlocal (3)
- mybatis (22)
- xstream (1)
- 排序 (1)
- 股票资源 (1)
- RPC (2)
- NIO (3)
- http client (6)
- 他人博客 (1)
- 代理服务器 (1)
- 网络 (2)
- web (1)
- 股票 (5)
- deadlock (1)
- JConsole (2)
- activemq (3)
- oralce (1)
- 游标 (1)
- 12月13日道富内部培训 (0)
- grant (1)
- 速查 (2)
- classloader (4)
- netty (4)
- 设计模式 (2)
- 缓存 (2)
- ehcache (2)
- framework (1)
- 内存分析 (2)
- dump (1)
- memory (2)
- 多高线程,并发 (1)
- hbase (2)
- 分布式系统 (1)
- socket (3)
- socket (1)
- 面试问题 (1)
- jetty (2)
- http (2)
- 源码 (1)
- 日志 (2)
- jni (1)
- 编码约定 (1)
- memorycache (1)
- redis (13)
- 杂谈 (1)
- drool (1)
- blockingqueue (1)
- ScheduledExecutorService (1)
- 网页爬虫 (1)
- httpclient (4)
- httpparser (1)
- map (1)
- 单例 (1)
- synchronized (2)
- thread (1)
- job (1)
- hashcode (1)
- copyonwriteArrayList (2)
- 录制声音 (1)
- java 标准 (2)
- SSL/TLS (1)
- itext (1)
- pdf (1)
- 钻石 (2)
- sonar (1)
- unicode (1)
- 编码 (4)
- html (1)
- SecurityManager (1)
- 坑 (1)
- Restful (2)
- svn hook (1)
- concurrentHashMap (1)
- 垃圾回收 (1)
- vbs (8)
- visual svn (2)
- power shell (1)
- wmi (3)
- mof (2)
- c# (1)
- concurrency (1)
- 劳动法 (1)
- 三国志游戏 (2)
- 三国 (1)
- 洪榕 (2)
- 金融投资知识 (1)
- motan (1)
- tkmybatis mapper (1)
- 工商注册信息查询 (1)
- consul (1)
- 支付业务知识 (2)
- 数据库备份 (1)
- 字段设计 (1)
- 字段 (1)
- dba (1)
- 插件 (2)
- PropEdit插件 (1)
- web工程 (1)
- 银行业知识 (2)
- 国内托管银行 (1)
- 数据库 (1)
- 事务 (2)
- git (18)
- component-scan (1)
- 私人 (0)
- db2 (14)
- alias (1)
- 住房 (1)
- 户口 (1)
- fastjson (1)
- test (6)
- RSA (2)
- 密钥 (1)
- putty (1)
- sftp (1)
- 加密 (1)
- 公钥私钥 (3)
- markdown (1)
- sweet (1)
- sourcetree (1)
- 好工具 (1)
- cmd (1)
- scp (1)
- notepad++ (1)
- ssh免密登录 (1)
- https (1)
- ssl (2)
- js (2)
- h2 (1)
- 内存 (2)
- 浏览器 (1)
- js特效 (1)
- io (1)
- 乱码 (1)
- 小工具 (1)
- 每周技术任务 (1)
- mongodb (7)
- 内存泄漏 (1)
- 码云 (2)
- 如何搭建java 视频服务器 tomcat (1)
- 资源 (1)
- 书 (1)
- 四色建模法 (1)
- 建模 (1)
- 配置 (1)
- 职位 (1)
- nginx (1)
- excel (1)
- log4j2 (2)
- 做菜 (1)
- jmap (1)
- jspwiki (1)
- activiti (1)
- 工作流引擎 (1)
- 安卓 (1)
- acitviti 例子 (1)
- 二维码 (1)
- 工作流 (1)
- powerdesign (2)
- 软件设计 (1)
- 乐观锁 (1)
- 王者荣耀 (1)
- session (2)
- token (5)
- cookie (4)
- springboot (24)
- jwt (2)
- 项目路径 (1)
- magicbook (1)
- requestType (1)
- json (2)
- swagger (1)
- eolinker (1)
- springdata (1)
- springmvc (1)
- controlleradvice (1)
- profile (1)
- 银行四要素 (1)
- 支付人员资源 (1)
- 支付渠道 (1)
- yaml (1)
- 中文编码 (1)
- mongo (2)
- serializable (1)
- 序列化 (1)
- zyd (1)
- unittest (1)
- 工具 (1)
- Something (1)
- 通达信 (1)
- protobuf (1)
- 算法 (1)
- springcloud (2)
- hikari (1)
- rocketmq (7)
- cachecloud (1)
- serfj (1)
- axure (1)
- lombok (1)
- 分布式锁 (1)
- 线程 (2)
- 同步代码块 (1)
- cobar (1)
- mq (1)
- rabbitmq (1)
- 定时执行 (1)
- 支付系统 (3)
- 唱歌 (1)
- elasticjob (1)
- 定时任务 (1)
- 界面 (1)
- flink (2)
- 大数据 (1)
- 接私活 (0)
- 内部培训 (2)
最新评论
-
dannyhz:
做股票从短线 试水,然后 慢慢发现 波段和 中期的故事可挖, ...
搭台唱戏 -
dannyhz:
http://developer.51cto.com/art/ ...
如何自己开发框架 它的注意点是什么
https://www.cnblogs.com/LiQ0116/p/7389049.html
一、业务背景
由于需要从A数据库提取大量数据同步到B系统,采用了tomikos+jta进行分布式事务管理,先将系统数据源切换到数据提供方,将需要同步的数据查询出来,然后再将系统数据源切换到数据接收方,进行批量的插入和更新操作,
关于数据源的切换可以参考之前的文章《spring+springMVC+Mybatis架构下采用AbstractRoutingDataSource、atomikos、JTA实现多数据源灵活切换以及分布式事务管理》
二、批量插入的具体实现
1.查询需要同步的数据:
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs(){
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
}
复制代码
2.将不能进行遍历的PO实体对象转为Map,此处有一个前提条件:MySQL中的表字段是按全大写加下划线命名,实体类PO映射字段为对应的标准驼峰命名方式,进行PO到Map
的转换时,会遵循这一规则。
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs() throws Exception{
//1.查询需要同步的数据
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
//2.将不能进行遍历的PO实体对象转为Map
//用于存放转换后的对象的List
List<Map<String,Object>> insertItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
Map<String,Object> insertItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
insertItems.add(insertItem);
}
}
复制代码
BeanMapUtil类,PO到Map的转换方法,基于类反射技术:
复制代码
import com.fms.common.utils.other.StringUtil;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
public class BeanMapUtil {
@SuppressWarnings({"unchecked", "rawtypes"})
public static Map convertBean2MapWithUnderscoreName(Object bean) throws Exception {
Map returnMap = null;
try {
Class type = bean.getClass();
returnMap = new HashMap();
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo
.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
PropertyDescriptor descriptor = propertyDescriptors[i];
String propertyName = descriptor.getName();
if (!propertyName.equalsIgnoreCase("class")) {
Method readMethod = descriptor.getReadMethod();
Object result = readMethod.invoke(bean, new Object[0]);
returnMap.put( StringUtil.underscoreName(propertyName), result);
}
}
} catch (Exception e) {
// 解析错误时抛出服务器异常 记录日志
throw new Exception("从bean转换为map时异常!", e);
}
return returnMap;
}
}
复制代码
StringUtil类,标准驼峰命名与数据库下划线命名之间转换的方法:
复制代码
public class StringUtil {
/**
* 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
* 例如:HelloWorld->HELLO_WORLD
*
* @param name 转换前的驼峰式命名的字符串
* @return 转换后下划线大写方式命名的字符串
*/
public static String underscoreName(String name) {
StringBuilder result = new StringBuilder();
if (name != null && name.length() > 0) {
// 将第一个字符处理成大写
result.append(name.substring(0, 1).toUpperCase());
// 循环处理其余字符
for (int i = 1; i < name.length(); i++) {
String s = name.substring(i, i + 1);
// 在大写字母前添加下划线
if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
result.append("_");
}
// 其他字符直接转成大写
result.append(s.toUpperCase());
}
}
return result.toString();
}
}
复制代码
3.编写Mybatis映射文件fmsDataDsMapper.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" >
<mapper namespace="com.fms.common.dao.fmsDataDsMapper">
<!-- 批量插入,传入表名和需要插入的数据的集合 -->
<insert id="insertDatas" parameterType="map">
insert into ${table_name}
<foreach collection="fields" index="field" item="fieldVal" separator="," open="(" close=")">
${field}
</foreach>
values
<foreach collection="list" index="index" item="record" separator="," >
<foreach collection="record" index="key" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</foreach>
</insert>
</mapper>
复制代码
4.调用sqlsession相关API的insert方法插入数据:
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs() throws Exception{
//1.查询需要同步的数据
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
//2.将不能进行遍历的PO实体对象转为Map
//用于存放转换后的对象的List
List<Map<String,Object>> insertItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
Map<String,Object> insertItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
insertItems.add(insertItem);
}
//3.插入数据
insertDatas(insertItems,"sys_person");
}
@Autowired
SqlSessionTemplate sqlSessionTemplate;
private String dataDsNameSpace = "com.fms.common.dao.fmsDataDsMapper";
private void insertDatas(List<Map<String,Object>> insertItems, String tableName){
if (!insertItems.isEmpty()) {
Map<String,Object> params = Maps.newHashMap();
//这里把数据分成每1000条执行一次,可根据实际情况进行调整
int count = insertItems.size() / 1000;
int yu = insertItems.size() % 1000;
for (int i = 0; i <= count; i++) {
List<Map<String,Object>> subList = Lists.newArrayList();
if (i == count) {
if(yu != 0){
subList = insertItems.subList(i * 1000, 1000 * i + yu);
}else {
continue;
}
} else {
subList = insertItems.subList(i * 1000, 1000 * (i + 1));
}
params.put("table_name", tableName);
params.put("fields", subList.get(0));
params.put("list", subList);
sqlSessionTemplate.insert(dataDsNameSpace+".insertDatas", params);
}
}
}
复制代码
三 、批量更新的具体实现
通常我们根据主键更新时的语句是 update table_name set column1 = val1 , column2 = val2 [,......] where id = ? 或者使用Mybatis提供的updateByPrimaryKey接口,
当我们希望一次性更新大量数据时,每条SQL只能执行一条更新,MySQL支持另外一种更新方式,让我们可以实现通过一条SQL语句一次性更新多条 根据主键更新的记录:
ON DUPLICATE KEY UPDATE
注意:这不同于在满足where条件时将某个table中的某一字段全部更新为同一各值,而是每条记录修改后的值都不一样。
1.构建需要更新的数据,需要注意的是如果PO中存在不想要更新的字段,你有两种处理方式,一种是将该字段的值在此处设为数据库中原来的值,另一种方式就是在进行Map转换时,
不将此字段构建到Map中,这只需要对convertBean2MapWithUnderscoreName方法做一些小的修改,你可以把不需要保留的字段作为参数传给它,然后在转换的时候过滤掉(主键不能省略)。
复制代码
//4.构建批量更新的数据
//用于存放转换后的对象的List
List<Map<String,Object>> updateItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
sysPersonPO.setCode(sysPersonPO.getCode()+"updateTest");
Map<String,Object> updatetItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
updateItems.add(updatetItem);
}
复制代码
2.编写Mybatis映射文件fmsDataDsMapper.xml
复制代码
<!-- 根据主键批量更新某个字段,传入表名和需要更新的数据的集合 -->
<insert id="updateDatas" parameterType="map">
INSERT INTO ${table_name}
<foreach collection="fields" index="field" item="fieldVal" separator="," open="(" close=")">
${field}
</foreach>
VALUES
<foreach collection="list" index="index" item="record" separator="," >
<foreach collection="record" index="key" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</foreach>
ON DUPLICATE KEY UPDATE
<foreach collection="fields" index="field" item="fieldVal" separator=",">
${field}=VALUES(${field})
</foreach>
</insert>
复制代码
3.更新数据
复制代码
//5.更新数据
updateDatas(updateItems,"sys_person");
private void updateDatas(List<Map<String,Object>> updateItems, String tableName){
if (!updateItems.isEmpty()) {
Map<String,Object> params = Maps.newHashMap();
//这里将数据分成每1000条执行一次,可根据实际情况调整
int count = updateItems.size() / 1000;
int yu = updateItems.size() % 1000;
for (int i = 0; i <= count; i++) {
List<Map<String,Object>> subList = Lists.newArrayList();
if (i == count) {
if(yu != 0){
subList = updateItems.subList(i * 1000, 1000 * i + yu);
}else {
continue;
}
} else {
subList = updateItems.subList(i * 1000, 1000 * (i + 1));
}
params.put("table_name", tableName);
params.put("fields", subList.get(0));
params.put("list", subList);
sqlSessionTemplate.insert(dataDsNameSpace+".updateDatas", params);
}
}
}
复制代码
引用
一、业务背景
由于需要从A数据库提取大量数据同步到B系统,采用了tomikos+jta进行分布式事务管理,先将系统数据源切换到数据提供方,将需要同步的数据查询出来,然后再将系统数据源切换到数据接收方,进行批量的插入和更新操作,
关于数据源的切换可以参考之前的文章《spring+springMVC+Mybatis架构下采用AbstractRoutingDataSource、atomikos、JTA实现多数据源灵活切换以及分布式事务管理》
二、批量插入的具体实现
1.查询需要同步的数据:
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs(){
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
}
复制代码
2.将不能进行遍历的PO实体对象转为Map,此处有一个前提条件:MySQL中的表字段是按全大写加下划线命名,实体类PO映射字段为对应的标准驼峰命名方式,进行PO到Map
的转换时,会遵循这一规则。
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs() throws Exception{
//1.查询需要同步的数据
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
//2.将不能进行遍历的PO实体对象转为Map
//用于存放转换后的对象的List
List<Map<String,Object>> insertItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
Map<String,Object> insertItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
insertItems.add(insertItem);
}
}
复制代码
BeanMapUtil类,PO到Map的转换方法,基于类反射技术:
复制代码
import com.fms.common.utils.other.StringUtil;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
public class BeanMapUtil {
@SuppressWarnings({"unchecked", "rawtypes"})
public static Map convertBean2MapWithUnderscoreName(Object bean) throws Exception {
Map returnMap = null;
try {
Class type = bean.getClass();
returnMap = new HashMap();
BeanInfo beanInfo = Introspector.getBeanInfo(type);
PropertyDescriptor[] propertyDescriptors = beanInfo
.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
PropertyDescriptor descriptor = propertyDescriptors[i];
String propertyName = descriptor.getName();
if (!propertyName.equalsIgnoreCase("class")) {
Method readMethod = descriptor.getReadMethod();
Object result = readMethod.invoke(bean, new Object[0]);
returnMap.put( StringUtil.underscoreName(propertyName), result);
}
}
} catch (Exception e) {
// 解析错误时抛出服务器异常 记录日志
throw new Exception("从bean转换为map时异常!", e);
}
return returnMap;
}
}
复制代码
StringUtil类,标准驼峰命名与数据库下划线命名之间转换的方法:
复制代码
public class StringUtil {
/**
* 将驼峰式命名的字符串转换为下划线大写方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。</br>
* 例如:HelloWorld->HELLO_WORLD
*
* @param name 转换前的驼峰式命名的字符串
* @return 转换后下划线大写方式命名的字符串
*/
public static String underscoreName(String name) {
StringBuilder result = new StringBuilder();
if (name != null && name.length() > 0) {
// 将第一个字符处理成大写
result.append(name.substring(0, 1).toUpperCase());
// 循环处理其余字符
for (int i = 1; i < name.length(); i++) {
String s = name.substring(i, i + 1);
// 在大写字母前添加下划线
if (s.equals(s.toUpperCase()) && !Character.isDigit(s.charAt(0))) {
result.append("_");
}
// 其他字符直接转成大写
result.append(s.toUpperCase());
}
}
return result.toString();
}
}
复制代码
3.编写Mybatis映射文件fmsDataDsMapper.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" >
<mapper namespace="com.fms.common.dao.fmsDataDsMapper">
<!-- 批量插入,传入表名和需要插入的数据的集合 -->
<insert id="insertDatas" parameterType="map">
insert into ${table_name}
<foreach collection="fields" index="field" item="fieldVal" separator="," open="(" close=")">
${field}
</foreach>
values
<foreach collection="list" index="index" item="record" separator="," >
<foreach collection="record" index="key" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</foreach>
</insert>
</mapper>
复制代码
4.调用sqlsession相关API的insert方法插入数据:
复制代码
@Autowired
SysPersonPOMapper sysPersonPOMapper;
public void dataDs() throws Exception{
//1.查询需要同步的数据
//根据具体情况可以创建查询条件或者采用自定义的Mapper进行查询
SysPersonPOExample sysPersonPOExample = new SysPersonPOExample();
sysPersonPOExample.createCriteria().andIsDeleteEqualTo(false);
//查询需要同步的数据
List<SysPersonPO> persons = sysPersonPOMapper.selectByExample(sysPersonPOExample);
//2.将不能进行遍历的PO实体对象转为Map
//用于存放转换后的对象的List
List<Map<String,Object>> insertItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
Map<String,Object> insertItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
insertItems.add(insertItem);
}
//3.插入数据
insertDatas(insertItems,"sys_person");
}
@Autowired
SqlSessionTemplate sqlSessionTemplate;
private String dataDsNameSpace = "com.fms.common.dao.fmsDataDsMapper";
private void insertDatas(List<Map<String,Object>> insertItems, String tableName){
if (!insertItems.isEmpty()) {
Map<String,Object> params = Maps.newHashMap();
//这里把数据分成每1000条执行一次,可根据实际情况进行调整
int count = insertItems.size() / 1000;
int yu = insertItems.size() % 1000;
for (int i = 0; i <= count; i++) {
List<Map<String,Object>> subList = Lists.newArrayList();
if (i == count) {
if(yu != 0){
subList = insertItems.subList(i * 1000, 1000 * i + yu);
}else {
continue;
}
} else {
subList = insertItems.subList(i * 1000, 1000 * (i + 1));
}
params.put("table_name", tableName);
params.put("fields", subList.get(0));
params.put("list", subList);
sqlSessionTemplate.insert(dataDsNameSpace+".insertDatas", params);
}
}
}
复制代码
三 、批量更新的具体实现
通常我们根据主键更新时的语句是 update table_name set column1 = val1 , column2 = val2 [,......] where id = ? 或者使用Mybatis提供的updateByPrimaryKey接口,
当我们希望一次性更新大量数据时,每条SQL只能执行一条更新,MySQL支持另外一种更新方式,让我们可以实现通过一条SQL语句一次性更新多条 根据主键更新的记录:
ON DUPLICATE KEY UPDATE
注意:这不同于在满足where条件时将某个table中的某一字段全部更新为同一各值,而是每条记录修改后的值都不一样。
1.构建需要更新的数据,需要注意的是如果PO中存在不想要更新的字段,你有两种处理方式,一种是将该字段的值在此处设为数据库中原来的值,另一种方式就是在进行Map转换时,
不将此字段构建到Map中,这只需要对convertBean2MapWithUnderscoreName方法做一些小的修改,你可以把不需要保留的字段作为参数传给它,然后在转换的时候过滤掉(主键不能省略)。
复制代码
//4.构建批量更新的数据
//用于存放转换后的对象的List
List<Map<String,Object>> updateItems = Lists.newArrayList();
for (SysPersonPO sysPersonPO : persons) {
sysPersonPO.setCode(sysPersonPO.getCode()+"updateTest");
Map<String,Object> updatetItem = BeanMapUtil.convertBean2MapWithUnderscoreName(sysPersonPO);
updateItems.add(updatetItem);
}
复制代码
2.编写Mybatis映射文件fmsDataDsMapper.xml
复制代码
<!-- 根据主键批量更新某个字段,传入表名和需要更新的数据的集合 -->
<insert id="updateDatas" parameterType="map">
INSERT INTO ${table_name}
<foreach collection="fields" index="field" item="fieldVal" separator="," open="(" close=")">
${field}
</foreach>
VALUES
<foreach collection="list" index="index" item="record" separator="," >
<foreach collection="record" index="key" item="item" separator="," open="(" close=")">
#{item}
</foreach>
</foreach>
ON DUPLICATE KEY UPDATE
<foreach collection="fields" index="field" item="fieldVal" separator=",">
${field}=VALUES(${field})
</foreach>
</insert>
复制代码
3.更新数据
复制代码
//5.更新数据
updateDatas(updateItems,"sys_person");
private void updateDatas(List<Map<String,Object>> updateItems, String tableName){
if (!updateItems.isEmpty()) {
Map<String,Object> params = Maps.newHashMap();
//这里将数据分成每1000条执行一次,可根据实际情况调整
int count = updateItems.size() / 1000;
int yu = updateItems.size() % 1000;
for (int i = 0; i <= count; i++) {
List<Map<String,Object>> subList = Lists.newArrayList();
if (i == count) {
if(yu != 0){
subList = updateItems.subList(i * 1000, 1000 * i + yu);
}else {
continue;
}
} else {
subList = updateItems.subList(i * 1000, 1000 * (i + 1));
}
params.put("table_name", tableName);
params.put("fields", subList.get(0));
params.put("list", subList);
sqlSessionTemplate.insert(dataDsNameSpace+".updateDatas", params);
}
}
}
复制代码
发表评论
-
spring mvc的工作原理 有图很清晰
2018-09-29 11:01 380引用 https://www.cnblogs.com/xiao ... -
spring property loader的 placeholder的详细分析
2018-09-29 10:59 400引用 https://blog.csdn.net/liuxin ... -
对于spring controller的详细分析和使用指导
2018-09-29 10:58 400引用 https://www.cnblogs.com/lcs- ... -
简单servlet spring 已经mvc controller
2018-09-28 20:42 323引用 https://blog.csdn.net/liuxin ... -
mybatis 中 selectkey的作用
2018-09-21 19:07 591引用 https://blog.csdn.net/czd335 ... -
@value 的详解
2018-08-23 19:07 434引用 http://www.cnblogs.com/kings ... -
关于 多个值不同的处理 比如channelid 为空和非空的处理
2018-07-21 16:00 1966引用 <update id="update& ... -
mybatis调用查询日期
2018-07-19 22:42 572引用 dao: List<Date> getLa ... -
mybatis 对string类型判断比较 group case when then 综合
2018-07-19 20:57 1050引用 特别注意两点 一个是where 的用法 group的用 ... -
spring mvc ,spring boot里面的关于 global exception handle , controller advice的解释
2018-07-18 12:43 587引用 https://blog.csdn.net/kingin ... -
mybatis plus的文档
2018-07-11 19:31 528引用 http://mp.baomidou.com/#/qui ... -
springboot mybatis详解
2018-07-11 19:30 362引用 https://blog.csdn.net/mickjo ... -
关于spring 的json的传递 yixiaoping
2018-06-29 22:01 248https://blog.csdn.net/**/articl ... -
github 下载具体版本的 spring
2018-06-06 22:02 388引用https://blog.csdn.net/bbc2005 ... -
tomcat 到 servlet 到 spring servlet dispatcher的一串
2018-05-30 21:57 610引用 五月 30, 2018 9:31:35 下午 org. ... -
mybatis对乐观锁的 支持例子
2018-05-28 20:45 668引用 https://blog.csdn.net/zhouz ... -
mybatis timeout = 60 加上一个时间 可以让sql时间更长
2018-04-13 19:46 1171引用 <select id="fi ... -
mybatis 的分段插入大量数据的完整方法
2018-04-10 18:33 717https://blog.csdn.net/java_mr_z ... -
前三句可以打印 mybatis log
2018-03-25 21:46 456引用 @Test public void test( ... -
mybatis 转义字符
2018-03-22 20:13 485引用 <= <= ...
相关推荐
在C#编程中,批量插入数据是数据库操作中常见的需求,尤其在处理大量数据时,为了提高效率,避免频繁的数据库交互,批量插入是必不可少的技巧。本篇将详细讲解如何在C#中实现批量插入数据,以及涉及的相关知识点。 ...
本文将介绍三种批量插入数据的方法。第一种方法是使用循环语句逐个将数据项插入到数据库中;第二种方法使用的是SqlBulkCopy,使您可以用其他源的数据有效批量加载 SQL Server 表;第三种使用的方法是sql server中的...
本文将深入探讨如何使用JDBC进行批量插入数据,这在处理大量数据时能显著提高性能。 批量插入数据是数据库操作中常见的一种优化策略,特别是在数据分析、数据迁移或大数据处理等场景。传统的单条插入方式可能会导致...
本教程将详细讲解如何进行批量插入数据到Oracle数据库,以提高数据导入的效率。 批量插入数据到Oracle数据库通常比单条插入更有效率,因为它减少了与数据库的交互次数,降低了网络延迟,并减少了系统资源的占用。...
当我们需要快速填充大量的测试数据或初始化数据库时,批量插入数据软件就显得尤为实用。本篇将详细阐述如何使用一款专业的数据库智能创建数据软件,它具备自动导入百万条数据的能力,并且允许用户自定义数据格式,...
oracle 批量插入数据存储过程。亲测好用。支持 plsql ,toad,等数据库分析软件。主要包括变量的定义,循环及游标的使用等, 亲测好用
考虑到当Excel数据量较大时,循环Insert语句效率太低,故采用批量插入的方法。在插入操作运行时,会造成系统短暂的“卡死”现象。为了让用户知道插入的状态,需要制作一个进度条来显示插入的进度。 批量插入 项目中...
本文将深入探讨如何利用`JdbcDaoSupport`进行批量插入数据的操作,以及其背后的原理和源码分析。 首先,`JdbcDaoSupport`是`AbstractJdbcDaoSupport`的子类,它提供了对JDBC访问的便捷封装,允许开发者无需直接管理...
5. **批量插入数据到数据库** 在数据处理过程中,往往还需要将数据批量插入到数据库。EasyExcel提供了一个`executeBatchInsert`方法,可以配合JDBC或其他ORM框架如MyBatis,将数据批量插入到数据库。首先,我们需要...
本压缩包“Delphi批量插入数据库数据”可能包含了一个或多个示例代码,用于演示如何在Delphi中高效地向数据库批量插入数据。 批量插入数据是数据库操作中的常见需求,尤其是在处理大量数据时,为了提高效率和减少...
在ASP(Active Server Pages)开发中,批量插入数据是一个常见的需求,特别是在处理大量记录时,为了提高效率,避免频繁的数据库交互,批量插入是必不可少的技术。本文将详细讲解如何在ASP中实现批量插入数据,以及...
本篇文章将详细介绍如何利用Java和MyBatis实现批量插入数据到Oracle数据库中。 首先,我们需要理解Oracle数据库的一些基本概念。Oracle是世界上最流行的商业关系型数据库管理系统之一,以其强大的功能和高可靠性而...
这款工具专为数据库管理员和开发人员设计,用于快速、高效地向ACCESS和SQL Server数据库中批量插入数据,尤其在进行负荷测试时,它能显著提高工作效率。 首先,我们来了解一下ACCESS。ACCESS是Microsoft Office套件...
支持批量插入的Delphi数据输入程序,配合数据实现的数据批量输入程序,程序的原型是一个学生管理程序,用来输入学生的基本信息,本程序添加了批量插入数据的功能,可看作是一个批量插入数据的实例吧。相关的代码: ...
在.NET框架中,C#提供了一个非常强大的工具——SqlBulkCopy类,用于高效地将大量数据从一个数据源批量插入到SQL Server数据库中。相比于传统的单条INSERT INTO语句,SqlBulkCopy在处理大规模数据导入时能显著提高...
在本文档中,我们将深入探讨如何使用Java API与HBase数据库进行交互,特别是关于如何创建表、修改表结构以及批量插入数据。HBase是Apache的一个分布式、可扩展的大数据存储系统,它基于谷歌的Bigtable设计,适用于...
最近跟客户做数据对接比较多,发现平常的添加到数据库数据太慢,所以也没少逛论坛。结合论坛上的资料封装...插入数据库数据请使用SqlBackCopy。下载过的朋友我这个帖子行或者不行麻烦给在下评论下,希望能帮更多的人。
在批量插入数据的场景下,可以创建一个CountDownLatch对象,初始化为线程的数量,每个线程处理完自己的数据后调用`countDown()`方法,主线程通过调用`await()`方法等待所有线程完成后再执行后续操作,如提交事务。...
你需要先创建存储过程,然后调用...存储过程可以通过循环批量插入数据,提高代码的重用性和可维护性。 这样的好处:逻辑封装:复杂的插入逻辑可以封装在存储过程内,易于管理。 灵活性:可以根据参数动态调整插入行为。
然而,随着数据量的增长,批量插入数据的效率变得至关重要。"android sqlite 批量插入数据优化代码"这个主题正是针对这一需求,探讨如何高效地在SQLite数据库中进行大量数据的插入操作。 首先,我们要理解SQLite的...