簡體   English   中英

如果在 JWTAuthorizationFilter 中獲取實體,則休眠 LazyInitializationException

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM