使用JpaRepository更新审核和版本控制实体

时间:2018-09-19 14:31:27

标签: java hibernate spring-boot spring-data-jpa

我有一个Spring Boot应用程序,它具有简单的Entity以及JpaRepository和Service。

实体

@Getter
@Setter
@EntityListeners(AuditingEntityListener.class)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    @Version
    private Long version;

    @CreatedDate
    private LocalDateTime created;

    @LastModifiedDate
    private LocalDateTime lastModified;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String lastModifiedBy;

    private String name;

    private String email;

}

JpaRepository

@Repository
public interface UserRepository extends JpaRepository<User, Long> {}

服务

@Service
class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public User create(User user) {
        Assert.isNull(user.getId(), "Can't create an existing user!");
        return userRepository.saveAndFlush(user);
    }

    @Transactional
    public User update(User user) {
        Assert.notNull(user.getId(), "Can't update a new user!");
        return userRepository.saveAndFlush(user);
    }

}
  

在我的实际应用程序中,@Transactional中设置了RestController批注,但是create()update()从未在同一事务中执行

当我这样创建新用户时:

User user = new User();
user.setName("user");
user.setEmail("user@email");
userService.create(user);

Spring会自动将所有Auditing属性(创建,lastModified等)设置为0。

但是当我像这样更新现有用户时:

User user = new User();
user.setId(1L);             // Id of the User I want to update
user.setVersion(5L)         // Current version is 5L
user.setName("user");  
user.setEmail("new@email"); // I want to update only the email
userService.update(user);

我收到此错误:

org.postgresql.util.PSQLException: ERROR: null value in column "created" violates not-null constraint

这意味着Spring审核未处理created属性。

要解决此问题,我已通过以下方式在update中更改了UserService方法:

@Transactional
public User update(User user) {
    Assert.notNull(user.getId(), "Can't update a new user!");
    User original = userRepository.getOne(user.getId())
    original.setVersion(user.getVersion());
    original.setName(user.getName());
    original.setEmail(user.getEmail());
    return userRepository.saveAndFlush(original);
}

此命令修复了PSQLException,但是此版本不再经过验证。这意味着,如果我在数据库中设置的版本与当前版本不同,则不会出现ObjectOptimisticLockingFailureException错误,并且更新后的用户将被保存在数据库中而没有任何错误。

  

我可以将.getOne()替换为.findById(),但没有任何变化

最后,我已经能够以这种方式解决我的两个问题:

@Transactional
public User update(User user) {
    Assert.notNull(user.getId(), "Can't update a new user!");
    Assert.notNull(user.getVersion(), "Version must be defined!");
    User original = userRepository.getOne(user.getId())
    User update = new User();
    update.setId(original.getId());
    update.setCreated(original.getCreated());
    update.setCreatedBy(original.getCreatedBy());
    update.setVersion(user.getVersion());
    update.setName(user.getName());
    update.setEmail(user.getEmail());
    return userRepository.saveAndFlush(update);
}
  

我仍然需要检查版本是否为null,否则用户将被保存而不检查版本

现在,审核字段不会抛出PSQLException,并且版本会在更新之前进行验证,并且在错误时会抛出ObjectOptimisticLockingFailureException

但是此解决方案糟糕,因为我需要左右复制属性,在较大的实体中,很容易忘记某些东西。

您知道此问题的更好解决方案吗?

0 个答案:

没有答案