Java 使用JPA将两个类映射到一个表,以加快spring security UserDetailsService的速度
我想使用Spring、JPA和Hibernate创建一个安全的restful服务 必须保护每个端点,为此,我使用特定的UserDetails服务使用spring安全性,如spring安全文档中所述: 这里的要点是:由于每个请求都将经过身份验证,这意味着对于每个请求,my UserDetails服务将从我的数据库中加载一个用户,并需要获取其密码和角色 默认的JdbcDaoImpl使用2个请求来查找用户及其角色。 我不使用它,因为:Java 使用JPA将两个类映射到一个表,以加快spring security UserDetailsService的速度,java,spring,hibernate,spring-mvc,jpa,Java,Spring,Hibernate,Spring Mvc,Jpa,我想使用Spring、JPA和Hibernate创建一个安全的restful服务 必须保护每个端点,为此,我使用特定的UserDetails服务使用spring安全性,如spring安全文档中所述: 这里的要点是:由于每个请求都将经过身份验证,这意味着对于每个请求,my UserDetails服务将从我的数据库中加载一个用户,并需要获取其密码和角色 默认的JdbcDaoImpl使用2个请求来查找用户及其角色。 我不使用它,因为: 我希望在我的业务控制器使用UserDetails对象时,将我的
- 我希望在我的业务控制器使用UserDetails对象时,将我的用户Id放在UserDetails对象中
- 我希望我的用户只加载一个请求
@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
}
我有很多用户子类(比如Seller,…),它们与出于业务目的而急切获取的其他对象有关联,userRepository.findByLogin(username)
生成3个或更多重连接,以提供正确的完整获取用户对象(当然这是“正常的”),但是我只需要一个只初始化用户字段的light查询
根据这一问题:
我想做的事情似乎很复杂,但我发现我可以将@polymorphics
Hibernate注释与PolymorphismType.EXPLICIT
:
@polymorphics
不符合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
}
@实体
@表(name=“aa_用户”)
公共类LightUser实现SimpleUser
{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
长id;
@NotNull
@列(唯一=真)
受保护的字符串登录;
受保护的字符串密码;
@ManyToMany(targetEntity=Role.class)
受保护的列表角色;
//吸气剂
}
和我的存储库:
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);
}
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);
}
公共界面LightUserRepository扩展了JpaRepository
{
@查询(“从LightUser中选择u u加入获取u.roles,其中u.login=:login”)
LightUser findByLogin(@Param(“login”)字符串login);
}
User
和LightUser
使用myUserDetailsImpl
所需的所有getter实现相同的SimpleUser
接口
现在,lightUserRepository.findByLogin(用户名)
使最智能的查询成为可能,并且只得到我想要的
我还有问题:
- 它符合JPA吗
工作,但尝试在表hbm2ddl.SchemaExport
和角色表之间放置两次相同的外键。如何避免这种情况aa_user
- 如果我可以使用与
相同的行为进行查询,那么编写代码时可能不会那么痛苦。有人知道这是否可能吗PolymorphismType.EXPLICIT
- LightUser能否成为“只读”对象以避免错误
@polymorphics
是@heritation
。它允许您使用单表或联接多表。众所周知,Joined存在一些性能问题。如果使用单表,则该表将包含所有字段,并且这些字段中允许为空,因此可能会丢失一些数据完整性强制。单个表要求您在父对象上指定一个@DiscriminatorColumn
,在子对象上指定一个@DiscriminatorValue
,以标识JPA需要构建的对象。此处的更多信息:@polymorphics
和@heritation
的目标不同:-@heritation
正如您所解释的,更改JPA在DB中存储对象的方式,实际上会对性能产生影响,但在从DB加载对象时不阻止自动多态性-@polymorphics
仅适用于Hibernate,并且在从DB加载对象时可以防止自动多态性。看,我所做的只是使用
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);
}