首页 > 解决方案 > @PostConstruct 中的 org.hibernate.LazyInitializationException

问题描述

我有一个带有嵌入式 Derby 的 SpringBootApp;工作正常。当我实现 CommandLineRunner 或 @PostConstruct 时出现上述错误

“org.hibernate.LazyInitializationException 无法延迟初始化角色集合:...- 无法初始化代理 - 无会话”。

如何在应用程序实际运行之前但在加载 applications.properties 文件之后创建与 Hibernate 的会话?另外,SprinBoot 在其他地方做了什么来防止正常运行中出现此错误?

 @Component
@Transactional
public class DatabaseTesting01 {
    private static Logger logger = LoggerFactory.getLogger(DatabaseTesting01.class);
    @Autowired
    EDITypeService ediTypeService;
    @Autowired
    VendorService vendorService;
    @Autowired
    SubscriberService subscriberService;
    @PostConstruct
    public void init(){
        Vendor v = vendorService.findOneByShortName("UNFI");
        logger.debug("Vendor:UNFI"+v.toString());
    }
}

更新这是有效的。HTH。

@Component
@Service("database01")
public class Database01 {
    private static Logger logger = LoggerFactory.getLogger(Database01.class);
    @Autowired
    @Qualifier("transactionManager")
    protected PlatformTransactionManager txManager;
    @Autowired VendorService vendorService;

    @PostConstruct
    private void init(){
        TransactionTemplate tmpl = new TransactionTemplate(txManager);
        tmpl.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                vendorService.deleteAll();
            }
        });
    }
}

标签: hibernatespring-data-jpa

解决方案


对类所做的唯一事情@Transactional是将事务功能(创建代理等)应用于所有公共方法。所以你不应该依赖初始化代码,比如@PostConstruct. 这是适当的弹簧参考

在代理模式下(默认),只有通过代理传入的外部方法调用会被拦截。这意味着自调用(实际上,目标对象中的一个方法调用目标对象的另一个方法)不会导致运行时的实际事务,即使调用的方法标有@Transactional。此外,代理必须完全初始化以提供预期的行为,因此您不应在初始化代码(即@PostConstruct)中依赖此功能。

UPD

在您的情况下,主要问题是加载供应商角色的一对多列表。由于交易不存在,这是一种可预测的行为。我希望这个主题能帮助你解决问题,但无论如何问问自己——真的有必要在 a 中做这样的事情@PostCunstruct吗?如果没有,您可以在存储库中实现另一种方法,使用投影jpql 构造函数来摆脱连接实体的加载


推荐阅读