繁体   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