Java Hibernate(JPA) queries - java

what is the right way to make a query with JPA. Here is my way now:
EntityManagerFactory factory = Persistence.createEntityManagerFactory("hellojpa");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
//query here
em.getTransaction().commit();
em.close();
I just started learning it and I am pretty sure that there will be more intelligent way. Some helper class, maybe?
Thanks.

In my opinion it is the right way, if you use local transactions. Keep in mind that EntityManager is not thread safe.
You will have less boilerplate code in a JavaEE environment, where the application server takes care of EntityManager injection and uses JTA.
#PersistenceContect
EntityManager em;
public void foo() {
// query
}

Related

Managing Multiple Database Connections

I've been struggling with this problem for days,
Here is the scenario:
I have several databases, one for each of my customers, all of them with the same
structure(same tables and columns), so my application needs to decide at runtime with which one it needs to connect. I'm using JPA2, EclipseLink and EJB3.
My first attempt was to implement a custom EntityManager with all the logic to performs the operations on the right database, then I configured this EntityManager as an Stateless EBJ in order to make it possible to inject it with the #EBJ annotation (as described at this link: http://www.hostettler.net/blog/2012/11/20/multi-tenancy/). I coundn't make it work because it was throwing an exception when trying to inject the EntityManager.
So I decided to try something else, I've created EntityManagerFactory and I passed the
JTA_DATASOURCE to it(after decide at runtime which one to use), so it could connect to the
right database.
Here is the code:
#Stateless
#TransactionManagement(TransactionManagementType.CONTAINER)
public class TestEntDAO {
private EntityManager em;
private EntityManagerFactory emf;
#PostConstruct
public void init() {
em = getEntityManager();
}
public EntityManager getEntityManager() {
Map props = new HashMap();
props.put(PersistenceUnitProperties.TRANSACTION_TYPE, "JTA");
props.put(PersistenceUnitProperties.JTA_DATASOURCE, dataSourceName());
emf = Persistence.createEntityManagerFactory("testePU", props);
em = emf.createEntityManager();
return em;
}
public String dataSourceName(){
if(someCondition){
return "db1";
}else{
return "db2";
}
}
}
This worked perfectly, the only problem is that the transaction is not managed by the
container, so I had to explicitly mark the transaction's boundaries(call begin() and
commit()). I could just use the #PersistenceContext annotation to make it work, but then I
wouldn't have the EntityManagerFactory to pass the datasource.
Does anyone know of a way to use the Container-Managed Transactions(CMT) and still be able
to pass the datasource?
Maybe try to define 3 Data sources and 3 Persistence units.
<persistence-unit name="PU1">
<jta-data-source>jdbc/DS1</jta-data-source>
...
</persistence-unit>
<persistence-unit name="PU2">
<jta-data-source>jdbc/DS2</jta-data-source>
...
</persistence-unit>
<persistence-unit name="PU3">
<jta-data-source>jdbc/DS3</jta-data-source>
...
</persistence-unit>
And inject Entity manager from whatever Persistence unit you want.
#PersistenceContext(unitName = "PU2")
EntityManager em;
This should work, although I didn't test it.

Proper Usage of Entity Manager from EntityManagerFactory

I am having some trouble understanding the proper usage of entity manager when querying for objects and or deleting/creating. Right now for any database transactions I have several service methods that open and close new entity managers like so:
public static Long getCountApplicants(String active){
EntityManager entityManager = factory.createEntityManager();
long value = (Long) entityManager.createQuery("select count(distinct a) from Applicant a where a.active = " +active).getSingleResult();
System.out.println("get count app query");
entityManager.close();
return value;
}
Since I have a Java EE app with a persistence.xml file that defines my unit, why can't I declare only one from my factory and use it throughout the life of my app? Is there any performance or memory leak issues with using just one of these objects?
Update:
I am using the following stack, Spring Framework/JPA Eclipselink
Long story short: Since you're using Spring, you're better off defining the Entity Manager as an attribute of your DAO like so:
#PersistenceContext
EntityManager em;
Your code then becomes:
public static Long getCountApplicants(String active){
long value = (Long) em.createQuery("select count(distinct a) from Applicant a where a.active = " +active).getSingleResult();
System.out.println("get count app query");
return value;
}
This will work only with Non Extended Persistence Contexts.
The EntityManager injected by Spring will be threadsafe.
Whether you need to configure an LocalEntityManagerFactorBean application-managed or LocalContainerEntityManagerFactoryBean container-managed Entity Manager is just a matter of configuration in the Spring configuration files.
EntityManager is generally not threadsafe when application managed.
http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
However, if you're using a container managed version, it should be. You would inject it:
#PersistenceContext
EntityManager entityManager;
Spring is one such container that can do this. The link above is a helpful resource.

How to use Eclipselink #Multitenant in JSF/EJB?

The #Multitenant support in Eclipselink 2.3 looks really interesting, but I'm having a hard time understanding how to use it in a JSF or EJB which injects an EntityManager with #PersistenceContext. The EclipseLink docs are pretty clear that #PersistenceContext injection doesn't work in this case, but you could inject an EntityManagerFactory via #PersistenceUunit instead.
Still, what I'm not seeing is how to manage the lifecycle of an EntityManager you might create via injected EntityManagerFactory.createEntityManager() - in particular, when to close the resulting EntityManager, and how to participate in transactions.
Has anyone gotten this to work? Or am I missing something obvious?
See also: http://wiki.eclipse.org/EclipseLink/Examples/JPA/Multitenant
UPDATE
I had some success with #PersistenceContext (EntityManager) injection and then passing parameters to EclipseLink via session listener. I'm not 100% sure this is the right answer and would appreciate confirmation that it isn't creating a non-obvious race condition or thread-safety issue.
For example:
public static class TenantListener extends SessionEventAdapter {
#Override
public void postAcquireClientSession(SessionEvent event) {
long tenantId = **business logic**;
event.getSession().setProperty("eclipselink.tenant-id", tenantId);
}
}
Using events is fine.
You could also inject the EntityManager and set the property, or inject the EntityManagerFactory and use joinTransaction() to join the active JTA transaction.

How can I receive the persistence unit name of an EntityManager?

In a Java EE application I am using #PersistenceContext on an EJB3.0 SessionBean to let an EntityManager be autowired.
As I am using multiple Datasources, I want to programmatically determine the autowired PersistenceUnit name of the EntityManager. Any chance?
You can retrieve more than one entity manager in this way:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("name your PU")
EntityManager em = emf.createEntityManager();
...
em.close();
emf.close();
But I do not know if a good solution. Annotation #PersistenceContext allows retrieve only one entity manager. But you may try create one class/stateless bean which will keep more than one PU, and take from him PU which you need. Maybe this little better than use EntityManagerFactory.

Hibernate EntityManagerFactory EntityManager

Can I create an EntityManager from EntityManagerFactory outside a bean. If so, how would I do it?
In a non-managed environment (this is what you mean by outside a bean, right?), then you typically use:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("MyPu");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin()
...
em.getTransaction().commit();
emf.close();
Check the other factory method allowing to pass properties as parameter (they will override any values that may have been configured elsewhere): Persistence.createEntityManagerFactory(String, Map).
See also
Using the Java Persistence API in Desktop Applications
An Introduction to Java Persistence for Client-Side Developers

Categories

Resources