问题描述
我需要更新数据库中的数千条记录,但我想在一批5000条记录之后提交。
@Service
@Transactional (rollbackFor=Throwable.class)
public class AttributeProcessorServiceImpl extends DataLoader implements
AttributeProcessorService
{
.....
private final TransactionTemplate transtemplate;
private final JdbcTemplate jdbcTemplate;
@Autowired private PlatformTransactionManager platformTransactionManager;
@Autowired
public BlockAttributeProcessorServiceImpl(
TransactionTemplate transtemplate,JdbcTemplate jdbcTemplate,.....)
{
super();
this.transtemplate = transtemplate;
this.jdbcTemplate=jdbcTemplate;
.....
}
@Async
@Transactional (propagation=Propagation.NOT_SUPPORTED)
public void reloadAttrs()
{
loadAttrs();
updateAttrs();
}
private void loadAttrs()
{
...some data fetching and processing,finally call db update.
updateDbInBatches(rowcount,sql);
}
private void updateAttrs()
{
...some data fetching and processing,sql);
}
private void updateDbInBatches(long rowcount,String sql)
{
DefaultTransactionDeFinition def;
boolean hasMore=true;
Integer from;
Integer to = 0;
int batchSize=5000; //gets from property
while (hasMore)
{
from = to+1;
to = batchSize;
def = new DefaultTransactionDeFinition();
def.setName("backCommitTx");
def.setPropagationBehavior(TransactionDeFinition.PROPAGATION_required);
TransactionStatus status = platformTransactionManager.getTransaction(def);
int rows = jdbcTemplate.update(sql,paramValues,paramTypes);
logger.debug("Loaded ["+rows+"] records.");
platformTransactionManager.commit(status);
if (to > rowcount)
{
hasMore=false;
logger.debug("All records ["+rowcount+"] updated.");
}
}
}
}
如果我在loadAttrs()之后放置一个断点,则表明它已将一堆记录加载到数据库中并发出了commit(),但是直到整个公共方法完成后,数据库才反映该提交。如何确保每次提交后确实将数据写入数据库。提交也不会给出任何错误。
解决方法
我错过了解决问题的重要信息。
我还有另一种公开方法,就是从外面叫。
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
上面的方法实际上是使用默认事务传播的,因为我没有具体提及。由于这是第一个被调用的公共方法,因此spring忽略了对下一个被调用的公共(异步)方法的事务划分。我将上面的签名更改为:
@Transactional (propagation=Propagation.NOT_SUPPORTED)
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
然后它起作用了。每次提交后,我都能看到数据库中的更改。