mybatis 使用经验小结,batch批量提交大量数据

MyBatis的性能优化——批量操作 批量操作是数据处理场景中的性能关键点,尤其在数据迁移、报表生成等大数据量场景下,优化效果可提升10倍以上性能。 阅读详情
AI摘要

本文详细介绍MyBatis在实际项目中的高级应用技巧,包括多数据源配置、使用Map作为参数进行动态SQL生成、兼容不同数据库特性、批量插入优化等,并提供具体实现代码示例。

一、多数据源问题

主要思路是把dataSource、sqlSesstionFactory、MapperScannerConfigurer在配置中区分开,各Mapper对应的包名、类名区分开

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
 4        xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
 5        xmlns:context="http://www.springframework.org/schema/context"
 6        xsi:schemaLocation="
 7      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
 8      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 9      http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
10      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
11      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
12        default-autowire="byName">
13 
14     <bean id="dataSource1" class="org.h2.jdbcx.JdbcConnectionPool"
15           destroy-method="dispose">
16         <constructor-arg>
17             <bean class="org.h2.jdbcx.JdbcDataSource">
18                 <property name="URL" value="jdbc:h2:r:/h2db/awbprint/a"/>
19                 <property name="user" value="sa"/>
20                 <property name="password" value="sa"/>
21             </bean>
22         </constructor-arg>
23     </bean>
24 
25 
26     <bean id="dataSource2" class="org.h2.jdbcx.JdbcConnectionPool"
27           destroy-method="dispose">
28         <constructor-arg>
29             <bean class="org.h2.jdbcx.JdbcDataSource">
30                 <property name="URL" value="jdbc:h2:r:/h2db/awbprint/b"/>
31                 <property name="user" value="sa"/>
32                 <property name="password" value="sa"/>
33             </bean>
34         </constructor-arg>
35     </bean>
36 
37     <bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
38         <property name="dataSource" ref="dataSource1"/>
39         <property name="configLocation" value="classpath:mybatis-config.xml"></property>
40         <property name="typeAliasesPackage" value="awbprint.mybatis.entity"></property>
41         <property name="mapperLocations" value="classpath:mybatis/a/**/*.xml"></property>
42     </bean>
43 
44     <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
45         <property name="dataSource" ref="dataSource2"/>
46         <property name="configLocation" value="classpath:mybatis-config.xml"></property>
47         <property name="typeAliasesPackage" value="awbprint.mybatis.entity"></property>
48         <property name="mapperLocations" value="classpath:mybatis/b/**/*.xml"></property>
49     </bean>
50 
51     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
52         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory1"></property>
53         <property name="basePackage" value="awbprint.mybatis.mapper.a"/>
54     </bean>
55 
56     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
57         <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"></property>
58         <property name="basePackage" value="awbprint.mybatis.mapper.b"/>
59     </bean>
60 
61 
62 </beans>
复制代码

上面的配置,一个连h2的a数据库,一个连h2的b数据库,至于事务管理器,大家可参考这个思路,建二个,各管各的。

项目中mapper接口及映射文件均用包名区分开,如下图:

 

二、如何使用Map做为参数及动态条件生成

复制代码
 1     <resultMap id="BaseResultMap" type="awbprint.mybatis.entity.PrintLayout">
 2         <id column="D_RECID" property="recid" jdbcType="DECIMAL"/>
 3         <result column="D_USER_NAME" property="userName" jdbcType="VARCHAR"/>
 4         <result column="D_NAME" property="name" jdbcType="VARCHAR"/>
 5         <result column="D_TYPE" property="type" jdbcType="VARCHAR"/>
 6         ...
 7        
 8     </resultMap>
 9 
10    <sql id="Base_Column_List">
11         D_RECID, D_USER_NAME, D_NAME, D_TYPE, ...
12     </sql>
13 
14     <select id="select" resultMap="BaseResultMap"
15             parameterType="java.util.Map">
16         select
17         <include refid="Base_Column_List"/>
18         from T_PRINT_LAYOUT
19         where D_USER_NAME = #{userName,jdbcType=VARCHAR} and D_TYPE = #{awbType,jdbcType=VARCHAR}
20         <if test="recId != null">
21             and D_RECID = #{recId,jdbcType=DECIMAL}
22         </if>
23         <if test="ids != null">
24             or D_RECID in
25             <foreach item="item" index="index" collection="ids"
26                      open="(" separator="," close=")">
27                 #{item}
28             </foreach>
29         </if>
30 
31     </select>
复制代码

14-31演示了如何使用Map做为参数,动态传入查询条件,及List参数生成in(...)条件

java端代码示例:

复制代码
 1         PrintLayoutMapper mapper = context.getBean(PrintLayoutMapper.class);
 2         
 3         Map<String, Object> map = new HashMap<String, Object>();
 4         map.put("userName", "ADMIN");
 5         map.put("awbType", "CARGOLABEL_MU");
 6         map.put("recId", 1);
 7         
 8         List<Integer> ids = new ArrayList<Integer>();
 9         ids.add(0, 1);
10         ids.add(0, 2);
11         ids.add(0, 3);
12         
13         map.put("ids", ids);
14 
15         List<?> list = mapper.select(map);
复制代码

其实PrintLayoutMapper接口的定义为:

1 public interface PrintLayoutMapper {    
2     ...
3     
4     List<PrintLayout> select(Map<String, Object> map);
5 }

最终生成的SQL语句为:

1 select D_RECID, D_USER_NAME, D_NAME, D_TYPE, ... from T_PRINT_LAYOUT where D_USER_NAME = ? and D_TYPE = ? and D_RECID = ? or D_RECID in ( ? , ? , ? )

 

三、兼容不同的数据库

复制代码
 1 <insert id="insert">
 2  <selectKey keyProperty="id" resultType="int" order="BEFORE">
 3  <if test="_databaseId == 'oracle'">
 4  select seq_users.nextval from dual
 5  </if>
 6  <if test="_databaseId == 'db2'">
 7  select nextval for seq_users from sysibm.sysdummy1"
 8  </if>
 9  </selectKey>
10  insert into users values (#{id}, #{name})
11 </insert>
复制代码

这是官方文档上的示例,演示了如何兼容oracle与db2这二种不同的数据库,来获取序列的下一个值

 

四、加强版的分支、选择判断

复制代码
 1 <select id="findActiveBlogLike"
 2  resultType="Blog">
 3  SELECT * FROM BLOG WHERE state = ‘ACTIVE’
 4  <choose>
 5  <when test="title != null">
 6  AND title like #{title}
 7  </when>
 8  <when test="author != null and author.name != null">
 9  AND author_name like #{author.name}
10  </when>
11  <otherwise>
12  AND featured = 1
13  </otherwise>
14  </choose>
15 </select>
复制代码

这也是官方文档上的示例,因为<if>...</if>并没对应的<else>标签,所以要达到<if>...<else>...</else> </if>的效果,得借助<choose>、<when>、<otherwise>组合使用。

 

五、避免Where 空条件的尴尬

复制代码
1 <select id="findActiveBlogLike" resultType="Blog">
2  SELECT * FROM BLOG
3  WHERE
4  <if test="state != null">
5  state = #{state}
6  </if> 
7 </select>
复制代码

如果state参数为空时,最终生成SQL语句为 

1  SELECT * FROM BLOG
2  WHERE

执行会出错,当然,你可以在where 后加一个1=1,改成

复制代码
1 <select id="findActiveBlogLike" resultType="Blog">
2  SELECT * FROM BLOG
3  WHERE 1=1
4  <if test="state != null">
5  and state = #{state}
6  </if> 
7 </select>
复制代码

但是这个做法不太“环保”(毕竟引入了一个垃圾条件),其实只要改成<where>...</where>即可

复制代码
1 <select id="findActiveBlogLike" resultType="Blog">
2  SELECT * FROM BLOG
3  <where>
4      <if test="state != null">
5          and state = #{state}
6      </if>
7  </where> 
8 </select>
复制代码

 

六、$与#的区别

1  select * from T_PRINT_LAYOUT where  D_RECID = ${recId}

最后生成的SQL为:

1 select * from T_PRINT_LAYOUT where  D_RECID = 1

即:直接将参数值替换到了原来${recId}的位置,相当于硬拼SQL

 

1  select * from T_PRINT_LAYOUT where  D_RECID = #{recid,jdbcType=DECIMAL}

最后生成的SQL为:

1 select * from T_PRINT_LAYOUT where  D_RECID = ?

即:#{...}被识别为一个SQL参数

 

七、大量数据的批量insert

大量数据(条数>10000)做insert时,如果按常规方式,每条insert into table(...) values(...);来提交,速度巨慢。改善性能的思路是多条insert批量提交。

oracle环境中,有一种批量insert的小技巧,原理是 insert into ... select from ...,套在mybatis上,变形为:

复制代码
 1 INSERT INTO T_TEST
 2   (ID, COL_A, COL_B)
 3   SELECT SEQ_TEST.NEXTVAL, A.*
 4     FROM (
 5               SELECT 'A1', 'B1' FROM DUAL
 6     UNION ALL SELECT 'A2', 'B2' FROM DUAL
 7     UNION ALL SELECT 'A3', 'B3' FROM DUAL
 8     UNION ALL SELECT 'A4', 'B4' FROM DUAL
 9     UNION ALL SELECT 'A5', 'B5' FROM DUAL
10     UNION ALL SELECT 'A6', 'B6' FROM DUAL
11     ) A
复制代码

中间的部分非常有规律,可以用foreach标签生成,参考下面的片段:

复制代码
 1 <insert id="insertBatch2" parameterType="ctas.entity.SharkFlt">
 2     <selectKey keyProperty="recId" order="BEFORE" resultType="Long">
 3       select SEQ_CTAS_SHARK_FLT.nextval as recId from dual
 4     </selectKey>
 5     insert into CTAS_SHARK_FLT (<include refid="Base_Column_List"/>) SELECT SEQ_TEST.NEXTVAL, A.*
 6     FROM (
 7     <foreach collection="list" item="item" index="index" open="" close="" separator="union all">
 8       select #{item.awbType,jdbcType=VARCHAR}, #{item.awbPre,jdbcType=VARCHAR},... from dual
 9     </foreach>
10     ) A
11   </insert>
复制代码

即使这样,也不能直接run,oracle中一次执行的sql语句长度是有限制的,如果最后拼出来的sql字符串过长,会导致执行失败,所以java端还要做一个分段处理,参考下面的处理:

复制代码
 1         List<SharkFlt> data = new ArrayList<SharkFlt>();
 2         for (TSharkFlt f : sharkFlts) {
 3             data.add(getSharkFlt(f));
 4         }
 5 
 6         System.out.println(data.size());
 7 
 8         long beginTime = System.currentTimeMillis();
 9         System.out.println("开始插入...");
10         SqlSessionFactory sqlSessionFactory = ctx.getBean(SqlSessionFactory.class);
11         SqlSession session = null;
12         try {
13             session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
14             int a = 2000;//每次提交2000条
15             int loop = (int) Math.ceil(data.size() / (double) a);
16 
17             List<SharkFlt> tempList = new ArrayList<SharkFlt>(a);
18             int start, stop;
19             for (int i = 0; i < loop; i++) {
20                 tempList.clear();
21                 start = i * a;
22                 stop = Math.min(i * a + a - 1, data.size() - 1);
23                 System.out.println("range:" + start + " - " + stop);
24                 for (int j = start; j <= stop; j++) {
25                     tempList.add(data.get(j));
26                 }
27                 session.insert("ctas.importer.writer.mybatis.mappper.SharkFltMapper.insertBatch2", tempList);
28                 session.commit();
29                 session.clearCache();
30                 System.out.println("已经插入" + (stop + 1) + " 条");
31             }
32         } catch (Exception e) {
33             e.printStackTrace();
34             session.rollback();
35         } finally {
36             if (session != null) {
37                 session.close();
38             }
39         }
40         long endTime = System.currentTimeMillis();
41         System.out.println("插入完成,耗时 " + (endTime - beginTime) + " 毫秒!");
复制代码

13,27-29这几行是关键,这一段逻辑会经常使用,为了重用,可以封装一下:

复制代码
 1     /**
 2      * 批量提交数据
 3      * @param sqlSessionFactory
 4      * @param mybatisSQLId SQL语句在Mapper XML文件中的ID
 5      * @param commitCountEveryTime 每次提交的记录数
 6      * @param list 要提交的数据列表
 7      * @param logger 日志记录器
 8      */
 9     private <T> void batchCommit(SqlSessionFactory sqlSessionFactory, String mybatisSQLId, int commitCountEveryTime, List<T> list, Logger logger) {
10         SqlSession session = null;
11         try {
12             session = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
13             int commitCount = (int) Math.ceil(list.size() / (double) commitCountEveryTime);
14             List<T> tempList = new ArrayList<T>(commitCountEveryTime);
15             int start, stop;
16             Long startTime = System.currentTimeMillis();
17             for (int i = 0; i < commitCount; i++) {
18                 tempList.clear();
19                 start = i * commitCountEveryTime;
20                 stop = Math.min(i * commitCountEveryTime + commitCountEveryTime - 1, list.size() - 1);
21                 for (int j = start; j <= stop; j++) {
22                     tempList.add(list.get(j));
23                 }
24                 session.insert(mybatisSQLId, tempList);
25                 session.commit();
26                 session.clearCache();
27             }
28             Long endTime = System.currentTimeMillis();
29             logger.debug("batchCommit耗时:" + (endTime - startTime) + "毫秒");
30         } catch (Exception e) {
31             logger.error("batchCommit error!", e);
32             e.printStackTrace();
33             session.rollback();
34         } finally {
35             if (session != null) {
36                 session.close();
37             }
38         }
39     }
复制代码

对应的,如果是批量update,也是类似的思路,只不过要注意一点:oracle环境中,多条语句提交的sql语句为

begin

  update xxx set xxx =xxx ;

  update xxx set xxx =xxx;

end;

用mytais拼的时候,参考下面的写法:

1   <update id="updateBatch" parameterType="java.util.List">
2     <foreach collection="list" item="item" index="index" open="begin" close="end;" >
3       update xxx set x=#{item.x,jdbcType=VARCHAR} where x =#{item.x,jdbcType=VARCHAR};
4     </foreach>
5   </update>

关于批量提交的性能,Oracle环境下,我大概测试了一下:

insert into ... select xxx

  union all select yyy

  union all select zzz;

最快,其次是

begin

  insert into ... values  ...;

  insert into ... values ...;

end;

当然最慢是逐条insert提交,最后谈下Spring与mybatis集成后,AOP事务管理 对 批量提交的影响 ,通常情况下,我们会这样配置AOP事务管理:

复制代码
 1     <tx:advice id="txAdvice" transaction-manager="transactionManager">
 2         <tx:attributes>
 3             <tx:method name="do*" read-only="false" rollback-for="java.lang.Exception"/>
 4             <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
 5         </tx:attributes>
 6     </tx:advice>
 7 
 8     <aop:config>
 9         <aop:pointcut id="pc" expression="execution(* ctas.service.*.*(..))"/>
10         <aop:advisor pointcut-ref="pc" advice-ref="txAdvice"/>
11     </aop:config>
复制代码

这样,ctas.service(及子包)下的所有方法都被拦截,而且只有do开头的方法,具有可写的事务(即:能insert/update/delete记录),而其它方法是只读事务(即:只能select数据),但是我们前面谈到的批量提交操作,都是写代码手动提交的,不需要spring管理,所以配置中需要将某些方法排除,可以约定self开头的方法,由开发者自己管理事务,不需要spring代为管理,上面的配置要改成:

1     <aop:config>
2         <aop:pointcut id="pc" expression="execution(* ctas.service.*.*(..)) and !execution(* ctas.service.*.self*(..)))"/>
3         <aop:advisor pointcut-ref="pc" advice-ref="txAdvice"/>
4     </aop:config>

 通过 and !execution(...) 将self开头的方法排除就可以了,前面的批量操作代码写到selfXXX方法中。

 

关于批量提交,还有一种情况:父子表的批量插入。思路还是一样的,但是SQL的写法有点区别,原理参考下面的语句(Oracle环境)

复制代码
 1 DECLARE
 2   BASE_ID   INTEGER;
 3   DETAIL_ID INTEGER;
 4 BEGIN
 5   --第1组记录
 6   SELECT SEQ_T_BASE.NEXTVAL INTO BASE_ID FROM DUAL;
 7   INSERT INTO T_BASE (ID, FEE) VALUES (BASE_ID, ?);
 8   
 9   SELECT SEQ_T_DETAIL.NEXTVAL INTO DETAIL_ID FROM DUAL;
10   INSERT INTO T_DETAIL (ID, BASE_ID, FEE) VALUES (DETAIL_ID, BASE_ID, ?);
11   SELECT SEQ_T_DETAIL.NEXTVAL INTO DETAIL_ID FROM DUAL;
12   INSERT INTO T_DETAIL (ID, BASE_ID, FEE) VALUES (DETAIL_ID, BASE_ID, ?);
13   
14   --第2组记录
15   SELECT SEQ_T_BASE.NEXTVAL INTO BASE_ID FROM DUAL;
16   INSERT INTO T_BASE (ID, FEE) VALUES (BASE_ID, ?);
17   
18   SELECT SEQ_T_DETAIL.NEXTVAL INTO DETAIL_ID FROM DUAL;
19   INSERT INTO T_DETAIL (ID, BASE_ID, FEE) VALUES (DETAIL_ID, BASE_ID, ?);
20   SELECT SEQ_T_DETAIL.NEXTVAL INTO DETAIL_ID FROM DUAL;
21   INSERT INTO T_DETAIL (ID, BASE_ID, FEE) VALUES (DETAIL_ID, BASE_ID, ?);
22   
23   --...
24 END;
复制代码

 

xml映射文件中的写法:

复制代码
 1     <insert id="insertBatch" parameterType="java.util.List">
 2         DECLARE
 3         base_id INTEGER ;
 4         detail_id INTEGER ;
 5         <foreach collection="list" item="item" index="index" open="begin" close="end;">
 6             select seq_t_base.nextval into base_id from dual;
 7             insert into t_base(id, fee) values(base_id, #{item.baseEntity.fee,jdbcType=DECIMAL});
 8             <foreach collection="item.details" item="detail" index="index">
 9                 select seq_t_detail.nextval into detail_id from dual;
10                 insert into t_detail(id, base_id, fee) values(detail_id,base_id,#{detail.fee,jdbcType=DECIMAL});
11             </foreach>
12         </foreach>
13     </insert>
复制代码

 List中的Dto定义

复制代码
 1 public class BaseDetailDto {
 2 
 3     private TBase baseEntity;
 4 
 5     private List<TDetail> details;
 6 
 7     public TBase getBaseEntity() {
 8         return baseEntity;
 9     }
10 
11     public void setBaseEntity(TBase baseEntity) {
12         this.baseEntity = baseEntity;
13     }
14 
15 
16     public List<TDetail> getDetails() {
17         return details;
18     }
19 
20     public void setDetails(List<TDetail> details) {
21         this.details = details;
22     }
23 }
复制代码

 

作者: 菩提树下的杨过
出处: http://yjmyzz.cnblogs.com 
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
MyBatis批量插入几千条数据慎用foreach     近日,项目中有一个耗时较长的Job存在CPU占用过高的问题,经排查发现,主要时间消耗在往MyBatis中批量插入数据。mapper configuration是用foreach循环做的,差不多是这样。(由于项目保密,以下代码均为自己手写的demo代码) &lt;insert id="batchInsert" parameterType="java.util.List"&gt; ... 阅读详情

相关推荐

MyBatis批处理使用过程中需要注意的那些坑

MyBatis 批处理虽然强大,但在使用中需要注意以下关键点: 分批次提交,避免内存溢出。 显式提交和回滚,确保数据一致性。 每个线程使用独立的 SqlSession,避免多线程问题。 优化数据库连接和驱动,提升批处理性能。 处理部分提交和主键冲突,确保业务逻辑正确。

qq_29781527的博客 1070

MyBatis---BATCH批量提交数据

当需要更新数据库里大量数据时,可以用MyBatis里BATCH来批量提交数据,这样可以节省时间。

zhiwenganyong的博客 7921

基于mybatis batch实现批量提交大量数据

主要介绍了基于mybatis batch实现批量提交大量数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

Mybatis批量提交

目录一、通过foreach标签二、通过Mybatis的ExecutorType.BATCH方式 有两种方式可以实现mybatis的批量提交,第一种便是foreach标签,第二种便是开始mybatis的批量模式。 一、通过foreach标签 foreach标签即是通过迭代传入的集合或者数组,进行拼接sql。 标签包含以下属性: ​ item:表示集合中每一个元素进行迭代时的别名 ​ index:表示...

淋雨一直走啊 7597

MyBatis通过BATCH批量提交的方法

今天小编就为大家分享一篇关于MyBatis通过BATCH批量提交的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

PSIM仿真实战:反激电源从设计到调试的完整流程(附短路保护配置)

本文详细介绍了使用PSIM仿真工具进行反激电源从设计到调试的完整流程,包括变压器参数设计、功率器件选型、动态特性调试以及短路保护配置。通过实战案例和仿真技巧,帮助工程师提前暴露并解决设计中的常见问题,如负载突变、输入电压波动和短路保护失效等,显著降低硬件试错成本。

weixin_29216353的博客 244

关于Mybatis批量插入使用JDBC原生batch批处理以及mybatis的ExecutorType.BATCH的批处理和Mybatis的动态sql语句批处理

近期处理数据,总结一下 项目背景:从Mongo中定时转移前第7天文本到mysql数据库且生成文件,有各种不同的定时任务,有批次消息、发送明细消息等等很多的数据需要转移,也有老系统和新系统数据的转移,mysql使用的分区表;架构使用的ssm,定时任务使用的xxl-job分布式任务调度 上面都是废话; 1、JDBC原生batch处理400万条数据 /** * @Descriptio...

qq_40144558的博客 7754

RDMA性能调优实战:如何用ib_*命令榨干你的Mellanox网卡带宽?

本文深入探讨了如何利用ib_*命令工具集对RDMA网络进行深度性能调优,以充分释放Mellanox网卡的带宽潜力。文章从理解Send/Write/Read三种核心通信原语的差异入手,逐步指导读者通过调整消息大小、队列深度、内联数据等关键参数,并结合系统级的NUMA绑定、中断亲和性等优化策略,实现从基准测试到逼近硬件极限的性能提升。

weixin_29306011的博客 88

Mybatis批量插入大量数据最优方式

mybatis

blueheartstone的博客 3万+

本地使用大模型:Ollama+open-webui+AnythingLLM(Windows+linux)

随着大模型的发展,大量的开源模型可以被直接使用。大模型的使用可以选择在云端或者在本地,如果本地存储空间尚可,而且模型需求不是很大的话,我们可以选择在本地部署一个大模型来使用。针对特定的任务需求,进一步在本地去微调我们的大模型。我在windows和linux上都尝试了一遍,这里记录一下过程。

wpqgt的博客 2166

专栏丨华为HN8145XR光猫获取超级管理员密码

摘要:本文详细介绍了华为HN8145xr光猫获取超级管理员权限的完整步骤。首先通过ONT使能工具补全shell,然后利用Telnet登录光猫后台进行操作。文章提供了多种获取超级密码的方法,包括配置文件解密、一键查询工具等,并针对联通光猫特别说明了默认密码格式(CUAdmin+后八位数字)。此外,还介绍了恢复出厂设置、修改SSID等实用操作,帮助用户完全掌控光猫设备。文末附有详细的命令行操作指南,适合有一定技术基础的用户参考。

8280

mybatis批量插入优化(ExecutorType.BATCH/BatchInsert/executeBatch)

Mybatis内置的有3种,默认的是simple单句模式,该模式下它为每个语句的执行创建一个新的预处理语句,单句提交sql;batch模式重复使用已经预处理的语句,并且批量执行所有语句,大批量模式下性能更优。请注意batch模式在Insert操作时事务没有提交之前,是没有办法获取到自增的id,所以请根据业务情况使用。使用simple模式提交10000条数据,时间为19s,batch模式为6s ,大致情况如此,优化的具体还要看提交的语句情况。如果需要使用foreach。

★【World Of Moshow 郑锴】★ 3万+

【总目录】AUTOSAR精进之路专栏介绍及内容目录持续更新...

本专栏系统讲解AUTOSAR汽车电子开发技术,包含Eth/OS/Can/Lin等协议栈、MCAL驱动、功能安全等核心模块。内容基于实际项目经验,从概念原理到工程配置、特殊需求实现及问题排查进行深入剖析。重点涵盖TC3xx芯片平台开发、多核OS、网络管理、存储协议栈等难点问题,提供100+篇原创技术文章。专栏采用付费模式,保证内容完整性和持续更新,并提供专业答疑服务。适合汽车电子工程师系统学习AUTOSAR开发技术。

qq_36056498的博客 6517

MyBatis批量插入大量数据(1w以上)--解决方案

echo编辑整理,欢迎转载,转载请声明文章来源。欢迎添加echo微信(微信号:t2421499075)交流学习。 百战不败,依不自称常胜,百败不颓,依能奋力前行。——这才是真正的堪称强大!!! 问题背景:只用MyBatis中foreach进行批量插入数据,一次性插入超过一千条的时候MyBatis开始报错。项目使用技术:SpringBoot、MyBatis 批量插入碰到的问题: java.la...

xlecho的博客 3万+

OpenOCD入门到精通:第 1 章 OpenOCD 概述

OpenOCD是一款开源的片上调试工具,支持60+调试适配器和8大处理器架构。它提供三大核心功能:片上调试、在系统编程和边界扫描测试。作为嵌入式开发工具链的中间桥梁,OpenOCD连接上层IDE/GDB与底层硬件,采用分层架构设计实现硬件兼容性。其配置基于Tcl脚本语言,支持网络服务接口,广泛应用于ARM、RISC-V等芯片的调试与烧录场景。

从事嵌入式linux android驱动开发,拥有全栈能力 1402

eNSP常见故障处理

eNSP无法启动设备一直停在#井号的问题的解决方案?

lvshiliang123的博客 2万+

jdbc,mybatis中fetchsize使用,批处理方案

数据库优化之查询优化,fetchsize使用,常用sql

FOREVER_DO 2万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Mybatis优化:使用batch模式实现批量插入/更新

Mybatis批量插入优化

manba_out的博客 1万+

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

MyBatis批量插入大量数据

1. 思路分析 批量插入这个问题,我们用 JDBC 操作,其实就是两种思路吧: 用一个 for 循环,把数据一条一条的插入(这种需要开启批处理)。 生成一条插入 sql,类似这种 insert into user(username,address) values(‘aa’,‘bb’),(‘cc’,‘dd’)…。 到底哪种快呢? 我们从两方面来考虑这个问题: 插入 SQL 本身执行的效率。 网络 I/O。 先说第一种方案,就是用 for 循环循环插入: 这种方案的优势在于,JDBC 中的 Prepare

qq_39853669的博客 9735

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java 批量提交_基于mybatis batch实现批量提交大量数据

很多人在用 MyBatis 或者 通用 Mapper 时,经常会问有没有批量插入和批量更新的方法。实际上许多时候没必要用 去实现特别复杂的批量操作。直接通过 MyBatis 的 BATCH 方式执行增删改方法即可。下面是一个批量用法的例子:在xml文件配置多条参数同时插入:select SEQ_CTAS_SHARK_FLT.nextval as recId from dualinsert int...

weixin_34070493的博客 946

Mybatis 批量插入大量数据的最优方案

点击上方“Java基基”,选择“设为星标”做积极的人,而不是积极废人!每天14:00更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2021超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT 源码解析作业调度中间件 Elast...

weixin_44421461的博客 1735

在 MyBatis 中如何配置单个批量插入或更新的 Session 使用 ExecutorType.BATCH 方式

使用执行器类型是 MyBatis 提供的一个高效的批量操作方案,能够显著提高批量插入和更新操作的性能。通过合理配置SqlSession和批量提交大小,可以有效地减少数据库交互次数、提高处理性能,并避免内存溢出等问题。理解和掌握这个功能,能够在处理大量数据时带来更高的效率。

Java老兵的后端进阶与AI前沿探索之路。 1278

对比 MyBatis 批处理 BATCH 模式与 INSERT INTO ... SELECT ... UNION ALL 进行批量插入

在开发中,我们经常需要批量插入大量数据。不同的批量插入方法有不同的优缺点,适用于不同的场景。MyBatis 的批处理模式。使用进行批量插入。MyBatis 批处理模式数据量适中:适用于数据量不是特别大,但需要频繁插入、更新或删除的场景。需要灵活的 SQL 操作:需要支持多种类型的 SQL 操作,如插入、更新和删除。需要细粒度的错误处理:需要在批处理完成后检查每个操作的结果,以便发现和处理错误。大数据量插入:适用于需要一次性插入大量数据的场景,尤其是数据量非常大时。性能要求高。

小单的博客专栏 2465
上一篇: Packet for query is too large (12238 > 1024). You can change this value
下一篇: 在Java中,break还可以这样用
Java_Mr_Zheng
博客等级 码龄11年 18粉丝 20原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值