[英]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.