我看了几个例子,不明白我在做什么不同;但是,这对我不起作用。下面是对我的代码的简化描述,以及代码片段,以说明哪些代码不起作用。
我有一个主事务表,它为每个应用程序事务保存一条记录。我有一个链接表,它保存来自事务的图像,外键指向主事务记录。这里没有太奇怪或太花哨的东西(完全公开:还有另外两个链接表,但我确信对一个表的修复将适用于所有这些表。)
我的代码创建了一个restful端点,如下所示:
@Controller
@RequestMapping("/feed/v1")
public class ReportingDataFeedControllerV1 {
@Resource(name = "dataFeedService")
private DataFeedService dataFeedService;
@PostMapping(value = "/myend", consumes = "application/json", produces = "application/json")
public @ResponseBody DataFeedResponse DataFeed(@RequestBody DataFeedRequest request) {
DataFeedResponse response = new DataFeedResponse();
try {
dataFeedService.saveData(request);
datafeedservice是定义savedata方法并由datafeedserviceimpl实现的接口:
public class DataFeedServiceImpl implements DataFeedService {
@Resource(name = "dataFeedRepository")
private DataFeedRepository dataFeedRepository;
@Override
//@Transactional // Outer @Transactional commented
/**
* Call the save method on the repository implementation class.
*
* @param request - DataFeedRequest object that contains the data to be saved
* @throws Exception
* @author SmithDE
*/
public void saveData(DataFeedRequest request) throws Exception {
dataFeedRepository.saveData(request);
}
datafeedrepository是datafeedrepositoryimpl实现的另一个接口:
public class DataFeedRepositoryImpl implements DataFeedRepository {
private static final int REF_SS_MFA = 4;
@Resource(name="rdpJdbcTemplate")
private JdbcTemplate jdbcTemplate;
因此,在启动此操作的方法和对savedata()的实际调用之间至少有两个级别的类。
我的方法,在类datafeedrepositoryimpl中,将事务数据保存到数据库表中,用@transactional注解,如下所示:(它还包括@override,因为它是基类接口的实现。)
@Override
@Transactional // Nested @Transactional
/**
* Method that performs the save of the data to the database tables.
*
* @param request - Request object containing the data to be saved
* @exception Exception
* @author SmithDE
*/
public void saveData(DataFeedRequest request) throws Exception {
该方法为主事务表构建insert语句。它需要检索新的主键,所以调用jdbctemplate的update方法如下:
KeyHolder keyHolder = new GeneratedKeyHolder();
int newRowCount = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection
.prepareStatement(thisquery, Statement.RETURN_GENERATED_KEYS);
return ps;
}, keyHolder);
id = (long) keyHolder.getKey();
接下来,它将为与此事务关联的映像构建一系列insert语句,并通过单独调用jdbctemplate.update()将它们发送到数据库,如下所示:
for (DataFeedImage image : images) {
...
newRowCount = jdbcTemplate.update(thisquery);
}
我的期望是,任何将图像插入链接图像表的调用中的错误都会导致整个数据库事务回滚。然而,我的观察却不同:
主事务数据记录仍在主事务表中。
在发生错误之前插入的所有图像仍然存在于图像表中。
我希望所有这些对update()的调用都是同一个数据库事务的一部分,但它们显然不是。
请帮助我理解我做错了什么。
只是我在写这篇编辑时的一个想法。上一个实现类中的方法被注解为@transactional,而实际进行jdbctemplate.update()调用的方法也被注解为@transactional,这可能是个问题吗?@transactional的嵌套声明会导致问题吗?
1条答案
按热度按时间siotufzp1#
这是一个决议,但不是一个答案!
这个决定可能高于我的工资等级,这个应用程序将被重新设计和重写,以便它使用java持久性api(jpa)而不是jdbc模板。
会有同样的数据库事务问题吗?我们拭目以待。
此问题已解决。
感谢对这个问题提出建议的人。我真的很想解决这个问题,但事实并非如此。