Hibernate Sessions in Quartz Job in Spring - spring

TL;DR: Do I need to manually setup a Hibernate session around the Quartz job invocation?
I have quartz scheduler running in Spring but have very strange behaviour when it comes to using Hibernate in the Quartz job.
I have JPA repositories, and using these as below works as expected.
Reservation reservation = reservationRepo.findOne(resId);
However, when I try to use this entity as follows I get the subsequent exception
User owner = reservation.getRoom().getOwner();
Exception:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
If I set the spring logging to TRACE I see some JPA/Transaction/Thread magic, but it seems like it's all sorted out per-call to beans used, and no managed hibernate session exists on the Thread.
Do I need to somehow craft a Hibernate session around the Quartz job invocation?

Related

Running a statement for each transaction in Spring Boot

I want to set a PostgreSQL transaction timeout for each Spring transaction like so:
SET LOCAL lock_timeout = '10s';
How can I extend Spring to do that?
I am not using Hiberante, but jOOQ, so setting a queryHint does not work in my case.
You could provide your own extended transaction manager and add the behaviour in the appropriate spot, probably in the begin method.

Configuring Spring Boot to use both H2 AND Oracle at the same time

I am writing a Spring Batch job and don't care about restarts and don't want the hassle of creating, securing and managing an Oracle schema for Spring Batch database objects. H2 on the file system is more than enough for us.
The issue is that I am writing an batch job that needs to connect to an Oracle database and failing miserably just trying to get 2 data sources, transaction managers and entity managers. Right now I am trying two H2 database and haven't even tried configuring Oracle database yet.
I have used two Oracle data sources in other Spring Boot applications successfully in the past but this is my first attempt with Spring Batch that has configuration code to create the data source.
I have tried creating two DataSource, EntityManagerFactoryBean and TransactionManager with one using default spring.datasources configuration, default bean names and #Primary.
I have tried creating just a second DataSource, EntityManagerFactoryBean and TransactionManager with different bean names. This seems to have an issue that the TransactionManager orEntityManager is already assigned to the thread.
I have tried creating a dataSource for batch but run into circular bean creation errors.
I have tried creating a BatchConfigurer and that runs into circular bean creation errors.
I have tried creating a JobRepositoryFactoryBean but a default one is still created.
I have tried using a #PersistenceContext on my #Entity classes.
It shouldn't be this hard so I must be missing something. Any help would be appreciated.
Thanks, Wes.
I think I have some success. I am able to eventually run the batch job using Spring Boot 2.2.0 and Spring Batch 4.2.0 but I have to wait for a 5 minute timeout while creating the Entity Manager for H2 for the Spring Batch repository. The Oracle Entity Manager is registered really quickly and before the H2 Entity Manager despite the H2 Entity Manager being #Primary.
I have a separate configuration class for each of my two DataSources. Each one is annotated with #Configuration, #EnableTransactionManagement and #EnableJPARepository.
The one for Spring Batch is using the standard bean names, dataSource, entityManagerFactory and transactionManager. Each #Bean is annotated with #Primary.
One setting that I needed was to add a .packages("org") to the entityManagerFactory bean. This would pick up all of org.springframework including Spring Batch.
The only other real change I have made from common implementations is to set the dialect in the JPA Properties of the Entity Manager.
I needed the spring.main.allow-bean-definition-overriding: true setting.
There may be more to my solution that I should share but I have been at this for a couple of days and have gone in circles. I even remember getting what appeared as a hung process time and and killed the job thinking it was hung. I may have had some "success" early on but just was too quick to kill the execution.
I would still like to know why it is taking so long to create the H2 Entity Manager.
Thanks, Wes.

Using multiple embedded datastores with Spring Boot

I'm trying to set up a Spring Boot application using Spring Data JPA, Neo4J and MongoDB. The goal is to be able to save different entities in each datastore, as well as using cross-store entities.
The project seems to work well with each store individually, but saving a JPA entity raises this exception :
org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'persist' call
This exception is not raised if I remove all neo4J and mongoDB related code.
Here is a link to the project on github :
GitHub
I managed to get it working by using the configuration of this project.
It looks like I had to add an "transactionManagerRef" attribute to the #EnableJpaRepositories annotation, a bit more configuration for Transition Managers, and modify some dependencies.

spring-boot-jpa Initial Entity Persistence

I'm trying to figure out how, in the lifecycle of a Spring Boot application, to conditionally persist a single entity when the application starts up. The normal method of loading initial data via 'import.sql' or similar methods is no good in this use case, because the insert is conditional. On start up, I'd like for my application to check and see if an admin account and the associated admin role exists. If neither exists, I'd like the application to create them. If they do exist, I'd like the application to do nothing and leave the existing entities alone. If I use the import.sql method, I'll either wind up with a duplicate key (username=admin) or I'll overwrite the existing admin account, which may have had it's password changed away from the default password by a previous installation of the application.
I've tried using ApplicationListeners for all the default Spring and Spring Boot events, and I get null pointer exceptions for every one of those listeners because the JPA repositories are not yet initialized. I thought that listeners invoked for the ContextRefreshedEvent were supposed to be called after all beans and such are initialized, but I guess I'm wrong about that. I've also tried to create a bean which has a #PostConstruct annotated method which does this entity creation, however I had the same result with the JPA CrudRepositories not being initialized.
So my base question is; "What is the preferred entry point for doing initialization work with JPA CrudRepositories during Spring Boot application start up?"
ContextRefreshedEvent would normally work (so you may have an initialization ordering problem with your listener). You can also use SmartInitializingSingleton or a SmartLifecycle with autostart=true. In a Spring Boot app you also have CommandLineRunner.

Should one close Hibernate Session object every time after performing any CRUD operation?

I am working with enterprise application that uses Spring 3.x with Hibernate annotated programming.I am working with hibernate Session object for performing db operations in my XYZDaoImpl class.
And my doubt is "Is it correct way to close Hibernate Session object every time after performing any CRUD operation?"
If it is not the correct way, please advise me the recommended way of opening/closing of hibernate Session Object.
can you post a bit daoImpl code......
If you use sessionFactory.getCurrentSession(), you will get current session..in this case framework automatically flushed and closed when the transaction ends (commit or rollback).
If you use sessionFactory.openSession(), you have to manage the session yourself and to flush and close it "manually".
No, when using hibernate with spring, you should not (manually) open or close sessions, but let spring manage the hibernate session for you. Spring manages the session as a transactional resource, so you have to configure transaction management correctly.
If you open/close the hibernate session manually, you are hardly using the integration between these two frameworks: the session management is the main feature of the integration.
The only reason to open/close a hibernate session in a spring context is to use the same session to span multiple transactions.

Resources