在Java、MyBatis 3.4中,大量的批插入实际上并没有立即存储到数据库中
任务:我需要一批至少插入10k条记录 事实上:在提交/刷新调用期间,我可以通过使用“SELECT*FROM TABLE”看到记录是以完全随机的数字插入的。 比如它可以插入1k,然后是500,再插入1.5k,然后再插入500。一些非常奇怪的事情正在发生 我有非常基本的设置,如:在Java、MyBatis 3.4中,大量的批插入实际上并没有立即存储到数据库中,java,mysql,mybatis,Java,Mysql,Mybatis,任务:我需要一批至少插入10k条记录 事实上:在提交/刷新调用期间,我可以通过使用“SELECT*FROM TABLE”看到记录是以完全随机的数字插入的。 比如它可以插入1k,然后是500,再插入1.5k,然后再插入500。一些非常奇怪的事情正在发生 我有非常基本的设置,如: <bean id="armDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <propert
<bean id="armDataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="jdbcUrl" value="${database.url}"/>
<property name="user" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="maxPoolSize" value="30"/>
<property name="idleConnectionTestPeriod" value="300"/>
<property name="maxIdleTime" value="300"/>
<property name="preferredTestQuery" value="SELECT 1"/>
<property name="testConnectionOnCheckin" value="true"/>
</bean>
<tx:annotation-driven />
<bean id="armTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="armDataSource"/>
</bean>
<bean id="armSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="armDataSource"/>
<property name="typeAliasesPackage" value="com.database.arm.model"/>
</bean>
<bean id="armSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="armSqlSessionFactory" />
<constructor-arg index="1" value="BATCH" />
</bean>
然后我有以下代码:
SqlSession sqlSession = armSqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
HeaderMapper headerMapper = sqlSession.getMapper(HeaderMapper.class);
List<List<HeaderDAO>> partitions = Lists.partition(HeaderDAOS, 10000);
partitions.forEach(partition -> {
partition.forEach(headerDAO -> {
headerDAO.setFileId(fileId);
headerMapper.insert(headerDAO);
});
sqlSession.flushStatements();
});
sqlSession.commit();
sqlSession.close();
SqlSession SqlSession=armSqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH,false);
HeaderMapper HeaderMapper=sqlSession.getMapper(HeaderMapper.class);
列表分区=列表分区(HeaderDAOS,10000);
partitions.forEach(分区->{
分区。forEach(headerDAO->{
headerDAO.setFileId(fileId);
封头上镶块(封头道);
});
sqlSession.flushStatements();
});
提交();
sqlSession.close();
它只适用于100条或更少记录的小批量插入。但一旦我走得更高,看起来Mybati做的比一批还要多
sqlSessionFactory或模板或数据源的设置可能有问题?我尝试了很多选择,但都没用。
非常感谢您的任何输入。因此我调试了所有的堆栈直到mysql驱动程序,并找到了原因。 默认情况下,MySQL驱动程序实际上在一个事务中逐个执行批插入。 要启用一个大批量插入,需要使用以下属性让mysqldriver知道: rewriteBatchedStatements=true 这可以在数据源的connectionUrl中绕过,或通过数据源的属性指定:
<property name="properties">
<props>
<prop key="rewriteBatchedStatements">true</prop>
</props>
</property>
真的
注意:您只需要在MyBatis的情况下使用它,因为例如Hibernate将自动执行此操作。因此我已经调试了所有堆栈直到mysql驱动程序,并找到了原因。 默认情况下,MySQL驱动程序实际上在一个事务中逐个执行批插入。 要启用一个大批量插入,需要使用以下属性让mysqldriver知道: rewriteBatchedStatements=true 这可以在数据源的connectionUrl中绕过,或通过数据源的属性指定:
<property name="properties">
<props>
<prop key="rewriteBatchedStatements">true</prop>
</props>
</property>
真的
注意:您只需要在MyBatis的情况下使用它,因为例如Hibernate会自动执行