I am using Hibernate and I have Many methods of this type:
public static void modifySchemeEvents(String schmCode, String username) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(SchmEventsTable.class);
cr.add(Restrictions.eq("schmCode", schmCode));
SchmEventsTable evt = (SchmEventsTable) cr.uniqueResult();
evt.setLchgUserId(username);
tx.commit();
} catch (HibernateException asd) {
log.debug(asd.getMessage());
if (tx != null) {
tx.rollback();
}
} finally {
session.close();
}
}
This updated the database with the username where schmCode is <schmCode> I am attempting to convert to generic so that I do not have to write a separate method for all updates so I have come up with this generic method:
public static <T> T getUpdateObject(Class c, Map<String, ?> params) {
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
T value = null;
try {
tx = session.beginTransaction();
Criteria cr = session.createCriteria(c);
for (Map.Entry<String, ?> entry : params.entrySet()) {
cr.add(Restrictions.eq(entry.getKey(), entry.getValue()));
}
value = (T) cr.uniqueResult();
////How to set the values here?***
tx.commit();
} catch (HibernateException asd) {
log.debug(asd.getMessage());
if (tx != null) {
tx.commit();
}
} finally {
session.close();
}
return value;
}
I am attempting to use it this way:
Map<String, String> schemeEventMap = new HashMap();
schemeEventMap.put("schmCode", "CA201");
SchmEventsTable evt = DataOperation.getUpdateObject(SchmEventsTable.class, schemeEventMap);
evt.setLchgUserId(username);
This does not update the table like the first method. I am wondering how to pass the parameters in the generic Method Dynamically.
Related
The Idea:
When I was using hibernate I saw that everytime I had to write some sort of code. So I moved them to another method as wrapper. Where there will be functional interface as argument so that I can append some code in those context methods.
Problem:
Here is my two methods. One returns Object while another one is returning List. How can I exactly generify and make those two methods as one so that I can avoid code duplication.
public Object objectReturnContext(Function<Session, Object> function) {
Object object = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
object = function.apply(session);
transaction.commit();
} catch (NoResultException exception) {
if (transaction != null) transaction.rollback();
return object;
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return object;
}
public List<T> listReturnContext(Function<Session, List<T>> function) {
List<T> object = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
object = function.apply(session);
transaction.commit();
} catch (NoResultException exception) {
if (transaction != null) transaction.rollback();
return object;
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return object;
}
For better understanding, This is my whole class. If anyone can advice me any better way I will be very thankful. I have been into this for last few days.
package com.go_task.database;
import javax.persistence.Table;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import javax.persistence.NoResultException;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
public abstract class QueryExecutionContext <T> {
public Class<T> entity;
public String tableName;
public QueryExecutionContext(Class<T> entity) {
this.entity = entity;
this.tableName = entity.getAnnotation(Table.class).name();
}
public List<T> criteriaContext(CriteriaContextRunner<Session, Root<T>,
CriteriaQuery<T>, CriteriaBuilder, List<T>> runner) {
List<T> data = new ArrayList<>();
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery =
criteriaBuilder.createQuery(entity);
Root<T> root = criteriaQuery.from(entity);
data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
transaction.commit();
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return data;
}
public Object singleCriteriaContext(CriteriaContextRunner<Session, Root<T>,
CriteriaQuery<T>, CriteriaBuilder, Object> runner) {
Object data = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery =
criteriaBuilder.createQuery(entity);
Root<T> root = criteriaQuery.from(entity);
data = runner.apply(session, root, criteriaQuery, criteriaBuilder);
transaction.commit();
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return data;
}
public Object objectReturnContext(Function<Session, Object> function) {
Object object = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
object = function.apply(session);
transaction.commit();
} catch (NoResultException exception) {
if (transaction != null) transaction.rollback();
return object;
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return object;
}
public List<T> listReturnContext(Function<Session, List<T>> function) {
List<T> object = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
object = function.apply(session);
transaction.commit();
} catch (NoResultException exception) {
if (transaction != null) transaction.rollback();
return object;
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return object;
}
public void noReturnContext(Consumer<Session> consumer) {
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
consumer.accept(session);
transaction.commit();
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
}
}
I have extented QueryExecutionContext in my BaseDaoImpl.java later on. So I need to know 2 things.
Is my approch is ok or not. Im using pure hibernate and nothing else. No spring boot here.
If so then tell me how can I solve the code duplication in objectReturnContext() and listReturnContext() method.
The Object/List<T> parameter could be a generic parameter U:
public <U> U returnContext(Function<Session, U> function) {
U object = null;
Transaction transaction = null;
try {
Session session = HibernateUtil.sessionFactory().getCurrentSession();
transaction = session.beginTransaction();
object = function.apply(session);
transaction.commit();
} catch (NoResultException exception) {
if (transaction != null) transaction.rollback();
return object;
} catch (HibernateException exception) {
if (transaction != null) transaction.rollback();
exception.getStackTrace();
}
return object;
}
U will be inferred depending on what function you pass into the method. If you call it like:
Object o = returnContext(s -> {
...
return new Object(); // just an example
});
Then U is Object.
If you call it like:
List<T> list = returnContext(s -> {
...
return new ArrayList<T>(); // just an example
});
Then U is ArrayList<T>.
How can I print out an entire table from my database and its contents using Java and Hibernate?
My code thus far only prints one line of information that I need. It only prints the author:
package models;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import dao.HibernateDataDAO;
import hibernate.Books;
public class TestModel {
HibernateDataDAO data;
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void test() {
System.out.println("Testing hibernate");
//This Books is just a test, in the real implementation it will be added by the user.
Books books = new Books();
books.setTitle("A Game of Thrones");
books.setAuthor("George RR Martin");
data.insertBooks(books);
Session session = sessionFactory.openSession();
session.beginTransaction();
books = (Books) session.get(hibernate.Books.class, 1);
System.out.println(books.getAuthor());
//int id = 3;
//We set this as 'increment' so that keys are set by database and not by users.
//data.deleteBooks(books, id);
}
public HibernateDataDAO getData() {
return data;
}
public void setData(HibernateDataDAO data) {
this.data = data;
}
}
My table is called books. and there are 3 columns in it: booksKey, title, and author. booksKey is an integer, title/author are strings. How can I print the entire table so that it prints out all the rows of information?
I tried modifying the above code and doing this, however, nothing printed:
Query query = session.createSQLQuery("select *from books");
List<Books> list = query.list();
for(Books test: list) {
System.out.println(test.getAuthor());
}
If someone can please help-preferably show me what code to add/fix, that would be awesome. I can't figure this out at all!
HibernateDataDAO:
package dao;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import hibernate.Books;
import hibernate.Music;
import hibernate.Contacts;
import hibernate.Movies;
//DAO = data access object.
public class HibernateDataDAO {
private SessionFactory sessionFactory;
private Transaction transaction;
public void insertBooks(Books books) {
Session session = sessionFactory.openSession();
try {
transaction = session.beginTransaction();
session.save(books);
transaction.commit();
}
catch (Exception e) {
if (transaction != null) transaction.rollback();
throw e;
}
finally {
session.close();
}
}
public void deleteBooks(Books books, int booksKey){
Session session = sessionFactory.openSession();
try{
transaction = session.beginTransaction();
Object persistentInstance = session.load(hibernate.Books.class, booksKey);
if (persistentInstance != null) {
session.delete(persistentInstance);
}
transaction.commit();
}catch(HibernateException e){
if(transaction!= null) transaction.rollback();
e.printStackTrace();
}
finally{
session.close();
}
}
public void insertMusic(Music music) {
Session session = sessionFactory.openSession();
try {
transaction = session.beginTransaction();
session.save(music);
transaction.commit();
}
catch (Exception e) {
if (transaction != null) transaction.rollback();
throw e;
}
finally {
session.close();
}
}
public void deleteMusic(Music music, int musicKey){
Session session = sessionFactory.openSession();
try{
transaction = session.beginTransaction();
Object persistentInstance = session.load(hibernate.Music.class, musicKey);
if (persistentInstance != null) {
session.delete(persistentInstance);
}
transaction.commit();
}catch(HibernateException e){
if(transaction!= null) transaction.rollback();
e.printStackTrace();
}
finally{
session.close();
}
}
public void insertMovies(Movies movies) {
Session session = sessionFactory.openSession();
try {
transaction = session.beginTransaction();
session.save(movies);
transaction.commit();
}
catch (Exception e) {
if (transaction != null) transaction.rollback();
throw e;
}
finally {
session.close();
}
}
public void deleteMovies(Movies movies, int movieKey){
Session session = sessionFactory.openSession();
try{
transaction = session.beginTransaction();
Object persistentInstance = session.load(hibernate.Movies.class, movieKey);
if (persistentInstance != null) {
session.delete(persistentInstance);
}
transaction.commit();
}catch(HibernateException e){
if(transaction!= null) transaction.rollback();
e.printStackTrace();
}
finally{
session.close();
}
}
public void insertContacts(Contacts contacts) {
Session session = sessionFactory.openSession();
try {
transaction = session.beginTransaction();
session.save(contacts);
transaction.commit();
}
catch (Exception e) {
if (transaction != null) transaction.rollback();
throw e;
}
finally {
session.close();
}
}
public void deleteContacts(Contacts contacts, int contactKey){
Session session = sessionFactory.openSession();
try{
transaction = session.beginTransaction();
Object persistentInstance = session.load(hibernate.Contacts.class, contactKey);
if (persistentInstance != null) {
session.delete(persistentInstance);
}
transaction.commit();
}catch(HibernateException e){
if(transaction!= null) transaction.rollback();
e.printStackTrace();
}
finally{
session.close();
}
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
}
Try this:
Criteria criteria = session.createCriteria(Books.class);
List<Books> list = criteria.list();
for(Books test: list) {
System.out.println(test.getBooksKey + " " + test.getAuthor() + " " + test.getTitle());
}
If you there's any error, then please let me know about it.
You should change your code like following;
Query qry=session.createQuery("from books");
List<Books> user=(List<Books>) qry.list();
session.getTransaction().commit();
session.close();
List<Books> list = query.list();
for(Books test: list) {
System.out.println(test.getAuthor());
}
Here is the above code, I just want to add country class to the criteria such that if the deleteflag in country class is false, it should not fetch the states in staveprovince class:
public List<StateProvince> getAllState(Country country)throws HibernateException,ConstraintViolationException {
Session session = SessionFactoryUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
Criteria criteria = session.createCriteria(StateProvince.class);
criteria.setCacheable(true);
criteria.add(Restrictions.eq("country", country));
criteria.add(Restrictions.eq("deleteFlag", false));
return criteria.list();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
session.getTransaction().commit();
session.close();
}
}
I guess country is an attribute of StateProvince of type Country, so in that case your criteria must be the following:
criteria.createCriteria("country").add(Restrictions.eq("deleteFlag", false));
public class StateProvinceDAOImpl implements StateProvinceDAO {
#SuppressWarnings("unchecked")
#Override
public List<StateProvince> getAllState(Country country)throws HibernateException,ConstraintViolationException {
Session session = SessionFactoryUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
Criteria criteria = session.createCriteria(StateProvince.class,"state");
criteria.setCacheable(true);
criteria.createAlias("state.country", "country");
criteria.add(Restrictions.eqProperty("state.deleteFlag", "country.deleteFlag"));
criteria.add(Restrictions.eq("country", country));
criteria.add(Restrictions.eq("deleteFlag", false));
return criteria.list();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
session.getTransaction().commit();
session.close();
}
}
I am assuming you have Country associated in StateProvince. Please comment if this does not solve your problem.
public List<StateProvince> getAllState(Country country)throws HibernateException,ConstraintViolationException {
Session session = SessionFactoryUtil.getSessionFactory().openSession();
try {
session.beginTransaction();
Criteria criteria = session.createCriteria(StateProvince.class);
criteria.createAlias("country", "country");
criteria.setCacheable(true);
criteria.add(Restrictions.eq(deleteFlag", false));
criteria.add(Restrictions.eq("country", country));
criteria.add(Restrictions.eq("country.deleteFlag", false));
return criteria.list();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
session.getTransaction().commit();
session.close();
}
}
Why session object's delete method is not working in GenericDAOImpl.java, neither its giving any exception nor its showing any output. All other methods working fine expect public void delete(T object), Please help me, Sorry if i asked this question in wrong way.
public class GenericDAOImpl<T> implements IGenericDAO<T> {
private SessionFactory sessionFactory;
public GenericDAOImpl(Class<T> cl, SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
if (sessionFactory == null)
throw new RuntimeException("Session factory is null!!!");
}
#Override
public T get(Class<T> cl, Long id) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
#SuppressWarnings("unchecked")
T element = (T) session.get(cl, id);
session.getTransaction().commit();
return element;
}
#Override
public T get(Class<T> cl, Serializable obj) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
#SuppressWarnings("unchecked")
T element = (T) session.get(cl, obj);
session.getTransaction().commit();
return element;
}
#Override
public T save(T object) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
session.save(object);
session.getTransaction().commit();
return object;
}
#Override
public void update(T object) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
session.update(object);
session.getTransaction().commit();
}
#Override
public void delete(T object) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
session.delete(object);
session.getTransaction().commit();
}
#SuppressWarnings("unchecked")
#Override
public T findUniqueByQuery(String hsql, Map<String, Object> params) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery(hsql);
if (params != null) {
for (String i : params.keySet()) {
query.setParameter(i, params.get(i));
}
}
return (T) query.uniqueResult();
}
#SuppressWarnings("unchecked")
#Override
public List<T> query(String hsql, Map<String, Object> params) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery(hsql);
if (params != null) {
for (String i : params.keySet()) {
query.setParameter(i, params.get(i));
}
}
List<T> result = null;
if ((hsql.toUpperCase().indexOf("DELETE") == -1)
&& (hsql.toUpperCase().indexOf("UPDATE") == -1)
&& (hsql.toUpperCase().indexOf("INSERT") == -1)) {
result = query.list();
} else {
}
session.getTransaction().commit();
return result;
}
}
As investigated in comments, you are facing
org.hibernate.TransactionException: nested transactions not supported exception
This is happening because you began transaction and never committed or rollbacked upon an exception.
I can see one of it's case in your code. See your code below
#SuppressWarnings("unchecked")
#Override
public T findUniqueByQuery(String hsql, Map<String, Object> params) {
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery(hsql);
if (params != null) {
for (String i : params.keySet()) {
query.setParameter(i, params.get(i));
}
}
return (T) query.uniqueResult();
}
See, you began and never committed a transaction. Like wise check all other places in your project.
I have the same problem. Although I was not using transaction at all. I was using namedQuery like this :
Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES);
int rows = query.executeUpdate();
session.close();
It was returning 2 rows but the database still had all the records. Then wrap up the above code with this :
Transaction transaction = session.beginTransaction();
Query query = session.getNamedQuery(EmployeeNQ.DELETE_EMPLOYEES);
int rows = query.executeUpdate();
transaction.commit();
session.close();
Then it started working fine. I was using SQL server. But I think if we use h2 above code (without transaction) will also work fine.
org.hibernate.TransactionException: nested transactions not supported exception
Most probably you're not closing your session after an update or insert, and then you're doing the delete.
I am trying to run an update query which would look like this in sql:
update studentMaster set sess_status = 'G' where ACADEM_YEAR = COURSE_YEAR;
I am trying to re-create the query using Criteria like this:
public void updateSessionStatus() {
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
Criteria crit = sess.createCriteria(CollegeStudentsMaster.class);
crit.add(Restrictions.eqProperty("academicYear", "courseYears"));
CollegeStudentsMaster e = (CollegeStudentsMaster) crit.uniqueResult();
e.setSessionStatus("G");
sess.saveOrUpdate(e);
tx.commit();
} catch (HibernateException asd) {
if (tx != null) {
tx.rollback();
}
log.debug(asd.getMessage());
} finally {
sess.close();
}
}
This is not working because the rows which meet this Criteria are many, my unique result is the problem here I guess.
How can I convert this into an update for all the rows that meet the Criteria. I do not want to use HQL query, I am rather doing it with Criteria.
public void updateSessionStatus() {
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
Criteria crit = sess.createCriteria(CollegeStudentsMaster.class);
crit.add(Restrictions.eqProperty("academicYear", "courseYears"));
// Here is updated code
ScrollableResults items = crit.scroll();
int count=0;
while ( items.next() ) {
CollegeStudentsMaster e = (CollegeStudentsMaster)items.get(0);
e.setSessionStatus("G");
sess.saveOrUpdate(e);
if ( ++count % 100 == 0 ) {
sess.flush();
sess.clear();
}
}
tx.commit();
} catch (HibernateException asd) {
if (tx != null) {
tx.rollback();
}
log.debug(asd.getMessage());
} finally {
sess.close();
}
}
It is always suggested that execute bulk operations very close to database and we do not need keep updated object in session unless they are required, Hence try to avoid load objects in session while executing bulk operations.