Getting a JDBC connection from EclipseLink - jpa

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) ).

Related

.NETCore PostgreSQL "A command is already in progress"

I am developing a WebAPI on .NETCore accessing data to a POSTGRESQL DB.
I have troubles with the non-MARS support of PostgreSQL. NPGSQL is unable to support multiple connections from the same instance (as described in EntityFramework DbContext lifecycle + Postgres: "An operation is already in progress."). For Asynchronous management, this is blocking.
Unfortunately, I cannot find any solution to this.
At the moment, I inject my DB context with:
services.AddEntityFrameworkNpgsql().AddDbContextPool<DBApiContext>(opt => opt.UseNpgsql('connectionString');
I use EntityFramework.
Just for people who got stuck in this - In my case, it was a simple code change in the end of the method to fix this:
reader.close();
reader is an object of NpgsqlDataReader.
For who may be interested in: my problem was all about service scope and dependency injection.
The requestor was not a transient service, so that for every requests, even parallel, it was trying to access the DB.
Postgresql doesn't support MARS, then the second requests were rejected.
You need to have transient service requesting the access, for every invokation to use a different DB handler.

eclipselink.read-only and transaction bounderies

I'm using EclipseLink as my JPA provider.
When I use the following code on a query object:
myQuery.setHint("eclipselink.read-only", "true");
The query is executed on a different connection than the original EntityManager is using and return wrong results.
Does it make sense that setting the query to read only will cause EclipseLink to run it on a different connection? (I'm using connection pooling).
In additional I've added in the persistence.xml:
<shared-cache-mode>NONE</shared-cache-mode>
to disable cross session cache.
Read-only queries are meant to only show read-committed data. If you want transactional data, you should not use read-only.
You may be able to use an exclusive connection, (persistence unit, or persistence context property)
"eclipselink.jdbc.exclusive-connection.mode"="Always"

JPA (EclipseLink) connection timeouts

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.

EF usage from thread spawned from Role.OnStart()

I'm using EF code-first to manage my DB connection, with an explicit connection string declared in web.config. I would like to schedule some DB cleaning process (like deleting test transactions every day), so I'm spawning a thread from Role.OnStart() with proper concurrency management among the instances.
But I'm getting DB database exceptions, like the DB not matching my model, whereas I'm sure it does (the same code used from "inside" the app works well). So my guess is that web.config is not used from the thread, so EF probably uses the default connection string.
What would be the best way to use my connection string from there ?
Thanks
The OnStart method doesn't run in the same process as your web application meaning it doesn't make use of the web.config. I suggest you store the connection string in the service configuration and read it from here when initializing your context.
An other advantage is that you change the setting without re-deploying the application.

JPA build entity manager with a specific JDBC connection instance

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.