Spring-数据 JdbcTemplate 没有提交
Spring-data JdbcTemplate does not commit
我需要更新数据库中的数千条记录,但我想在一批 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, finally call db update.
updateDbInBatches(rowcount, 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 方法完成.我如何确保在每次提交后确实将数据写入数据库。 commit 也不会给出任何错误。
我错过了一条解决问题的重要信息。
我有另一个 public 方法,这是从外部调用的方法。
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
上面的方法实际上是使用默认的事务传播,因为我没有具体提到它。由于这是调用的第一个 public 方法,因此 spring 忽略了下一个调用的 public(异步)方法的事务划分。我将上面的签名更改为:
@Transactional (propagation=Propagation.NOT_SUPPORTED)
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
然后成功了。每次提交后我都能看到数据库中的变化。
我需要更新数据库中的数千条记录,但我想在一批 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, finally call db update.
updateDbInBatches(rowcount, 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 方法完成.我如何确保在每次提交后确实将数据写入数据库。 commit 也不会给出任何错误。
我错过了一条解决问题的重要信息。
我有另一个 public 方法,这是从外部调用的方法。
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
上面的方法实际上是使用默认的事务传播,因为我没有具体提到它。由于这是调用的第一个 public 方法,因此 spring 忽略了下一个调用的 public(异步)方法的事务划分。我将上面的签名更改为:
@Transactional (propagation=Propagation.NOT_SUPPORTED)
public void reloadAttrs(TransDetail trans)
{
reloadAttrs();
}
然后成功了。每次提交后我都能看到数据库中的变化。