spring Batch实现数据库大数据量读写

SpringBoot高效批量插入百万数据 前言:我相信很多小伙伴和我一样在初学的时候,面对几万几十万数据插入,不知道如何下手,面对百万级别数据时更是不知所措,我们大部分初学者,很多人都喜欢for循环插入数据,或者是开启多个线程,然后分批使用for循环插入,当我们需要将大量数据存储到数据库中时,传统的逐条插入方式显然效率低下,并且容易导致性能瓶颈。总结:经过上面的示例演示我们心里已经有谱了,知道什么时候该使用哪一种数据插入方式,针对对不同线程数的测试,发现不是线程数越多越好,具体多少合适,通常的算法:CPU核心数量*2 +2 个线程。 阅读详情

1. data-source-context.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<!-- 1) USE ANNOTATIONS TO IDENTIFY AND WIRE SPRING BEANS. -->
	<context:component-scan base-package="net.etongbao.vasp.ac" />
	
	<!-- 2) DATASOURCE, TRANSACTION MANAGER AND JDBC TEMPLATE -->
 
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close" abstract="false" scope="singleton">
		<!-- oracle.jdbc.driver.oracleDriver -->
		<property name="driverClass" value="oracle.jdbc.OracleDriver" />
		<property name="jdbcUrl" value="jdbc:oracle:thin:@192.168.1.23:1521:orcl01" />
		<property name="user" value="USR_DEV01" />
		<property name="password" value="2AF0829C" />
		<property name="checkoutTimeout" value="30000" />
		<property name="maxIdleTime" value="120" />
		<property name="maxPoolSize" value="100" />
		<property name="minPoolSize" value="2" />
		<property name="initialPoolSize" value="2" />
		<property name="maxStatements" value="0" />
		<property name="maxStatementsPerConnection" value="0" />
		<property name="idleConnectionTestPeriod" value="30" />	
	</bean>
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
	</bean>
	
	<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

 2. quartz-context.xml       commit-interval="10000"每次批量数据的条数,数值越大效率越高,可在此处添加事物处理,

每次回滚数就是commit-interval数

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:batch="http://www.springframework.org/schema/batch"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch-2.1.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

	<import resource="data-source-context.xml"/>
	
	<!--   JOB REPOSITORY - WE USE IN-MEMORY REPOSITORY FOR OUR EXAMPLE -->
	<bean id="jobRepository"
		class="org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean">
		<property name="transactionManager" ref="transactionManager" />
	</bean>
	
	<!-- batch config -->
	<bean id="jobLauncher"
		class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
		<property name="jobRepository" ref="jobRepository" />
	</bean>

	<!--  FINALLY OUR JOB DEFINITION. THIS IS A 1 STEP JOB -->
	<batch:job id="ledgerJob">
		<batch:listeners>
			<batch:listener ref="appJobExecutionListener" />
		</batch:listeners>
		<batch:step id="step1">
		   <batch:tasklet transaction-manager="transactionManager">
			<batch:tasklet>
				<batch:listeners>
					<batch:listener ref="itemFailureLoggerListener" />
				</batch:listeners>
				<batch:chunk reader="ledgerReader" writer="ledgerWriter"
					commit-interval="10000" /> <!-- 1万条进行一次commit -->
			</batch:tasklet>
                   </batch:tasklet>
		</batch:step>
	</batch:job>
	 
	<!--  READER -->
	<bean id="ledgerReader"
		class="org.springframework.batch.item.database.JdbcCursorItemReader">
		<property name="dataSource" ref="dataSource" />
		<property name="sql" value="select * from ledger" /> 
		<property name="rowMapper" ref="ledgerRowMapper" />
	</bean>
	 
	<!-- Spring Batch Job同一个job instance,成功执行后是不允许重新执行的【失败后是否允许重跑,可通过配置Job的restartable参数来控制,默认是true】,如果需要重新执行,可以变通处理,
		添加一个JobParameters构建类,以当前时间作为参数,保证其他参数相同的情况下却是不同的job instance -->
	<bean id="jobParameterBulider" class="org.springframework.batch.core.JobParametersBuilder" />
	
	<!-- 定时任务 开始 -->  
	<bean id="ledgerJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
		<property name="targetObject">  
			<!-- 定时执行的类 -->  
			<ref bean="quartzLedgerJob" />  
		</property>  
		<property name="targetMethod">  
			<!-- 定时执行的类方法 -->  
			<value>execute</value>  
		</property>  
	</bean>  
  
	<bean id="ledgerCronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean" >  
		<!-- 这里不可以直接在属性jobDetail中引用taskJob,因为他要求的是一个jobDetail类型的对象,所以我们得通过MethodInvokingJobDetailFactoryBean来转一下 -->  
		<property name="jobDetail" >  
			<ref bean="ledgerJobDetail" />  
		</property>  
		<!--在每天下午18点到下午18:59期间的每1分钟触发  -->  
		<!--在每天上午10点40分准时触发  -->  
		<property name="cronExpression" >  
			<!-- <value>0 * 15 * * ?</value> -->
			<value>0 45 10 * * ? * </value> 
		</property>  
        
	</bean>  
      
	<!-- 触发器工厂,将所有的定时任务都注入工厂-->  
	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
		<!-- 添加触发器 -->  
		<property name="triggers">  
			<list>  
				<!-- 将上面定义的测试定时任务注入(可以定义多个定时任务,同时注入)-->  
				<ref local="ledgerCronTrigger" />  
			</list>  
		</property>  
	</bean>  
	<!-- 定时任务 结束 -->  
</beans>  

 

3.定时调度job类 QuartzLedgerJob.java

 

 package net.etongbao.vasp.ac.quartz;

import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;

/**
 * 定时调度类
 * @author Fu Wei
 *
 */

@Component("quartzLedgerJob")
public class QuartzLedgerJob {

	private static final Logger LOG = LoggerFactory.getLogger(QuartzLedgerJob.class);

	@Autowired
	private JobLauncher jobLauncher;

	@Autowired
	private Job ledgerJob;

	@Autowired
	JobParametersBuilder jobParameterBulider;

	private static long counter = 0l;
	
	/**
	 * 执行业务方法
	 * @throws Exception
	 */
	public void execute() throws Exception {
		LOG.debug("start...");
		StopWatch sw = new StopWatch();
		sw.start();
		/*
		 * Spring Batch Job同一个job instance,成功执行后是不允许重新执行的【失败后是否允许重跑,
		 * 可通过配置Job的restartable参数来控制,默认是true】,如果需要重新执行,可以变通处理,
		 * 添加一个JobParameters构建类,以当前时间作为参数,保证其他参数相同的情况下却是不同的job instance
		 */
		jobParameterBulider.addDate("date", new Date());
		jobLauncher.run(ledgerJob, jobParameterBulider.toJobParameters());
		sw.stop();
		LOG.debug("Time elapsed:{},Execute quartz ledgerJob:{}", sw.prettyPrint(), ++counter);
	}
}
 

 4.程序启动类 StartQuartz.java

 package net.etongbao.vasp.ac.quartz;

import java.io.FileNotFoundException;

import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * 启动定时调度
 * @author Fu Wei
 *
 */
public class StartQuartz {

	public static void main(String[] args) throws FileNotFoundException {

		new ClassPathXmlApplicationContext("/net/etongbao/vasp/ac/resources/quartz-context.xml");
	}
}

 

5.pojo类 Ledger.java

 

package net.etongbao.vasp.ac.pojo;

import java.io.Serializable;
import java.util.Date;

public class Ledger implements Serializable {

	private int id;
	private Date receiptDate;
	private String memberName;
	private String checkNumber;
	private Date checkDate;
	private String paymentType;
	private double depositAmount;
	private double paymentAmount;
	private String comments;

	public Ledger() {
		super();
	}

	public Ledger(int id, Date receiptDate, String memberName, String checkNumber, Date checkDate, String paymentType,
	        double depositAmount, double paymentAmount, String comments) {
		super();
		this.id = id;
		this.receiptDate = receiptDate;
		this.memberName = memberName;
		this.checkNumber = checkNumber;
		this.checkDate = checkDate;
		this.paymentType = paymentType;
		this.depositAmount = depositAmount;
		this.paymentAmount = paymentAmount;
		this.comments = comments;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public Date getReceiptDate() {
		return receiptDate;
	}

	public void setReceiptDate(Date receiptDate) {
		this.receiptDate = receiptDate;
	}

	public String getMemberName() {
		return memberName;
	}

	public void setMemberName(String memberName) {
		this.memberName = memberName;
	}

	public String getCheckNumber() {
		return checkNumber;
	}

	public void setCheckNumber(String checkNumber) {
		this.checkNumber = checkNumber;
	}

	public Date getCheckDate() {
		return checkDate;
	}

	public void setCheckDate(Date checkDate) {
		this.checkDate = checkDate;
	}

	public String getPaymentType() {
		return paymentType;
	}

	public void setPaymentType(String paymentType) {
		this.paymentType = paymentType;
	}

	public double getDepositAmount() {
		return depositAmount;
	}

	public void setDepositAmount(double depositAmount) {
		this.depositAmount = depositAmount;
	}

	public double getPaymentAmount() {
		return paymentAmount;
	}

	public void setPaymentAmount(double paymentAmount) {
		this.paymentAmount = paymentAmount;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}
}

 

 6. LedgerDaoImpl.java

 package net.etongbao.vasp.ac.dao.impl;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import net.etongbao.vasp.ac.dao.LedgerDao;
import net.etongbao.vasp.ac.pojo.Ledger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.stereotype.Repository;

/**
 * ledger数据操作类
 * 
 * @author Fu Wei
 * 
 */

@Repository
public class LedgerDaoImpl implements LedgerDao {

	private static final String SAVE_SQL = "insert into ledger_temp (rcv_dt, mbr_nm, chk_nbr, chk_dt, pymt_typ, dpst_amt, pymt_amt, comments) values(?,?,?,?,?,?,?,?)";

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Override
	public void save(final Ledger item) {
		jdbcTemplate.update(SAVE_SQL, new PreparedStatementSetter() {
			public void setValues(PreparedStatement stmt) throws SQLException {
				stmt.setDate(1, new java.sql.Date(item.getReceiptDate().getTime()));
				stmt.setString(2, item.getMemberName());
				stmt.setString(3, item.getCheckNumber());
				stmt.setDate(4, new java.sql.Date(item.getCheckDate().getTime()));
				stmt.setString(5, item.getPaymentType());
				stmt.setDouble(6, item.getDepositAmount());
				stmt.setDouble(7, item.getPaymentAmount());
				stmt.setString(8, item.getComments());
			}
		});
	}

}
 

7.接口 LedgerDao .java

 

 

package net.etongbao.vasp.ac.dao;

import net.etongbao.vasp.ac.pojo.Ledger;

public interface LedgerDao {
	public void save(final Ledger item) ;
}

 

 8. JdbcTemplete 需要的LedgerRowMapper.java

  package net.etongbao.vasp.ac.batch.writer;

import java.sql.ResultSet;
import java.sql.SQLException;

import net.etongbao.vasp.ac.pojo.Ledger;

import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;
 
/**
 * ledger行的映射类
 * @author Administrator
 *
 */
@Component("ledgerRowMapper")
public class LedgerRowMapper implements RowMapper {
	public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
		Ledger ledger = new Ledger();
		ledger.setId(rs.getInt("id"));
		ledger.setReceiptDate(rs.getDate("rcv_dt"));
		ledger.setMemberName(rs.getString("mbr_nm"));
		ledger.setCheckNumber(rs.getString("chk_nbr"));
		ledger.setCheckDate(rs.getDate("chk_dt"));
		ledger.setPaymentType(rs.getString("pymt_typ"));
		ledger.setDepositAmount(rs.getDouble("dpst_amt"));
		ledger.setPaymentAmount(rs.getDouble("pymt_amt"));
		ledger.setComments(rs.getString("comments"));
		return ledger;
	}
}

 

9.关键类LedgerWriter.java ,写入数据,负责数据的添加 

 

package net.etongbao.vasp.ac.batch.writer;

import java.util.List;

import net.etongbao.vasp.ac.dao.LedgerDao;
import net.etongbao.vasp.ac.pojo.Ledger;

import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * ledger写入数据
 * 
 * @author Fu Wei
 * 
 */
@Component("ledgerWriter")
public class LedgerWriter implements ItemWriter<Ledger> {

	@Autowired
	private LedgerDao ledgerDao;

	/**
	 * 写入数据
	 * 
	 * @param ledgers
	 */
	public void write(List<? extends Ledger> ledgers) throws Exception {
		for (Ledger ledger : ledgers) {
			ledgerDao.save(ledger);
		}
	}

}

 

 

 classPath:

 <?xml version="1.0" encoding="UTF-8"?>

<classpath>
	<classpathentry kind="src" path="src"/>
	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jrockit-jdk1.6.0_24-R28.1.3-4.0.1"/>
	<classpathentry kind="lib" path="lib/aopalliance-1.0.jar"/>
	<classpathentry kind="lib" path="lib/c3p0-0.9.1.2.jar"/>
	<classpathentry kind="lib" path="lib/commons-collections-3.2.1.jar"/>
	<classpathentry kind="lib" path="lib/commons-lang-2.3.jar"/>
	<classpathentry kind="lib" path="lib/commons-logging-1.1.1.jar"/>
	<classpathentry kind="lib" path="lib/etb-log4j-1.2.16.jar"/>
	<classpathentry kind="lib" path="lib/etb-slf4j-api-1.5.8.jar"/>
	<classpathentry kind="lib" path="lib/etb-slf4j-log4j12-1.5.8.jar"/>
	<classpathentry kind="lib" path="lib/ojdbc6.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.aop-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.asm-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.aspects-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.beans-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.context-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.context.support-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.core-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.expression-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.instrument-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.instrument.tomcat-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.jdbc-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.jms-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.orm-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.oxm-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.test-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/org.springframework.transaction-3.0.5.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/quartz-all-1.6.5.jar"/>
	<classpathentry kind="lib" path="lib/spring-batch-core-2.1.6.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/spring-batch-infrastructure-2.1.6.RELEASE.jar"/>
	<classpathentry kind="lib" path="lib/spring-batch-test-2.1.6.RELEASE.jar"/>
	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
	<classpathentry kind="output" path="bin"/>
</classpath>
 

 

  总结: 测试数据8万多条,响应时间3分多钟。

 

关键在于quartz-context.xml 中<bean id="ledgerReader"

class="org.springframework.batch.item.database.JdbcCursorItemReader">

<property name="dataSource" ref="dataSource" />

<property name="sql" value="select * from ledger" /> 

<property name="rowMapper" ref="ledgerRowMapper" />

</bean> 负责读取数据 ,在程序执行时一次性抓取全部数据后在批量的交给LedgerWriter进行写操作。当然也可以使用分页读取JdbcPagingItemReader,但要分页数量与写入数量要大写相同,还可以对分页出来的数据进行添加悲观锁

LedgerWriter.java 负责写入数据,每次写入1000条。

 

 

 

 

 

Spring Batch 专题系列(七):Spring Batch 与数据库集成 在上一篇文章中,我们学习了 Spring Batch 的并行处理机制(多线程 Step、分区、并行 Job)和性能优化技巧,掌握了如何处理海量数据。在批处理任务中,数据库操作是最常见的场景之一,例如从源表读取数据,经过转换后写入目标表(ETL)、批量更新记录或生成报表。本文详细讲解了 Spring Batch 与数据库的集成,包括 JDBC、JPA 和 MyBatis 的读写方式,以及事务管理和性能优化实践。A:JDBC 适合高性能 ETL,JPA 适合复杂实体关系,MyBatis 介于两者,灵活性高。 阅读详情

相关推荐

Spring Batch从入门到精通的知识介绍

Spring Batch 是一个轻量级的、全面的批处理框架,用于开发企业级的批处理应用程序。它构建在经典的 Java EE 核心技术之上,同时利用了 Spring Framework 提供的灵活性和可扩展性。

技术探秘者的博客 1503

Spring Batch(6)——数据库批数据读写

前序文章陆续介绍了批处理的基本概念,Job使用、Step控制、Item的结构以及扁平文件的读写。本文将接着前面的内容说明数据库如何进行批处理读写。 数据读取 数据库是绝大部分系统要用到的数据存储工具,因此针对数据库执行批量数据处理任务也是很常见的需求。数据的批量处理与常规业务开发不同,如果一次性读取百万条,对于任何系统而言肯定都是不可取的。为了解决这个问题Spring Batch提供了2套数据读取方案: 基于游标读取数据 基于分页读取数据 游标读取数据 对于有经验大数据工程师而言数据库游标的操作应

menergy 3073

使用Java和Spring Batch实现批处理

Spring Batch是Spring官方提供的一个批处理框架,它基于POJO(Plain Old Java Object)实现,通过简单的配置可以处理大量数据,支持事务管理、并发处理、错误处理等功能。首先,配置一个简单的Spring Batch作业,包括Job、Step、ItemReader、ItemProcessor和ItemWriter。大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!微赚淘客系统3.0小编出品,必属精品!

微赚开发者技术分享博客 840

Java后台框架篇--spring Batch实现数据库大数据量读写

1. data-source-context.xml   Xml代码   xml version="1.0" encoding="UTF-8"?>   beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema

非淡泊无以明志,非宁静无以致远 2408

SpringBatch读数据库(MyBatisPagingItemReader)(三)

文章目录一、抽取顺序读取数据库公共reader二、封装实体三、mapper配置文件四、配置文件application.properties五、读取数据库job六、继承公共CommonProcesor七、执行job 前言:我们在日常开发中可能会遇到读取数据库,SpringBatch封装的也有读取数据库的Reader,但是我们这次做实验用的是Mybatis封装的MyBatisPagingItemRe...

境里婆娑 1万+

STM32F407 HAL库定时器触发ADC采集与DMA数据传输(定时器TIM+ADC+DMA)

在STM32F407系列微控制器的开发中,结合定时器、ADC(模数转换器)与DMA(直接存储器访问)控制器,能够显著提升数据采集与传输的效率。本文将指导你如何使用STM32 HAL库,通过定时器触发ADC1的单通道采集,利用DMA传输数据,最终通过串口将电压值打印出来。具体实现中,我们将读取ADC1的通道5(对应引脚PA5),并将转换得到的电压值发送到串口助手上进行显示。

jmlinux的博客 7012

Spring Batch 批处理框架

一、 介绍Spring Batch能够支持简单的、复杂的和大数据量的批处理作业,是一个批处理应用框架,不是调度框架,但需要和调度框架(Quartz, Tivoli, Control-M, Cron等)合作来构建完成批处理任务。整体架构如下: 二、 基本概念 Job: 作业, 由多个 Step 组成,封装整个批处理操作, 是 Batch 操作的基础单元; Job Instance: 作业实例,每次作

不影响全局 3776

Innovus ECO技巧:用setEcoMode+ecoAddRepeater实现批量buffer替换的5个关键步骤

本文详细介绍了在Cadence Innovus工具中,利用setEcoMode与ecoAddRepeater命令实现高效、批量Buffer/Inverter替换的工程化策略。通过启用批处理模式、构建可维护的替换规则、掌握高级定位技巧以及规避布线陷阱等5个关键步骤,帮助芯片设计工程师在ECO阶段大幅提升修改效率与质量,确保设计稳定签核。

d6e7f8的博客 1117

Spring Batch 大数据量处理实战:从入门到精通

别叫我大神,叫我 Alex 就好。处理百万级数据不用愁,Spring Batch 让批处理变得优雅而高效。

alex_goden的博客 4242

基于Arduino的智能垃圾桶

通过本次简单的Arduino智能垃圾桶小实验可以快速了解Arduino的基本用法 1、材料准备 Arduino UNO HC-SR04超声波模块 SG90舵机 杜邦线 电源 电脑 2、代码分析 电机的控制 #include<Servo.h> #define duoji D5 Servo myduoji; void setup() { myduoji.attach(duoji); //舵机连接 Serial.begin(115200); } void loop() { myduoji.w

weixin_41679960的博客 1万+

【CubeMX】STM32G474 HRTIM 互补PWM与死区时间配置实战

本文详细介绍了如何使用STM32CubeMX配置STM32G474的高分辨率定时器HRTIM生成互补PWM波形并精确设置死区时间。通过实战步骤讲解时钟配置、死区计算与高级功能,帮助工程师在电机驱动和电源应用中实现精准控制,避免上下桥臂直通风险。

grpc6streamer的博客 727

关于 Spring Batch 的详细解析及其同类框架的对比分析,以及如何自己设计一个java批处理框架(类似spring batch)的步骤

关于 Spring Batch 的详细解析及其同类框架的对比分析

爱的叹息的专栏 2028

ArcGIS拓扑面错误批量修改

在工作学习中经常会遇到拓扑修改的问题,当数据量巨大的时候会产生拓扑问题 当拓扑错误数量巨大时,人工逐一修改是不现实的,基于此利用gis自带工具箱实现拓扑面类错误的批量修改。 一、.常见拓扑错误的类型: 1面重叠 2空隙(绿色部分) 二、拓扑检查 1新建数据库-----新建数据集—导入数据. 2新建拓扑 3修改拓扑容差及名称 添加拓扑修改规则 完成拓扑检查-查看拓扑错误 三、拓扑批量...

qq_43173805的博客 3万+

深入解析Spring Batch:企业级批处理框架的技术之旅

Spring Batch是一个开源的、轻量级的批处理框架,它基于Spring框架构建,继承了Spring的诸多优点,如依赖注入、面向切面编程等。Spring Batch旨在简化批处理应用程序的开发,提供了一套丰富的功能来支持事务管理、作业调度、异常处理、日志记录等。Spring Batch是一个完善的批处理框架,旨在帮助企业建立健壮、高效的批处理应用。它是Spring的一个子项目,使用Java语言并基于Spring框架为基础开发,使得已经使用Spring框架的开发者或者企业更容易访问和利用企业服务。

码到三十五 2万+

【加密社】私钥碰撞器,秒杀市面上的碰撞器

基于上述的逻辑和代码,开发了ETH挖掘器(图1.1)这里有个亮点是:1.很多开发者在判断地址是否有效的环节上,用的是查询余额,其实这是不对的,查询余额你可能只能查询对应代币的余额,例如usdt,eth等但是如果用查询交易次数就不一样了,你只要是交易过,我就认为是有效钱包,这样的速度比查询余额要快,也要更准确。2.rpc节点可配置。

加密社的博客 1580

Power BI常见问题篇1:无法打开文档

Power BI常见问题篇1:无法打开文档

weixin_48273257的博客 3304

Spring Batch 批处理框架优化实践,效率嘎嘎高!

一、Spring Batch简介1 框架概述2 核心概念和组件二、批处理优化实践4.1 使用Spring Boot Actuator进行监控4.2 使用管理控制台来监控3.1 批处理启动前校验3.2 读写校验2.1 多进程处理2.2 多线程处理1.1 分页处理数据1.2 使用读写缓存1.3 行级别写操作1 减少读写次数2 并发处理任务3 提高数据校验准确性4 监控批处理任务三、实践示例3.1 修改...

Java知音 1335

利用插件扩展 Qt 应用程序

不仅 Qt 本身可以通过插件进行扩展,而且 Qt 应用程序也可以通过插件来扩展,这需要应用程序使用 `QPluginLoader` 检测和加载插件。

青春不老,奋斗不止! 1万+

Spring Batch零基础入门:第一个批处理程序

Spring Batch是Spring生态中的一个轻量级批处理框架,主要用于处理大量数据的读取、处理和写入。它的核心思想是将批处理任务分解为一个个独立的步骤,每个步骤由读取、处理和写入三个部分组成。

CyanWave34的博客 1043

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

上一篇: HttpClient post请求 手机直冲案例
下一篇: servlet 使用spring管理bean
VirusFu
博客等级 码龄21年 51粉丝 79原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值