I was trying to figure out how hibernate works and few things are there I want to how they works and I wanted to know if I understood correctly.
EntityManagerFactory emf = Persistence.createEntityManagerFactory();
The above does following things
Creates entitymanager factory instance.
EntityManagerFactory stores the mapping for all the entity classes.
Its the provider of entity manager instances.
what else above line does?
EntityManager em = emf.createEntityManager()
createa an entitymanager.
EntityManager is responsible for managing lifecycle of managed objects.
what else above line do? does it create a session with database?
em.getTransaction().begin();
Does above lines creates a database session?
is session and transaction and session are java side things or database side things?
what transaction and session means ?
em.getTransaction().commit();
I feel that this line does all the work of creating transaction and saving the data to the database. am I correct?
em.close();
this line closes the database session.
emf.close();
all the mapping present in the factory are lost and eligible for GC?
Am I correct with my understandings?
Related
I am working an a JPA 2.0 project, where I am saving my Entity class objects like :-
InitialContext ctx = new InitialContext();
UserTransaction userTrans = (UserTransaction)
ctx.lookup("java:comp/UserTransaction");
EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_NAME);
EntityManager em = emf.createEntityManager();
User user = new User("ankit","nigam",25);
em.persist(user); // persisted in db after this executes
userTrans.commit(); // whether it is required OR not.
So whether I am using userTrans.commit() or not, my user object is getting saved in Db, after persist() executes. But some of my colleagues say, as a standard we should commit() the transaction.
What should be the approach which I follow and whats the logic behind commit() and persist(). Please throw some lights.
Is autocommit ON in your DB? If it is then that is the reason why the changes get permanently stored in your DB irrespective of whether or not you commit the transaction from your application. In production the autocommit is generally set OFF because it hampers the performance/response time of the DB, that is why developers are generally encouraged to control the commit or rollback of a transaction from their application. The link details the command to handle autocommit in db2: http://www.db2util.com/administration/options-db2-command-line-disable-autocommit/
So I had been working with Hibernate SessionFactory and its getCurrentSession method for inside a transaction for a while now.
Session session = sessionFactory.getCurrentSession();
and having it interact with other DAO classes within the same test. Switching to JPA though, can I inject a container managed EntityManagerFactory and then replacing the above with
EntityManager entityManager = myFactory.createEntityManager();
and then continue as session interface equivalents in EntityManager in current tests? Performing entityManager.flush() causes
javax.persistence.TransactionRequiredException: no transaction is in progress
.flush() call must be part of a transaction. Either you create one or propagate from calling class using #Transactional annotation.
To create:
entityManager.getTransaction().begin();
// Some DB operations
entityManager.flush();
entityManager.getTransaction().commit(); //commit() will do the flush anyway
If you want to to be part of calling class transaction, then include #Transactional annotation either at method or class level depending on design.
Can #PersistenceUnit be used with JTA in JPA? If so, how is it possible?
Per http://tomee.apache.org/jpa-concepts.html:
With <persistence-unit transaction-type="RESOURCE_LOCAL"> [...]
You must use the EntityManagerFactory to get an EntityManager
[...]
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
With <persistence-unit transaction-type="JTA"> [...]
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
I have a similar code which uses JTA and #PersistenceUnit at the same time. But sometimes I am having NullPointerException when accesing transaction (defined as #Resource).
Using JTA means that you delegate the work to the container. You can override it by using a UserTransaction. Your quotation contains all the answers you want to know. Using PersistenceUnit to get an EntityManager won't work.
If you are using RESOURCE_LOCAL you are responsible for the transaction itself, by using EntityManager.getTransaction(). An entity manager is created by an EntityManagerFactory. To obtain that factory, you can use PersistenceUnit.
So the simple answer is no, if you rely on container managed entity managers.
As example see http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html
Application Managed Entity Managers = RESOURCE_LOCAL can use UserTransaction (which are part of JTA).
What does entity manager means???
If i am a naive programmer i could simply interpret something which manages entity & Indeed it means the same.
An Entity Manager is been instantiated with the help of an Entity Manager Factory. A connection to a database is managed by the entity manager i.e. it provides functionality for performing operations on a database. Therefore we could say if an application needs multiple database connections, an EntityManagerFactory will be constructed for a specific database which provides an efficient way to construct multiple EntityManager instances(if required, even single instance of entity manager can the job depending upon the requirement you may opt for multiple instances) for that database required for every HTTP request. We shall understand this with the help of an example. Suppose we have a
Database : A , having a relational tables B and C.
So for A, an instance of entity manager factory will be instantiated. Now we if ever want to perform any update to table B & lets say delete operation for table C, either two different entity manager could be instantiated or same the entity manager instance can be utilized for both.
The instantiation of Entity Manager Factory itself is considered to be less efficient but since it's a one time activity therefore it's manageable task because Entity Manager Factory once instantiated, it will serve the entire application
The entity manager instantiated is associated with a persistence context.
#PersistenceUnit(unitName = "MyDatabase")
EntityManagerFactory emf;
EntityManager entityManager = emf.createEntityManager();
or
#PersistenceContext(unitName = "MyDatabase")
private EntityManager entityManager;
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
EntityManagerFactory defines another method for instantiation of EntityManager that, like the factory, takes a map of properties as an argument. This form is useful when a user name and a password other than the EntityManagerFactory's default user name and password have to specified:
Map properties = new HashMap();
properties.put("javax.persistence.jdbc.user", "kashyap");
properties.put("javax.persistence.jdbc.password","kashyap");
EntityManager em = emf.createEntityManager(properties);
Within the persistence context, the entity instances and their lifecycle are managed. By Entity instance, we mean instance of an entity & each entity designates relational table in the database. Entity Manager is actually an interface which provides methods to create and remove persistent entity instances, to find entities by their primary key, and to query over entities so together these functionalities are grouped under operations we perform. Operations that modify the content of a database require active transactions. Transactions are managed by an Entity Transaction instance obtained from the EntityManager.
Precise Definition :-
An Entity Manager is defined by a persistence unit. A persistence unit defines the set of all classes that are related or grouped by the application, and which must be colocated in their mapping to a single database.
Below i'm writing a code snippet for better understanding :-
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction
/**
*getTransaction() EntityManager's method Return the resource-level EntityTransaction object. See JavaDoc Reference Page
*/
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
Lets proceed as per JPA Specification :-
1) Extended vs Transactional - Scoped :
By Default the Transactional Persistence Context is in used which means all changes are flushed and all managed entities become detahced when the current transaction commits.
The Extended scope is available only for Stateful EJBs & it even makes a perfect sense since stateful beans can save the state therefore one can say end of
one business method doesn't necessary means the end of the transaction.
With the Stateless beans, it has a different aspect - We have business method that must end when the business method finishes.
===> One Method = One Transaction;
Only Transactional-Scoped Entity Manager is allowed for Stateless Beans
You can control if the EntityManager is extended or transactional during the EntityManager Injection :-
#PersistenceContext (type = javax.persistence.PersistenceContextType.EXTENDED)
EntityManager emng;
By Default it's javax.persistence.PersistenceContextType.TRANSACTION
Extended and Transaction Scoped PersistenceContext are allowed only in case of container-managed EntityManagers.
Time to step up a bit with: Container-managed vs Application-managed
2) Container-managed vs Application-managed :
#PersistenceContext
EntityManager emng;
Above statement authorises Container to inject the entity manager for you, hence Container-Managed.
Alternatively, you can create an EntityManager by yourself using EntityManagerFactory But this time the injection will be bit different -
#PersistenceUnit
EntityManagerFactory emf;
Now to get the EntityManager you need to invoke
emf.createEntityManager();
And here it is - you're using the application managed Persistence Context. Now you're responsible for creation and removal of EntityManagers.
Focus before you read the next para because that's what the tangled context , i'm trying to resolve-
You might use createEntityManager if you want to have control over created EM - e.g. if you need to move the created EntityManager across multiple beans involved in the trasaction - the container won't do it for you and every time you invoke createEntityManager(), you're creating an EntityManager that is connected to the new PersistenceContext. You might use the CDI for EntityManager's sharing.
Stay tuned for Entity Transaction - JPA and Resource-local, will be posting a detailed discussion on it.
Hope it gives a brief idea about the context. & Feel free to post queries.
Read the second part from here
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.
I have a little of confusion about JDBC connection, transactions and their integration in EJB, JTA, Hibernate environment. My doubts are:
when we use #Resource DataSource ds; ... ds.getConnection() , are we working in the same transaction used by the managed bean? Should we close the connection, statement, resultset?
what about session.doWork? Are we in the same transaction? What about closing statement and result set?
aggressive release mode in Hibernate means that connections are closed after each statement. Does it mean that transaction is committed too? (I don't think this is true, but I can't understand how Hibernate works here)
There are a few things you need to figure out. First thing you need to identify what is your unit of work.
The session-per-request pattern is one of the most used and unless you have specific needs stick with that.
If you are using Hibernate you don't use statements and result sets directly. Hibernate will do that for you. what you need to close is the hibernate session
What you use is a SessionFactory and a Session object. The session pretty much represents your unit of work. Inside the hibernate session you get your objects, you change them and save them back.
The session per request pattern opens a session when a request is received and closes it when the response is sent back.
In a container managed EJB session bean a transaction is available and the datasource you (or hibernate) use in such a container is automatically handled by a JTA TransactionManager.
Now because Hibernate is smart it can automatically bind the "current" Session to the current JTA transaction.
This enables an easy implementation of the session-per-request strategy with the getCurrentSession() method on your SessionFactory:
try {
UserTransaction tx = (UserTransaction)new InitialContext()
.lookup("java:comp/UserTransaction");
tx.begin();
// Do some work
factory.getCurrentSession().load(...);
factory.getCurrentSession().persist(...);
tx.commit();
}
catch (RuntimeException e) {
tx.rollback();
throw e; // or display error message
}
So to answer your questions:
If you are using Hibernate with JTA in a container you'd be better off using a JPA EntityManager or maybe spring hibernate template.
Here are some references:
http://community.jboss.org/wiki/sessionsandtransactions#Transaction_demarcation_with_JTA
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/orm/hibernate3/HibernateTemplate.html