Detect which JPA provider is used based on EntityManager - jpa

Is there a way to detect which JPA provider is used when only a EntityManager handle is available?
Since EntityManagers are often proxied, looking at the class doesn't work too well. Is there a standard property for this in EntityManager or EntityManagerFactory getProperties map?

AFAIK, no. But you can use the getDelegate() method and see what it returns. For Hibernate, it returns the Hibernate Session instance, for example. Just getting the name of the class of the delegate returned should give you an idea of the underlying provider.

Related

Why are my entities only partially populated when loading them using Spring Data JPA?

I'm using Spring Data JPA and DataNucleus as JPA persistence provider and have something like
interface BookRepository extends CrudRepository<Book, Long> {
Book findByAuthorId(Long id);
}
If I call bookRepository.findByAuthorId() and then access book.publishingHouse.manager.name is null. As opposed to calling bookRepository.findAll() when the fields are populated correctly all the way. I set datanucleus.DetachAllOnCommit=true and datanucleus.maxFetchDepth=-1 (I also tried with 10).
Any idea why?
If you don't have any additional transaction boundaries defined, the EntityManager closed when leaving the query method. That means what you get back is detached entities and what kind of load state you get back is determined by the defaults the persistence provider uses.
You basically have two options:
Have a client (service or controller class) using #Transactional to keep the EntityManager open and thus the loaded instances eligible to lazy-loading to pull data out of the store while you use the instance. If a controller or service is not enough, you might wanna look into the OpenEntityManagerInViewFilter/-Interceptor which basically keeps the EntityManager open until the view is rendered.
Define what should be fetched explicitly either using JPA 2.1 entity graphs (see the reference docs for details) or explicitly adding fetch-joins to the query by defining it manually.

Spring Data JPA Repository CRUD Testing

I'm playing around with the Spring Data Repository and have a question on writing CRUD tests. I have written many CRUD tests against Hibernate DAOs and EJB 3 entity beans where I create and entity, flush it to the database, clear the entity manager, and read it back by ID. The entity manager is cleared so the first level cache is not hit on the read.
Using the Spring Data repository I can't find a way to clear the underlying entity manager used by my test so my read is not going back to the actual database, making my test invalid.
Is there any way to clear the entity manager in the test? Is there a way I can inject one into my test so that it is used by the repository?
Thanks!
Cory.
Try it by injecting the entitymanager like this:
#PersistenceContext
EntityManager entityManager
and make your test transactional by setting the #Transactional attribute on your test method. Then inside the method you can call the entityManager.flush() method.
Regards
If you wish the EntityManager to be cleared automatically you can set #Modifying annotation’s clearAutomatically attribute to true.
Please see here

How to call dbms_application_info with EntityManager injection

We are building a Java EE / JPA / CDI app with an Oracle Database. The data model (this we can't change) implements security partly by using views and client_info...something like..
create view the_view
as select *
from the_table
where organization_id = USERENV('CLIENT_INFO')
where userenv('CLIENT_INFO') is basically set by calling
dbms_application_info.set_client_info(11);
Now, we have a series of Stateless Beans that basically inject Persistence Context and execute queries (both native queries and regular POJO) and we need a way to inject the client info (that we can get from the security context) into the PersistenceContext before making calls to the EntityManager
in a nutshell I need to be able to call this..
#PersistenceContext
EntityManager em;
#Inject
UserInfo userInfo;
public TheView getTableData(long id) {
// At this point security Information should be set..
// Call the query
return em.find(TheView.class, id);
}
without having to call a setClientInfo() manually..
One way of doing this would probably be using interceptors and annotate the method and make the call there (providing I can get hold of the PersistenceContext that the method will use.. ).. will this even work??
Any other way of doing this??
TIA!
The interceptor approach you are writing about sounds like an excellent fit.
I'm not 100% sure if I understood your requirements correctly, but it seems as if would be a good idea to decouple authorization logic from the actual business logic to be able to write something like this:
...
#IsEditor("someMoreData")
public X getData() {
...
}
IsEditor is an interceptor and will encapsulate the relevant DB lookup.
Seam Security as an independent CDI modules comes with a couple of concepts (& implementations), you should definitely check it out.
If you are using EclipseLink, there is some info here on using EclipseLink with Oracle VPD, which seems similar.
Nasically, you can use events to execute your call.
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Shared_and_Isolated#Oracle_Virtual_Private_Database_.28VPD.29

compare two EntityManagerFactories for having PersistenceUnits with identical connection attributes

Having two JPA2 (EclipseLink) EntityManagerFactory instances what would be the best way to detect that their PersistenceUnit attributes are identical?
You can call getProperties() to get the persistence unit properties and compare them.
Normally EclipseLink will use the same EclipseLink ServerSession if the same persistence unit is used twice. You can call unwrap(Session.class) to get the session, and see if they are the same.
I think you're best hit would be to get (somehow, someway, ...) access to the PersistenceUnitInfo interface which is implemented and created by the container and passed to the JPA provider. The JPA provider uses it when creating the EntityManagerFactory.

JPA, scope, and autosave?

I am using JPA and lets say I do something like this
public class MoRun extends Thread {...
public void run() {
final EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("pu");
EntityManager manager = emFactory.createEntityManager();
manager.setFlushMode(FlushModeType.COMMIT);
someMethod(manager);
...
}
public void someMethod(EntityManager manager){
Query query = manager.createNamedQuery("byStates");
List<State> list = query.getResultList();
for (State state : list) {
if(someTest)
state.setValue(...)
}
...
}
So for those objects that pass "someTest" and values are updated are those changes automatically persisted to the db even though there is no transaction and I don't explicitly "manager.save(state)" the object? I ask because it seems like it is and I was wondering if the flush is doing it?
According to the javadoc of FlushMode (I'm assuming this is a JPA 1.0 question), and as pointed out by #Konrad:
If there is no transaction active, the persistence provider must not flush to the database.
Since you're very likely using a transaction-type="RESOURCE_LOCAL" for your persistence unit, since I don't see any begin/commit surrounding your calls to your EntityManager (which is not good, more on this just after), for me there is no transaction active so I wouldn't expect anything to be flushed.
Anyway, as reminded in the nice JPA Concepts page:
With <persistence-unit transaction-type="RESOURCE_LOCAL">
you are responsible for EntityManager
(PersistenceContext/Cache) creating
and tracking...
You must use
the EntityManagerFactory to get an
EntityManager
The resulting
EntityManager instance is a
PersistenceContext/Cache
An
EntityManagerFactory can be injected via the
#PersistenceUnit annotation only (not #PersistenceContext)
You are
not allowed to use #PersistenceContext to refer to a unit
of type RESOURCE_LOCAL
You
must use the EntityTransaction API to begin/commit around every call to your
EntityManger
Calling
entityManagerFactory.createEntityManager()
twice results in two separate
EntityManager instances and therefor
two separate PersistenceContexts/Caches.
It is
almost never a good idea to have more than one instance of an
EntityManager in use (don't create a
second one unless you've destroyed the
first)
So, in my opinion, you should fix your code here, there is no real point at wondering about unexpected behavior if your code is not correct. Just performs calls to your EntityManager inside a transaction.
How do you know there is no transaction? Are you using it from EJB? In that case I bet there is a transaction.
From docs (http://java.sun.com/javaee/6/docs/api/javax/persistence/FlushModeType.html):
If FlushModeType.COMMIT is set, the
effect of updates made to entities in
the persistence context upon queries
is unspecified.
If there is no transaction active, the
persistence provider must not flush to
the database.
If you are in transaction, attached entities (i.e. those loaded in the same transaction) are automatically recorded to database.