我的服务代码如下:
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
答案 0 :(得分:1)
@Transaction
批注或代码的执行顺序没有问题。只是更改没有被推送到数据库。所以你会得到那个错误。
在调用flush()
方法之后,您必须调用removeByUser()
方法以将更改推送到数据库。
您可以检查this link了解为什么需要