【发布时间】:2017-05-29 11:50:41
【问题描述】:
我一直在使用 Spring 4 的 UserDetailsManager 创建用户,架构是他们的文档为 USERS 和 AUTHORITIES 表建议的架构。
我也一直在使用 Spring Data @Repository 注释接口来管理单独的 REGISTRATIONS 表中的数据,该表被定义为与 USERS 表中的 username 字段有关系。
我一直面临的问题是,当我希望删除用户时,我首先使用注入的 Spring Data 存储库从REGISTRATIONS 表中删除记录,然后使用@987654330 调用deleteUser() @。 (这只是@Service 注释类中@Transactional 方法中的两个连续调用)。
例如
registrationsRepository.delete(uuid);
userDetailsManager.deleteUser(registration.getUsername());
但是,用户删除失败,因为REGISTRATIONS 表(第一行)中的记录尚未删除。随后我收到一个异常(第 2 行)抱怨无法删除用户,因为 REGISTRATIONS 表中有外键约束阻止它被删除。
如果这些更新发生在同一个事务中,为什么会失败?
编辑:
@Repository
public interface RegistrationsRepository extends CrudRepository<Registration, UUID>
{
// No EntityManager injected - uses Spring Data method queries
// No additional methods defined
}
注册表定义如下:
CREATE TABLE Registrations (
username varchar(64) NOT NULL REFERENCES Users (username),
uuid UUID NOT NULL PRIMARY KEY
);
【问题讨论】:
-
第一次删除后尝试刷新 EntityManager。
-
注册实体是否引用了用户实体?还是只是某种映射到 FK 的 id?
-
补充 Guillaume 的建议:delete() 不会删除实体。它标记要删除的实体。删除行的实际 SQL 查询仅在刷新时执行。
-
@GuillaumeF。我已经更新了我的问题以提供更多信息。我曾考虑过这一点,但这意味着我必须将 EM 单独注入我的服务类并单独调用
flush()- 感觉不对。我也不确定它是否与事务使用的相同,因为我已经阅读了@Transactional 可以从 EM 工厂创建一个新的 EM 并在事务开始时绑定到线程。 -
这就是为什么你应该调用flush()。如果没有刷新,用户行的删除发生在 注册行的删除之后。因为 delete() 不会删除。它仅将实体标记为删除。 flush() 是强制 JPA 执行删除 SQL 语句的原因。
标签: java spring-mvc jpa spring-data spring-transactions