【问题标题】:Spring-data-jpa lazy loading in @Scheduled and @Transactional methods@Scheduled 和 @Transactional 方法中的 Spring-data-jpa 延迟加载
【发布时间】:2018-08-31 12:03:50
【问题描述】:

在我的配置类中,我需要将方法作为 cronjob 运行。所以我使用@Scheduled注解创建了一个方法。

@Scheduled(initialDelay = 10 * 1000, fixedRate = 1000 * 1000)
public void ThemeUpdate() {
    List<ThemeIndex> indices = getServices();
    ...
}

ThemeUpdate() 方法现在在它自己的线程中运行,我将丢失我的事务。所以我使用@Transactional 注解创建了另一个方法。

@Transactional
public List<ThemeIndex> getServices() {
    List<Service> services = serviceRepository.findServices();

    Section section = services.get(0).getSections().iterator().next();

    return null;
}

我的List&lt;Service&gt; services 来自我的serviceRepository。但是,如果我想访问 Section,这是通过延迟加载获取的 Entity,为什么我会得到 LazyInitializationException

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.myPorject.db.model.Service.sections, could not initialize proxy - no Session

我错过了什么?

编辑:

预定:

@Scheduled(initialDelay = 10 * 1000, fixedRate = 10000 * 1000)
@Transactional
public void ThemeUpdate() {
    List<ThemeIndex> indices = themeUpdateServiceImpl.getIndices();
}

getIndices():

@Override
public List<ThemeIndex> getIndices() {
    return getIndices(serviceRepository
        .findServices());
}

@Override
public List<ThemeIndex> getIndices(List<Service> services) {
    return themeIndexServiceImpl.getThemeIndexes(services);
}

getThemeIndexes():

@Override
public List<ThemeIndex> getThemeIndexes(List<Service> services) {
    List<ThemeIndex> themeIndexs = new ArrayList<>();
    for (Service s : services) {
        ThemeIndex themeIndex = getThemeIndex(s);
        if (themeIndex != null) {
            themeIndexs.add(themeIndex);
        }
    }
    return themeIndexs;
}

@Override
public ThemeIndex getThemeIndex(Service service) {
    //SQL which is slow
    if (serviceRepository.isEpisService(service.getSvno())) {
        ...
    }

【问题讨论】:

    标签: java hibernate spring-boot spring-data-jpa


    【解决方案1】:

    您在本地调用 getServices(),因此本地方法调用没有事务代理。

    您应该将计划的方法移动到它自己的组件中,并使用 getServices() 方法注入该组件。

    【讨论】:

    • 感谢它现在的工作。但是选择比没有@Schedule@Transactional 的正常处理慢50 倍。有什么理由吗?
    • 你看过Hibernate执行的SQL语句吗?如果您只选择数据,您可以尝试将事务设置为 @Transactional(readOnly = true)
    • 语句应该在毫秒内完成。我可以尝试将内容设置为只读。但似乎事务是在每个循环之后创建的。我编辑了我的问题以显示当前的方式。
    • 顺便说一句。 readOnly 标志与众不同。只用了 5 秒而不是 20 分钟 ^^。这是为什么呢?
    • Spring 会将 JDBC 事务设置为只读模式,这会对数据库性能产生影响。问题:您使用 findServices 读取了多少条记录?
    猜你喜欢
    • 2022-09-29
    • 2011-05-11
    • 2013-11-02
    • 2017-07-23
    • 2018-03-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多