Spring数据@Transaction未按顺序执行

时间:2019-07-03 12:58:55

标签: spring spring-data-jpa spring-data spring-transactions spring-repositories

我的服务代码如下:

import javax.transaction.Transactional;

@Service
public class UserServiceImpl implements UserService {
    @Transactional
    @Override
    public void changeAuthorities(Long id, ChangeUserAuthoritiesRequest model) throws RecordNotFoundException {
        Optional<User> userOptional = userRepository.findById(id);
        if (userOptional.isPresent()) {
            User user = userOptional.get();
            long result = userAuthoritiesRepository.removeByUser(user);
//            System.out.println(userAuthoritiesRepository.findByUser(user));
            model.getAuthorityIds().stream().forEach(authorityId -> {
                UserAuthority userAuthority = new UserAuthority();
                Authority authority = authorityRepository.findById(authorityId).get();
                userAuthority.setUser(user);
                userAuthority.setAuthority(authority);
                userAuthoritiesRepository.save(userAuthority);
            });
        } else {
            throw new RecordNotFoundException("User not found with id: " + id);
        }
    }
}

代码的意思是“删除具有给定id的所有记录,然后再次添加新记录”(新记录可能与旧记录相同)。 我的问题是userAuthoritiesRepository.removeByUser(user)在保存新记录之前未执行方法userAuthoritiesRepository.save(userAuthority)。因此该应用引发了异常:

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Violation of UNIQUE KEY constraint 'user_authority_unique'. Cannot insert duplicate key in object 'dbo.user_authorities'. The duplicate key value is (1, 1).
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:258)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1535)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:467)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:409)
    at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:7151)
    at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:2478)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:219)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:199)
    at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:356)
    at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)
    at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)
    ... 177 more

1 个答案:

答案 0 :(得分:1)

@Transaction批注或代码的执行顺序没有问题。只是更改没有被推送到数据库。所以你会得到那个错误。

在调用flush()方法之后,您必须调用removeByUser()方法以将更改推送到数据库。

您可以检查this link了解为什么需要