返回CompletableFuture的Spring Transactional方法

时间:2017-01-16 21:35:07

标签: java spring transactional spring-restcontroller completable-future

我有RestController从服务调用方法。方法将User添加到PostresSQL数据库,该数据库最多有20个连接。

@RestController
public class Controller {
    @RequestMapping(value = "/user", method = RequestMethod.POST)
    public String addUser(@RequestBody UserInfo userInfo) {
        Future<String> completableFuture = userService.addUser(userInfo);
        String answer = voidCompletableFuture.get();
        return answer;
    }
}

服务中的方法由Spring Transactional注释,在持久化数据方法返回CompletableFuture之后,在其中进行了一些长操作。我从多个线程(大约100个)同时调用方法“/ user”。

@Transactional
public Future<String> addUser(UserInfo userInfo) {
    userDao.persist(userInfo);
    return CompletableFuture.supplyAsync(() -> {
        try {
            Thread.sleep(10000);
            return "Result";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "Error";
    });
}

如果阻塞当前线程的代码行“voidCompletableFuture.get()”被调用,那么只有20个并发请求正在工作,并且通过最大连接数将数据添加到数据库。另一个线程中有异常:

Caused by: java.sql.SQLTransientConnectionException: Connection is not available, request timed out after 30000ms.

如果我删除这行代码,那么每个请求都在工作,并按预期将数据添加到数据库。我认为这是因为如果我之后调用future.get(),则在方法“public Future addUser(UserInfo userInfo)”结束后事务未完成。 也许有人知道为什么Spring和CompletableFuture以这样的方式工作,或者可能还有另一个答案?为什么阻止CompletableFuture会影响另一种方法中的Transaction结束?如果请求方法中存在阻塞,为什么方法不完成当前事务而不释放连接。

1 个答案:

答案 0 :(得分:1)

添加spring.jpa.open-in-view=false事务后,在方法setUser()之后开始停止,而不是在请求的整个过程中停止。

来自文档: spring.jpa.open-in-view=true - Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request.