Bha*_*v J 6 java spring-transactions spring-boot
这里需要一些帮助,我无法理解为什么我的事务在发生异常时不会回滚。
我会尝试将我的代码尽可能接近项目中的位置(无法在互联网上共享)
这是我的服务
@Service
@SL4j
@Transactional(propagation = propagation.SUPPORTS, readOnly=true)
public class PublicationServiceImpl implements PublicationService{
@Autowired
private PartnerRepo partnerRepo;
@Autowired
private FlowRepo flowRepo;
@Autowired
private PubRepo pubRepo;
@Override
@Transactional(propagation = propagation.REQUIRED, rollbackFor=Exception.class)
public int save(Request request) {
try{
int pk_id_partner = partnerRepo.save(request);
int pk_id_flow = flowRepo.save(request);
String publicationCode = generatePubCode(request);
int publicationCode= pubRepo.save(pk_id_partner, pk_id_flow, request);
}
catch(Exception e){
log.error("Exception in saving");
}
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的存储库(1 的示例,所有 3 个存储库都遵循相同的编码标准)
@Repository
@Slf4j
public class PartnerRepo implemets PartnerRepo{
@Autowired
private NamedParamaterJDBCTemplate namedParamaterJDBCTemplate;
//String Declarations .....
private MapSqlParameterSource sqlParameterSource;
@Override
public int save(Request request){
sqlParamatersSource = new MapSqlParameterSource();
//sqlParamatersSource.addValue(.....)
//sqlParamatersSource.addValue(.....)
//sqlParamatersSource.addValue(.....)
return executeQuery();
}
private int executeQuery(){
try{
keyHolder = new GenerateKeyHolder();
namedParamaterJDBCTemplate.update(getInsertQuery(), sqlParamaterSource , kekHolder, new String[]{"pk_id"})
return keyHolder.getKey().intValue();
}catch(Exception e){
log.error("Exception while saving");
return 0;
}
}
}
Run Code Online (Sandbox Code Playgroud)
那么问题来了,考虑到方法中存在异常generatePubCode(request);,理想情况下由于我在类级别和方法级别都使用过@Transactional,之前的2个repo transactions()应该回滚吧?然而它并没有发生,即使代码完成执行后我也可以看到数据库(Postgres DB v10)中的记录。
请帮忙解决这个问题,我是不是做错了什么?
如果您需要更多可能有帮助的信息,请告诉我!
PS:我已经尝试了 的所有排列@Transactional,但没有任何效果:只有在 catch 块中使用它才有效! TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
我想知道这对于 springBoot 项目是否是正确的方法
先谢谢您的帮助!
编辑:根据公开的PublicationServiceSaverImpl.save()建议
最好的问候,巴尔加夫。
有几件事会破坏 Spring 中的正常事务
privateprivate方法事实上,你的PublicationServiceImpl save方法private基本上使得@Transactional该方法毫无用处。由于private方法无法被代理,因此不会应用任何交易。即使是这样,当public您从同一对象内调用该方法时,它也不会起作用,因此该方法的事务性适用。
要修复此问题,请创建您的方法public并save从其他类调用该方法(或者使正在调用的实际方法save具有正确的@Transactional.
事实上,这是行不通的,因为使用了 op AOP 类型,默认情况下 Spring 将使用代理,这是使用基于代理的 AOP 的一个缺点。
使其与private方法一起使用的另一个解决方案是切换到成熟的 AspectJ,并通过类的编译时或加载时编织来实现。两者都需要额外的设置,而且可能很乏味。
您的存储库和服务中都有一个try/catch块。其中每一个都会捕获并吞掉异常(它们被记录但不会重新抛出)。
为了使事务正常工作,需要查看异常情况。事实上,您捕获并吞下它们,使得事务方面看不到它们,并且不进行回滚,而是进行提交。对于交易方面,一切都很好,因为没有例外。
要修复此问题,请删除异常try/catch或重新引发异常。
由于 Spring 中代理的创建方式,注释通常不适用于从同一类调用的方法。
它与 @Transaction 特别无关,但与您的方法是私有的并且从同一对象内调用这一事实有关。
请将方法公开,并将 @Transactional 方法移动到用 @Service 注释的单独类中,并从类实例的外部调用它
@Service
public class PublicationServiceSaverImpl {
@Transactional
**public** int save(Request request) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
您必须从 PublicationServiceSaverImpl 类的外部调用 save 方法,也许是从 PublicationServiceImpl 调用。
| 归档时间: |
|
| 查看次数: |
16438 次 |
| 最近记录: |