无法从@Transaction中的两个表中删除关系

时间:2017-01-14 01:39:00

标签: java spring-mvc jpa spring-data spring-transactions

我一直在使用Spring 4的UserDetailsManager来创建用户,该模式是他们的文档为USERSAUTHORITIES表建议的模式。

我也一直在使用Spring Data @Repository带注释的接口来管理单独的REGISTRATIONS表中的数据,该表被定义为在{{1} username字段上有关系表格。

我遇到的问题是,当我想删除用户时,我首先使用注入的Spring Data存储库从USERS表中删除记录,然后调用REGISTRATIONS使用deleteUser()。 (这只是UserDetailsManager注释类中@Transactional方法中的两个连续调用。

例如

@Service

但是,删除用户失败,因为registrationsRepository.delete(uuid); userDetailsManager.deleteUser(registration.getUsername()); 表(第1行)中的记录尚未删除。随后我得到一个异常(第二行)抱怨无法删除用户,因为REGISTRATIONS表中存在外键约束,导致其被删除。

如果这些更新发生在同一个事务中,为什么会失败?

编辑:

REGISTRATIONS

注册表定义如下:

@Repository
public interface RegistrationsRepository extends CrudRepository<Registration, UUID>
{
    // No EntityManager injected - uses Spring Data method queries
    // No additional methods defined
}

1 个答案:

答案 0 :(得分:1)

因此,据我了解,Spring的UserDetailsManager使用JDBC调用删除&#39;用户&#39;和当局&#39;来自各自的表格。

我的注册&#39;实体由EntityManager管理,该用户与“用户”之间没有明确的关系(在ORM级别)。记录。这种关系纯粹是在DB级别指定的。

EntityManager会标记注册&#39;要删除的实体,而UserDetailsManager实际上会删除&#39;用户&#39;这是在事务结束时刷新EntityManager之前发生的。这是因为注册&#39;实体尚未被删除,事务仍未完成,但JDBC调用已经尝试删除用户和&#39;当局&#39;。

为了解决这个问题,我做了以下工作。

class DefaultService implements MyService {

    private final EntityManagerFactory emf;

    // Inject RegistrationRepository and UserDetailsManager...

    @Inject
    public DefaultService(EntityManagerFactory emf, ...) {
        // ...
        this.emf = emf;
    }

    @Override
    @Transactional
    public void serviceMethod(UUID uuid, String username) {
        registrationsRepository.delete(uuid);

        // Flush the entity manager to remove this record from the DB first.
        EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(emf);
        entityManagerHolder.getEntityManager().flush();

        // These will be JDBC calls, 'users' are not managed entities
        userDetailsManager.deleteUser(username);
    }
}

我以这种方式获得了EntityManager,以确保我为此事务获得绑定到此线程的正确结果。如果这是矫枉过正或有更好的方法,请发表评论!

希望有人帮助。并且是对的!