2

通过在我的 Spring Roo / Hibernate - JPA / Spring MVC / Spring Security 应用程序中选择以下类层次结构,我可能使我的生活变得比必要的复杂:

DomainBase(审计字段 - 为 lastUpdatedBy 和 createdBy 字段引用 AbstractUsers,所以循环依赖...(!))

@ManyToOne(fetch=FetchType.LAZY)
@CreatedBy
private AbstractUser createdBy;

@ManyToOne(fetch=FetchType.LAZY)
@LastModifiedBy
private AbstractUser lastModifiedBy;

^

|

AbstractUser(包含一般用户信息,如名称和字符串用户 ID)

@NotNull
@ManyToMany(fetch = FetchType.LAZY)
@Immutable
private Set<UserRole> roles;

^

|

操作员、消费者、客户(具体用户)、系统用户

其他域类派生自 DomainBase。

我使用以下 Auditor 实现:

public class SpringSecurityAuditorAware implements AuditorAware<AbstractUser> {

    public AbstractUser getCurrentAuditor() {

        Authentication authentication = SecurityContextHolder.getContext()
                .getAuthentication();

        return ((AbstractUser) authentication.getPrincipal());
    }
}

我的实现UserDetailsService包含以下内容:

userDetails = operatorRepository.findByUsername(username);

if (userDetails != null) {
    // overcome lazy load
    Collection<? extends GrantedAuthority> roles = userDetails
            .getAuthorities();
    roles.size();
    return userDetails;
}

不幸的是,JPA Transaction 和 Hibernate/JPA Session 之间的关系在我脑海中仍然不清楚,尽管我尝试使用文档和谷歌搜索。在 AuthenticationManager 询问我的 UserDetailsS​​ervice 时,显然有一个实时会话,并且返回的用户实体与持久会话(实时)相关联,并且角色被读取并用于确定以后的授权结果。在稍后的某个时间点,当用户发出涉及调用@Transactional导致更改或创建新实体的服务方法的请求时,AuditorAware<>侦听器触发并将存储在该对象中的引用分配SecurityContext给该对象,并随后被持久化。

我知道问多个问题是不好的形式,但它们都与这种特定的安排相互关联。

1)制作用户对象的深层副本以存储在 中是否更好的做法SecurityContext,如果是这样,那么当审计员被解雇时获取“活动”实体的合理策略是什么(除了每次都查询存储库)?

2)在处理域对象时,我对持久化用户实体并不真正感兴趣,并尝试设置,cascade=CascadeType.REFRESH但我当然遇到了在休眠会话的上下文中瞬态的用户对象。我考虑过简单地将用户 ID 存储在其中,DomainBase但随后我失去了在需要时懒惰地获取用户详细信息的能力。我可以在这里遵循“最佳实践”吗?

评论:对于试图同时与两个会话关联的同一用户的用户角色集合,我似乎经常遇到麻烦(我有后台计划作业,我怀疑我过分热心的日志记录extends CustomizableTraceInterceptor可能有很多与它有关)。

任何指导表示赞赏...

4

0 回答 0