0

In my Configuration class I need to run a method as a cronjob. So I created a method by using the @Scheduled annotation.

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

The ThemeUpdate() method is now running in its own thread and I will lose my transaction. So I created another method by using the @Transactional annotation.

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

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

    return null;
}

I get my List<Service> services from my serviceRepository. But if I want to access a Section which is an Entity fetched by lazy loading why do I get a 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

What do I miss here?

EDIT:

Scheduled:

@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())) {
        ...
    }

1 Answer 1

1

You are locally calling getServices() so there is no transaction proxy for the local method call.

You should move your scheduled method in its own component and inject the component with the getServices() method.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks its working now. But the selects are 50 times slower than the normal proecessing without @Schedule and @Transactional. Any reason for that?
Have you had a look at the SQL statements that are executed by Hibernate? And if you are only selecting data you could try to set the transaction to @Transactional( readOnly = true )
The statement should be finished in ms. I can try to set the stuff readOnly. But it seems that the transaction is created after every loop. I edited my question to show the current way.
By the way. The readOnly flag makes the different. Took just 5 seconds instead of 20 minutes ^^. Why is that?
Spring will set the JDBC transaction into a read-only mode and this can have an impact of the database performance. Question: how many records do you read with findServices?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.