[英]Hibernate LazyInitializationException if entity is fetched in JWTAuthorizationFilter
我正在使用 Spring Rest。 我有一个名为 Operator 的实体,如下所示:
@Entity
@Table(name = "operators")
public class Operator {
//various properties
private List<OperatorRole> operatorRoles;
//various getters and setters
@LazyCollection(LazyCollectionOption.TRUE)
@OneToMany(mappedBy = "operator", cascade = CascadeType.ALL)
public List<OperatorRole> getOperatorRoles() {
return operatorRoles;
}
public void setOperatorRoles(List<OperatorRole> operatorRoles) {
this.operatorRoles = operatorRoles;
}
}
我也有对应的OperatorRepository extends JpaRepository
我定义了一个公开这个 API 的控制器:
@RestController
@RequestMapping("/api/operators")
public class OperatorController{
private final OperatorRepository operatorRepository;
@Autowired
public OperatorController(OperatorRepository operatorRepository) {
this.operatorRepository = operatorRepository;
}
@GetMapping(value = "/myApi")
@Transactional(readOnly = true)
public MyResponseBody myApi(@ApiIgnore @AuthorizedConsumer Operator operator){
if(operator.getOperatorRoles()!=null) {
for (OperatorRole current : operator.getOperatorRoles()) {
//do things
}
}
}
}
在我使 OperatorRoles 列表变得懒惰之前,这曾经有效; 现在,如果我尝试遍历列表,它会抛出 LazyInitializationException。
Operator 参数由扩展 Spring 的 BasicAuthenticationFilter 的过滤器从数据库中获取,然后以某种方式自动连接到 API 调用中。
我可以毫无问题地获得其他非延迟初始化的属性。 如果我做类似operator = operatorRepository.getOne(operator.getId());
,一切正常,但我需要在代码中的太多点中更改它。
据我了解,问题是当我到达 OperatorController 中的实际 API 时,用于在 BasicAuthenticationFilter 中获取 Operator 的会话不再打开。
我设法将所有内容都包装在 OpenSessionInViewFilter 中,但它仍然不起作用。
任何人都有任何想法?
很长一段时间我都遇到了同样的问题,并且一直在使用FetchType.EAGER
但今天我的脑海中出现了一些东西......
@Transactional
不起作用,所以我想“如果声明性事务不起作用?也许以编程方式起作用”他们确实这样做了!
基于Spring Programmatic Transactions 文档:
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
private final TransactionTemplate transactionTemplate;
public JwtAuthorizationFilter(AuthenticationManager authenticationManager,
PlatformTransactionManager transactionManager) {
super(authenticationManager);
this.transactionTemplate = new TransactionTemplate(transactionManager);
// Set your desired propagation behavior, isolation level, readOnly, etc.
this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}
private void doSomething() {
transactionTemplate.execute(transactionStatus -> {
// execute your queries
});
}
}
你可能会迟到,但我希望它可以帮助其他人。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.