在spring批处理作业中,项目处理器将项目读取器读取的对象拆分为七个长度可变的列表。这些列表必须写入DB中的七个表,任何错误(如DB出于任何原因拒绝记录)都必须导致事务在所有七个表上回滚。
目前,我使用这七个列表创建一个包装对象,这些列表将传递给自定义项目编写器。作者获取所有这些项目,创建自己的七个列表,以便它只有七个批处理写入(使用基于JdbcTemboard的DAO)用于项目处理器返回的一批包装对象。
我的编写器按顺序为每个表调用insert函数,我希望加快速度。我想知道是否可以将列表并行地写入各自的表中,以便总的执行时间是最长的写入时间。我不能妥协的一个要求是,这必须在单个事务中,如果任何写入程序有任何异常,则需要回滚该事务。
这里有一个简单的解决方案,它利用TaskExecitor并扩展到CompositeItemWriterorg.springframework.batch.item.support.。
package de.incompleteco.spring.batch.item.support;
import java.util.List;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.support.CompositeItemWriter;
import org.springframework.core.task.TaskExecutor;
import org.springframework.util.Assert;
import de.incompleteco.spring.domain.SimpleEntity;
public class ParallelCompositeItemWriter extends CompositeItemWriter<SimpleEntity> {
private List<ItemWriter<? super SimpleEntity>> delegates;
private TaskExecutor taskExecutor;
@Override
public void write(final List<? extends SimpleEntity> item) throws Exception {
for (final ItemWriter<? super SimpleEntity> writer : delegates) {
taskExecutor.execute(new Runnable() {
@Override
public void run() {
try {
writer.write(item);
} catch (Throwable t) {
rethrow(t);
}
}
private void rethrow(Throwable t) {
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
}
else if (t instanceof Error) {
throw (Error) t;
}
throw new IllegalStateException(t);
}
});
}//end for
}
public void setTaskExecutor(TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
@Override
public void setDelegates(List<ItemWriter<? super SimpleEntity>> delegates) {
this.delegates = delegates;
super.setDelegates(delegates);
}
@Override
public void afterPropertiesSet() throws Exception {
super.afterPropertiesSet();
Assert.notNull(taskExecutor,"Task executor needs to be set");
}
}
示例配置如下所示;
<batch:job id="simpleJob">
<batch:step id="simpleJob.step1">
<batch:tasklet>
<batch:chunk reader="reader" writer="writer" commit-interval="10"/>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="reader" class="org.springframework.batch.item.support.IteratorItemReader">
<constructor-arg ref="itemList"/>
</bean>
<bean id="writer" class="de.incompleteco.spring.batch.item.support.ParallelCompositeItemWriter">
<property name="delegates" ref="writerDelegates"/>
<property name="taskExecutor" ref="writerTaskExecutor"/>
</bean>
<util:list id="writerDelegates">
<bean class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource1"/>
<property name="sql" value="insert into test_table (idcol,stuff) values (:idCol,:stuff)"/>
<property name="itemSqlParameterSourceProvider">
<bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>
</bean>
<bean class="org.springframework.batch.item.database.JdbcBatchItemWriter">
<property name="dataSource" ref="dataSource2"/>
<property name="sql" value="insert into test_table (idcol,stuff) values (:idCol,:stuff)"/>
<property name="itemSqlParameterSourceProvider">
<bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider"/>
</property>
</bean>
</util:list>
<util:list id="itemList">
<bean class="de.incompleteco.spring.domain.SimpleEntity">
<constructor-arg value="stuff1"/>
</bean>
<bean class="de.incompleteco.spring.domain.SimpleEntity">
<constructor-arg value="stuff2"/>
</bean>
<bean class="de.incompleteco.spring.domain.SimpleEntity">
<constructor-arg value="stuff3"/>
</bean>
</util:list>
<task:executor id="writerTaskExecutor" pool-size="3"/>
<bean id="dataSource1" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
<property name="className" value="org.h2.jdbcx.JdbcDataSource" />
<property name="uniqueName" value="#{T(System).currentTimeMillis()}" />
<property name="allowLocalTransactions" value="true"/>
<property name="maxPoolSize" value="2" />
<property name="driverProperties">
<props>
<prop key="URL">jdbc:h2:mem:a;DB_CLOSE_DELAY=-1</prop>
</props>
</property>
</bean>
<bean id="dataSource2" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close">
<property name="className" value="org.h2.jdbcx.JdbcDataSource" />
<property name="uniqueName" value="#{T(System).currentTimeMillis()}" />
<property name="allowLocalTransactions" value="true"/>
<property name="maxPoolSize" value="2" />
<property name="driverProperties">
<props>
<prop key="URL">jdbc:h2:mem:b;DB_CLOSE_DELAY=-1</prop>
</props>
</property>
</bean>
<jdbc:initialize-database data-source="dataSource1">
<jdbc:script location="classpath:/META-INF/sql/schema-h2.sql"/>
</jdbc:initialize-database>
<jdbc:initialize-database data-source="dataSource2">
<jdbc:script location="classpath:/META-INF/sql/schema-h2.sql"/>
</jdbc:initialize-database>
<!-- XA transaction -->
<bean id="btmConfig" factory-method="getConfiguration" class="bitronix.tm.TransactionManagerServices"/>
<bean id="BitronixTransactionManager" factory-method="getTransactionManager"
class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig" destroy-method="shutdown" />
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="BitronixTransactionManager" />
<property name="userTransaction" ref="BitronixTransactionManager" />
</bean>
此示例使用以下内容:;
(数据库中的内容非常粗糙,只是一个例子)
问题内容: 这个问题已经在这里有了答案 : 如何在Python中进行换行(换行)? (11个答案) 2年前关闭。 就像C一样,您可以将一条长线分成多条短线。但是在Python中,如果执行此操作,将会出现缩进错误…可能吗? 问题答案: 从PEP 8-Python代码样式指南: 包装长行的首选方法是在括号,方括号和花括号内使用Python的隐含行连续性。如有必要,可以在表达式周围添加一对额外的括号,但
我正在尝试创建Java程序,它可以读取多个pdf文件,并将它们合并成一个单一的pdf文件。然后打印PDF,但在打印时,我需要将多个PDF页面合并在一个页面中并打印。即使它是一个新的pdf创建,那对我来说是好的。我需要一些开源的Java pdf操纵库来处理这个。我知道一个解决方案是在打印时,选择多个打印选项,将多页打印到一张纸上。但我可以访问的打印机没有这样的功能。有谁能为这个问题提出一些解决方案,
问题内容: 想法是在片中具有可变数量的通道,将通过通道接收的每个值推入单个通道,并在最后一个输入通道关闭后关闭该输出通道。这样的事情,但对于多个渠道来说,要超过两个: 上面的代码避免了繁忙的循环,因为没有任何情况,这是很好的(编辑:看起来,“,ok”的存在使select语句成为非阻塞状态,并且循环毕竟是繁忙的。但是出于示例的目的,就好像将代码阻止一样)。是否可以通过任意数量的输入通道来实现相同的功
可能重复: 在锚中放置div是否正确? 我想有一个复杂元素的链接(包含图像、段落和其他内容)。我知道它是有效的,但是有
我有几份产品数据表。每个文件都是一个单独的文件。我想做的是使用iText根据Web表单的答案生成一组摘要/建议的操作,然后将所有相关的数据表附加到这些操作中。这样,我只需要在浏览器中打开一个新选项卡来打印所有信息,而不是为摘要打开一个选项卡,为所需的每个数据表打开一个选项卡。 那么,使用iText可以做到这一点吗?
问题内容: 我在詹金斯(Jenkins)有很多自由式工作,我想转换为多配置工作,这样我就可以在一项工作下跨多个平台进行构建。这些作业指定了很多构建参数,我不想通过创建新的多配置作业来再次手动设置它们。当前,每个作业都将其构建限制为我们一直在构建的平台,而我看到的唯一其他选择是克隆现有作业,并将限制更改为新平台。这不是理想的选择,因为我需要维护2个工作,其中唯一的区别是目标平台。 我没有看到通过UI