Spring data @Transaction не выполняется по порядку - PullRequest
0 голосов
/ 03 июля 2019

Код моей службы ниже:

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);
        }
    }
}

Код означает «удалить все записи с заданным идентификатором и затем добавить новые» (новые могут совпадать со старыми).Моя проблема заключается в том, что метод 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 Ответ

1 голос
/ 05 июля 2019

Нет ничего плохого в аннотации @Transaction или порядке выполнения вашего кода.Просто изменения не передаются в базу данных.Итак, вы получаете эту ошибку.

Вам нужно будет вызвать метод flush() после вызова метода removeByUser(), чтобы отправить изменения в базу данных.

Вы можете проверить эту ссылку , чтобы понять, зачем она нужна

...