我想使用Spring,JPA和Hibernate提供安全的restful服务。
每个端点都必须是安全的,我使用Spring安全性来使用特定的UserDetailsService,如spring安全文档中所述: http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#userdetailsservice-implementations
这一点:由于每个请求都将被验证,这意味着对于每个请求,我的UserDetailsService将从我的数据库加载用户,并需要获取其密码及其角色。
默认的JdbcDaoImpl使用2个请求来查找用户及其角色。 我不使用它,因为:
我的用户业务对象如下:
@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);
}
我的UserDetailsService:
@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.EXPLICIT
:
https://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);
}
User
和LightUser
都实现了与我SimpleUser
所需的所有getter相同的UserDetailsImpl
接口。
现在,lightUserRepository.findByLogin(username)
使最聪明的查询成为可能,并且只获取我想要的内容。
我仍然有疑问:
hbm2ddl.SchemaExport
工作但尝试在表aa_user
和角色表之间放置2次相同的外键。如何避免?PolymorphismType.EXPLICIT
相同的行为进行查询,那么写作可能会少一些。有谁知道这是否可能?