使用JPA将两个类映射到一个表,以加快Spring Security UserDetailsS​​ervice的速度

时间:2014-07-22 15:48:15

标签: java spring hibernate spring-mvc jpa

我想使用Spring,JPA和Hibernate提供安全的restful服务。

每个端点都必须是安全的,我使用Spring安全性来使用特定的UserDetailsS​​ervice,如spring安全文档中所述: http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#userdetailsservice-implementations

这一点:由于每个请求都将被验证,这意味着对于每个请求,我的UserDetailsS​​ervice将从我的数据库加载用户,并需要获取其密码及其角色。

默认的JdbcDaoImpl使用2个请求来查找用户及其角色。 我不使用它,因为:

  • 我想在UserDetails对象中拥有用户ID,因为我的业务控制器使用它。
  • 我希望我的用户只加载一个请求

我的用户业务对象如下:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "aa_user")
public class User
{
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   Long id;

   @NotNull
   @Column(unique = true)
   protected String login;

   protected String password;

   @ManyToMany(targetEntity = Role.class)
   protected List<Role> roles;

   //getter/setter
}

我的存储库:

public interface UserRepository extends JpaRepository<User, Long>
{
    @Query("SELECT u FROM User u JOIN FETCH u.roles where u.login = :login")
    User findByLogin(@Param("login") String login);
}

我的UserDetailsS​​ervice:

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
    User user = null;
    try
    {
        user = userRepository.findByLogin(username);
    } catch (Throwable e) {
        e.printStackTrace();
        throw new UsernameNotFoundException("Can't find username: " + username);
    }
    if (user == null) {
        throw new UsernameNotFoundException("Can't find username: " + username);
    }

    UserDetailsImpl userDetails = new UserDetailsImpl(user);

    return userDetails;
} 

我有很多User子类(比如Seller,...),这些子类与其他对象有关联以获取业务目的,并且通过这种实现,userRepository.findByLogin(username)会产生类似于3个或更多重连接的东西我是正确的完全获取用户对象(当然是“正常”),但我只想要一个只有初始化用户字段的轻量级查询。

根据这个问题: Avoiding outer joins across tables when using joined inheritance with Spring Data JPA我想做的事情似乎很复杂,但我发现我可以使用@Polymorphism Hibernate注释PolymorphismType.EXPLICIThttps://stackoverflow.com/a/18358863/1661338

@Polymorphism不符合JPA标准并制定我的业务逻辑部分或需要我重构大量查询。

为了避免这种情况,我添加了一个映射在同一个表上的第二个类:

@Entity
@Table(name = "aa_user")
public class LightUser implements SimpleUser
{  
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO)
   Long id;

   @NotNull
   @Column(unique = true)
   protected String login;

   protected String password;

   @ManyToMany(targetEntity = Role.class)
   protected List<Role> roles;

   //getter
}

我的存储库:

public interface LightUserRepository extends JpaRepository<User, Long>
{
    @Query("SELECT u FROM LightUser u JOIN FETCH u.roles where u.login = :login")
    LightUser findByLogin(@Param("login") String login);
}

UserLightUser都实现了与我SimpleUser所需的所有getter相同的UserDetailsImpl接口。

现在,lightUserRepository.findByLogin(username)使最聪明的查询成为可能,并且只获取我想要的内容。

我仍然有疑问:

  • 是否符合JPA标准?
  • hbm2ddl.SchemaExport工作但尝试在表aa_user和角色表之间放置2次相同的外键。如何避免?
  • 如果我可以使用与PolymorphismType.EXPLICIT相同的行为进行查询,那么写作可能会少一些。有谁知道这是否可能?
  • LightUser可以成为“readOnly”对象以避免错误吗?

0 个答案:

没有答案