Read only service : javax.persistence.TransactionRequiredException: no transaction is in progress - java

I have a service that reads data from database. After reading there is a flush which causes the exception mentioned in the title. Below is the sequence of statements
ManagerFactory factory = new ManagerFactory();
EntityManager manager = factory.getManager();
EntityTransaction transaction = manager.getTransaction();
Query query = manager.createQuery("select personRoleJPA from personRoleJPA");
personRoleJPA = (PersonRoleJPA) query.getSingleResult();
if (manager.isOpen()) {
manager.flush();
}
if (manager.isOpen()) {
manager.close();
manager = null;
}
if (transaction.isActive()) {
transaction.commit();
}
I suspect the exception is because I did not begin the transaction. My question is do you really need to flush & commit when you are not doing any writes ?

Remove everything related to transaction since you dont need an active transaction to retrieve data:
ManagerFactory factory = new ManagerFactory();
EntityManager manager = factory.getManager();
Query query = manager.createQuery("select personRoleJPA from personRoleJPA");
personRoleJPA = (PersonRoleJPA) query.getSingleResult();
if (manager.isOpen()) {
manager.flush();
}
if (manager.isOpen()) {
manager.close();
manager = null;
}

About flush() method you can read from documentation:http://docs.oracle.com/javase/1.5.0/docs/api/java/io/OutputStream.html#flush%28%29
If you read anything from database you do not need transaction.commit().commit() using for saving changes after sql statement executed but in select statement you do not need commit.Default in JDBC commit is auto-commit mode.In hibernate configuration file you can change this settings.The best practice is disabling auto-commit mode.
About commit() you can also read from:https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html

Related

Session and Transaction in Hibernate Java

In Java Hibernate, when we need to do something with DB we need:
1. Open session
2. Begin transaction
3. Finish transaction
4. Close session
For example if I want to get Student list:
public static List<Student> getStudentList()
{
List<Student> l = null;
Session session = HibernateUtil.getSessionFactory().openSession();
try {
String hql = "from Student";
Query query = session.createQuery(hql);
l = query.list();
} catch (HibernateException ex) {
//Log the exception
System.err.println(ex);
} finally {
session.close();
}
return l;
}
Insert a student
public static boolean addStudent(Student s)
{
Session session = HibernateUtil.getSessionFactory().openSession();
if (... /* check if student is already exists*/)
{
return false;
}
Transaction transaction = null;
try {
transaction = session.beginTransaction();
session.save(s);
transaction.commit();
} catch (HibernateException ex) {
//Log the exception
transaction.rollback();
System.err.println(ex);
} finally {
session.close();
}
return true;
}
Why there is no transaction in getStudentList()? Thank in advance
This hibernate article explains the behavior of SELECT operations which are not explicitly executed within a transaction.
The following example is given in the article but it's also true for your query example.
Session session = sessionFactory.openSession();
session.get(Item.class, 123l);
session.close();
A new Session is opened. It doesn’t obtain a database connection at this point.
The call to get() triggers an SQL SELECT. The Session now obtains a JDBC Connection from the connection pool. Hibernate, by default, immediately turns off the autocommit mode on this connection with setAutoCommit(false). This effectively starts a JDBC transaction!
The SELECT is executed inside this JDBC transaction. The Session is closed, and the connection is returned to the pool and released by Hibernate — Hibernate calls close() on the JDBC Connection. What happens to the uncommitted transaction?
The answer to that question is, “It depends!” The JDBC specification doesn’t say anything about pending transactions when close() is called on a connection. What happens depends on how the vendors implement the specification. With Oracle JDBC drivers, for example, the call to close() commits the transaction! Most other JDBC vendors take the same route and roll back any pending transaction when the JDBC Connection object is closed and the resource is returned to the pool.
Obviously, this won’t be a problem for the SELECT [...]
Lets extend the above example to provoke a possible problem.
Session session = sessionFactory.openSession();
Item item = session.get(Item.class, 123l);
item.setPrice(10);
session.close();
Now it depends on the JDBC driver if the new price for the Item is persisted or not.
So you can neglect begin and commit transactions on pure SELECT operations even when your JDBC driver will rollback the transaction as long as you have no database changes.
But anyway I would strongly recommend using transactions on any operation to avoid misunderstanding and problems.

Multiple Hibernate transactions in a JTA session

I would like to have multiple Hibernate transactions in a single EJB method call (running in WildFly). Currently my current_session_context_class is set to jta and transaction.factory_class is org.hibernate.transaction.JTATransactionFactory.
Now, for example, the following code fails:
public void myMethod(){
try{
Transaction tr = myHibernateSessionFactory.getCurrentSession().beginTransaction();
//execute some DB operation
tr.commit();
tr = myHibernateSessionFactory.getCurrentSession().beginTransaction();
//execute some DB operation
tr.commit();
}catch(Exception e){
e.printStackTrace();
}
}
The problem is that the second call to beginTransaction() throws an exception org.hibernate.TransactionException: Transaction instance is no longer valid.
How do I get a new transaction for the current session?

Hibernate session manager for bulk insertion and fetching at the same time

I am new to hibernate. I am facing problems with hibernate session problems. when i am trying to insert a data I will use
session.openSession();
After completing the updation I am using session.flush();session.clear(); and session.close().
I don't how to maintain this. I am getting deadlock exception. At the same time of insertion i am opening another one session to fetch data.
Please help me.. This is my existing sample code
#Autowired
#Qualifier("messageListenerReportSessionFactory")
private SessionFactory messageListenerReportSessionFactory;
Session session = messageListenerReportSessionFactory.openSession();
if(session != null && session.isOpen()){
try{
Transaction tx= session.beginTransaction();
Query q = session.createQuery("Update "+tableName+" set isUser = ? where id = ?");
q.setInteger(0, 2);
q.setLong(1, id);
q.executeUpdate();
tx.commit(); tx = null;
}catch(Exception ex){
PointelTraceLogger.logger.log(Level.ERROR, "[Audit] Error in updateUser() in com.pointel.application.database.pointelreport.MessageListenerReportDao");
PointelTraceLogger.writeStackTrace(ex);
}finally{
session.clear();
session.close();
}
}

Hibernate cannot access data inserted by phpMyAdmin

My question is about hibernate, actually I'm working on a Java EE application using hibernate and mysq.
Everything looks fine. but I still have one problem when I insert data via phpMyAdmin to my database, I cannot access them immediately via hibernate unless I started the server (tomcat) again.
This is because your transaction in phpMyAdmin was not committed.
Try running this query in phpMyAdmin before running commands.
SET ##AUTOCOMMIT = 1;
Or running commit; at the end of your query.
Possible duplicate of:
COMMIT not working in phpmyadmin (MySQL)
I noticed that i've forgot to add transaction.commit(); for every hibernate session.get(); method, so somehow it keeps data in the cache.
public List<User> getAllUsers(User user) throws Exception {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria c = session.createCriteria(User.class).add(Restrictions.ne("idUser", user.getIdUser()));
List<User> users = c.list();
tx.commit();//i forget to add this
return users;
} catch (Exception e) {
if (tx != null) tx.rollback(); throw e;
} finally {
session.close();
}
}

How to Encapsulate Transaction Pattern in Java

I'm trying to write DAOs for my database models using the transaction pattern like such,
Session session = null;
Transaction tx = null;
try{
session = HibernateUtil.getSessionFactory().openSession();
tx = session.beginTransaction();
tx.setTimeout(5);
//doSomething(session);
tx.commit();
}catch(RuntimeException e){
try{
tx.rollback();
}catch(RuntimeException rbe){
log.error("Couldn’t roll back transaction", rbe);
}
throw e;
}finally{
if(session!=null){
session.close();
}
}
What's a good approach to encapsulate this pattern in a method with
//doSomething(session);
as an argument to be performed as part of the transaction? Sometimes I run a query, sometimes I operate on session.saveOrUpdate, etc. I have many DAOs to write and this pattern of code duplication is bothering me.
EDIT
Is there a direct mapping between session operations and HQL (saveOrUpdate, delete, etc) so all I need to pass into this method is just a query?
Thanks for the insights.
Something like this might be what you're after
public void doSomething(MyQuery myQuery) {
...
Transaction tx = null;
try {
...
myQuery.execute(tx);
...
} catch (...) {
} finally {
}
}
public class MyQuery {
public void execute(Transaction tx) {
// run queries on transaction
}
}
Either create a new MyQuery instance or a new MyQuery subclass for each query or set of queries you want to execute

Categories