I am using JPA 2.0 with EclipseLink, Glassfish, and NetBeans. I am experiencing issues with connection timeouts after extended periods of inactivity. I've looked pretty hard for ways to either:
(1) Check for JPA's connection and then re-establish its connection if disconnected
(2) Keep the JPA's connection active as much as possible
However, I can't really find a solution for either. The closest thing I can find is this post: How To modify Eclipselink JPA 2.0 connection retry behavior .
If there is someway to directly work with the JPA's connection, it'd be nice but it's buried within the library.
What you state you are looking for is usually provided by the datasource, in this case it would be configurable in Glassfish as described here:
https://blogs.oracle.com/JagadishPrasath/entry/connection_validation_in_glassfish_jdbc
If you want to do this without a datasource, for instance by passing a URL to the provider and have it handle connections, it will be EclipseLink specific. EclipseLink does have options that can be configured when it attempts to reconnect and retry queries, such as the
public void setPingSQL(String pingSQL)
public void setQueryRetryAttemptCount(int queryRetryAttemptCount)
public void setDelayBetweenConnectionAttempts(int delayBetweenConnectionAttempts)
methods that can be set on the DatabaseLogin or DatabasePlatform classes through a customizer.
Related
Off late, we have been getting hikari connection pools getting exhausted more than a couple of times. The exception being thrown is as follows:
"org.springframework.transaction.CannotCreateTransactionException:
Could not open JDBC Connection for transaction;
nested exception is java.sql.SQLTransientConnectionException:
HikariPool-1 - Connection is not available, request timed out after 30000ms."
What I have observed is that some unaware developers have added #Transactional annotation to a lot of simple get calls on the DB (Postgres).
We use JdbcTemplate to make DB calls with a default connection pool size of 10.
The public endpoints at the controllers are already annotated as #Transactional. Can adding the #Transactional annotation to the DAO Beans result in creation of nested connections when the service layer, which is a seperate bean, which calls the DAO layer is already #Transactional.
We also have a few scheduled CRON jobs, and I see that these are not exposed via a public api or exposed via a controller, but do I still need to add #Transactional to the parent level methods in such cron/internal methods to be able to optimally make db calls? We are not expecting changes to roll back for these cron jobs. We already use JdbcTemplate which uses Hikari Connection poo. Is #Transactional need at all in such cases to optimise performance.
All configurations are default spring boot configurations, so default Tx.Type is REQUIRED unless explicitly set.
#Transactional should be mainly use in service layer when you are about to use database connections, it should be used on minimum methods that represent a business flow.
I think you are over using it and may create unnecessary connections, thus create timeout on overloaded pool
Notice that you use only one database connection pool,as HikariCP, and not also PGBouncer for example.
Also see more performance/configuration tweaks for HikariCP in its wiki page
I have a question about how Spring Data repositories are handling the datasource connections. Assuming Spring Data repositories open and close the connection and the connection when the method executes, how does the transaction started by declaring #Transactional in my service layer span across multiple repository calls?
Who handles the database connections? The #Transactional annotation or the JPA repository?
tl;dr
Ultimately it's the Spring JPA / Transaction infrastructure managing the connection via the thead-bound management of EntityManager instances. The scope of the transaction is controlled by #Transactional annotations in the user code but ultimately defaulted in Spring Data JPA's repository implementation. Connection acquisition is performed eagerly in case an OpenEntityManagerInViewFilter is used (enabled by default in Spring Boot 1.x and 2.x).
Details
SimpleJpaRepository is equipped with Spring's #Transactional annotations so that it will make sure it runs transactions in cases JPA requires them (e.g. to execute a call to EntityManager.persist(…) or ….merge(…)). Their default configuration makes sure, they automatically take part in transactions started at higher levels of abstraction. I.e. if you have a Spring component that's #Transactional itself, repositories will simply participate in the already running transaction:
#Component
class MyService {
private final FirstRepository first;
private final SecondRepository second;
// Constructor omitted for brevity
#Transactional
void someMethod() {
… = first.save(…);
… = second.save(…);
}
}
Both repositories participate in the transaction and a failure in one of them will roll back the entire transaction.
To achieve that, the JpaTransactionManager will use the transaction management API exposed by JPA's EntityManager to start a transaction and acquire a connection for the lifetime of the EntityManager instance. See JpaTransactionManager.doBegin(…) for details.
The role of an OpenEntityManagerInViewFilter or –Interceptor
Unless explicitly deactivated, Spring Boot 1.x and 2.x web applications run with an OpenEntityManagerInViewFilter deployed. Its used to create an EntityManager and thus acquire a connection pretty early and keep it around until very late in the request processing, namely after the view has been rendered. This has the effect of JPA lazy-loading being available to the view rendering but keeps the connection open for longer than if it was only needed for the actual transactional work.
That topic is quite a controversial one as its a tricky balance between developer convenience (the ability to traverse object relations to loaded lazily in the view rendering phase) at the risk of exactly that triggering expensive additional queries and keeping the resources in use for a longer time.
Some tutorial says use org.postgresql.ds.PGConnectionPoolDataSource but some says just the org.postgresql.ds.PGSimpleDataSource... what is the difference between the two?
The difference is that the class org.postgresql.ds.PGConnectionPoolDataSource implements Connection Pooling, therefore it can provide some performance benefits.
According to the documentation:
Class PGSimpleDataSource
Simple DataSource which does not perform connection pooling. In order
to use the DataSource, you must set the property databaseName. The
settings for serverName, portNumber, user, and password are optional.
Note: these properties are declared in the superclass.
Class PGConnectionPoolDataSource
PostgreSQL implementation of ConnectionPoolDataSource. The app server
or middleware vendor should provide a DataSource implementation that
takes advantage of this ConnectionPoolDataSource. If not, you can use
the PostgreSQL implementation known as PoolingDataSource, but that
should only be used if your server or middleware vendor does not
provide their own. Why? The server may want to reuse the same
Connection across all EJBs requesting a Connection within the same
Transaction, or provide other similar advanced features.
See also:
Connection Pooling with PostgreSQL JDBC
using EclipseLink as JPA 2.0 provider, I can obtain a JDBC connection by simply calling
Connection con = entityManager.unwrap(Connection.class);
But I'm unsure what I'm responsible for. Do I have to close the connection after submitting my queries? Or are I'm not allowed to close the connection, because EclipseLink also uses this connection internally. Or does it not care, because EclipseLink observes my behaviour and closes the connection automatically if I don't do it?
If you are in the context of a JPA transaction the connection will be managed by the provider (EclipseLink). If you are outside of a transaction you are responsible for managing the connection yourself.
See the following link for additional information:
http://wiki.eclipse.org/EclipseLink/Examples/JPA/EMAPI#Getting_a_JDBC_Connection_from_an_EntityManager
But I'm unsure what I'm responsible for. Do I have to close the
connection after submitting my queries? Or are I'm not allowed to
close the connection, because EclipseLink also uses this connection
internally.
A good and valid question. It seems that the documentation is lacking the semantics of the unwrap() calls.
Regarding EclipseLink, according from what I got from the source:
EclipseLink gives you a reference to the currently active connection which it uses for the currently active client session transaction. If no transaction is active, a new will be created, associated with the session and returned from the unwrap() method.
As a result, IMHO, a commit/rollback of such a obtained Connection may lead to undefined behavior and/or exceptions. Same is true for executing DML which changed records have been previously cached by eclipselink internal caches or for which managed entities exist.
So when using this API, especially if the underlying transaction is dirty, be careful.
If you can refer to internal eclipselink classes, you can access eclipselink internal connection pool to get a Connection exclusively (have a look at org.eclipse.persistence.sessions.server.ServerSession.getConnectionPool(String) ).
I want to manage the database connection outside entity manager context so that I can use it for different entity managers. The question is how can I build the entity manager factory or entity manager with my own connection instead of providing it with properties in persistence.xml?
In either case the answer is that you cannot, in SE you can specify the db connection properties when creating the EntityManagerFactory, but the db connection is still maintained by the EntityManager and for good reason, if you controlled this you could commit and rollback behind the EntityManager's back. If you gave the same db connection to multiple EntityManager's this would be chaos indeed, I am not sure why on earth you want to do this.
The best I can suggest is that you look into the EntityManager.getDelegate() (JPA 1.0) or EntityManager.unwrap(java.lang.Class cls) (JPA 2.0) methods they may return the underlying provider (ie. Hibernate) object which you may be able to pry the database connection out of, but you certainly won't be able to replace it.
In short really bad idea.