In my project, I just generate the pojo and dao classes with the hibernate. But the dao classes generated by Hibernate are all in this style:
package com.ligadesportiva.data;
// Generated 14/03/2014 22:39:34 by Hibernate Tools 3.4.0.CR1
import java.util.List;
import javax.naming.InitialContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.LockMode;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.ligadesportiva.core.Jogador;
/**
* Home object for domain model class Jogador.
* #see com.ligadesportiva.data.Jogador
* #author Hibernate Tools
*/
public class JogadorHome {
private static final Log log = LogFactory.getLog(JogadorHome.class);
private final SessionFactory sessionFactory = getSessionFactory();
protected SessionFactory getSessionFactory() {
try {
return (SessionFactory) new InitialContext()
.lookup("SessionFactory");
} catch (Exception e) {
log.error("Could not locate SessionFactory in JNDI", e);
throw new IllegalStateException(
"Could not locate SessionFactory in JNDI");
}
}
public void persist(Jogador transientInstance) {
log.debug("persisting Jogador instance");
try {
sessionFactory.getCurrentSession().persist(transientInstance);
log.debug("persist successful");
} catch (RuntimeException re) {
log.error("persist failed", re);
throw re;
}
}
public void attachDirty(Jogador instance) {
log.debug("attaching dirty Jogador instance");
try {
sessionFactory.getCurrentSession().saveOrUpdate(instance);
log.debug("attach successful");
} catch (RuntimeException re) {
log.error("attach failed", re);
throw re;
}
}
public void attachClean(Jogador instance) {
log.debug("attaching clean Jogador instance");
try {
sessionFactory.getCurrentSession().lock(instance, LockMode.NONE);
log.debug("attach successful");
} catch (RuntimeException re) {
log.error("attach failed", re);
throw re;
}
}
public void delete(Jogador persistentInstance) {
log.debug("deleting Jogador instance");
try {
sessionFactory.getCurrentSession().delete(persistentInstance);
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
public Jogador merge(Jogador detachedInstance) {
log.debug("merging Jogador instance");
try {
Jogador result = (Jogador) sessionFactory.getCurrentSession()
.merge(detachedInstance);
log.debug("merge successful");
return result;
} catch (RuntimeException re) {
log.error("merge failed", re);
throw re;
}
}
public Jogador findById(int id) {
log.debug("getting Jogador instance with id: " + id);
try {
Jogador instance = (Jogador) sessionFactory.getCurrentSession()
.get("com.ligadesportiva.data.Jogador", id);
if (instance == null) {
log.debug("get successful, no instance found");
} else {
log.debug("get successful, instance found");
}
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
public List findByExample(Jogador instance) {
log.debug("finding Jogador instance by example");
try {
List results = sessionFactory.getCurrentSession()
.createCriteria("com.ligadesportiva.data.Jogador")
.add(Example.create(instance)).list();
log.debug("find by example successful, result size: "
+ results.size());
return results;
} catch (RuntimeException re) {
log.error("find by example failed", re);
throw re;
}
}
}
But I want data be saved/read from a postgresql database. Is there any code I should add to this project for make this dao classes interact with my DB?
Just for the record, I am put here some considerations about this subject I learn there few days:
First all, besides the two sets of classes generated by Hibernate (DAO and POJO), I create one anotherm based in this example:
http://www.baeldung.com/hibernate-4-spring
where I configure some options and methods of the Hibernate and point to the file where I place the options for conect to the database (database.properties).
After, I made some changes in the generated classes:
1) In the POJO class, I added the annotation #Entity and #Table for the class (and the second annotation with de parameter value="?", where ? is the name of the table associated to this class). For the attributes, I add the annotation #Column for all of them and the annotation #Id for the attribute related to the primary key.
2) In the DAO classes, I added the annotation #Repository for the class, and the annotation #Transactional for all the methods. Because of this annotation, I may insert in my *-servlet.xml file the follow line:
<tx:annotation-driven transaction-manager="transactionManager"/>
and in the header, this options:
xmlns:tx="http://www.springframework.org/schema/tx"
and inside xsi:schemaLocation:
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd.
Also, the atribute sessionFactory was annotated with #Autowired, the association was removed, and this methos was added:
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
For use of this class to handle the queries to database, I add them as atributes of the controller, always informing the annotation #Autowired.
Inside each method of the controller, I use the classes as this examples:
read data
Usuario novo = usuario.findById(this.getId_usuario());
save data
Sessao nova = new Sessao(novo, 0);
sessao.persist(nova);
Related
How to perform rollback in Spring Data JPA for the following scenario?
Transactional
#Override
public Employee saveEmployee(EmployeeDto dto) {
// check if EmployeeId and Department Id is present
Employee employee = this.getByEmployeeId(dto);
Department department = this.getByDepartmentId(dto);
Employee employee = convertToEntity(dto, employee, department);
employee.setEmployees(Arrays.asList(employee));
department.setEmployees(Arrays.asList(employee));
try {
employee = employeeRepository.save(employee); //line-11
} catch (DataIntegrityViolationException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ConstraintViolationException", e.getCause());
} catch (Exception ex) {
throw new InternalServerException(HttpStatus.INTERNAL_SERVER_ERROR, env.getProperty(IConst.ERROR_DB_EXCEPTION), ex);
}
EmployeeEmployeeDepartment r = new EmployeeEmployeeDepartment();
r.setId(new EmployeeDepartmentPK());
r.setEmployee(employee);
r.setDepartment(department);
r.setEmployee(employee);
try {
compositeRepository.save(r); //line-22
}catch (DataIntegrityViolationException e) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ConstraintViolationException", e.getCause());
}
catch (Exception ex) {
throw new InternalServerException(HttpStatus.INTERNAL_SERVER_ERROR, env.getProperty(IConst.ERROR_DB_EXCEPTION), ex);
}
return employee;
}
How to roll back line-11 if line-22 fails?
1) If ResponseStatusException and InternalServerException are both RuntimeExceptions then you do not need to do anything as Spring by default rolls back the entire transaction on any RTE.
2) Just keep in mind that invoking save() and eventually persist() on entityManager does not cause any physical update on the DB until the transaction commits. These methods simply register an entity in the Persistence Context.
Use "rollbackFor"
#Transactional(rollbackFor = DataIntegrityViolationException.class)
Multiple exception:
#Transactional(rollbackFor = { ResponseStatusException.class, InternalServerException.class })
I am getting following exception. The exception always comes back to the line:
Session session = HibernateUtil.getDefaultSession().openSession();
Here is a trimmed version of the stacktrace:
SEVERE: Servlet.service() for servlet [jsp] in context with path [/examAdmin] threw exception [java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at dao.AddCartDAO.deleteUnknownCartProduct(AddCartDAO.java:105)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:396)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
My HibernateUtil looks like--
public class HibernateUtil {
private static SessionFactory factory;
#SuppressWarnings("deprecation")
private HibernateUtil() {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getDefaultSession() {
return factory;
}
And my DAO looks like something
public void deleteUnknownCartProduct(String uid, String status) {
Session session = HibernateUtil.getDefaultSession().openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
String hql = "Delete AddCart a where a.userid=:userid and a.status=:status";
Query query = session.createQuery(hql);
query.setParameter("userid", uid);
query.setParameter("status", status);
query.executeUpdate();
tx.commit();
} catch (HibernateException e) {
if (tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
I have been trying numerous different things and Have tried as stackoverflow suggested however and still get same null-pointer at same line of code..
My folder structure:
You say that the exception is thrown in this line:
Session session = HibernateUtil.getDefaultSession().openSession();
Since HibernateUtil.getDefaultSession is a static method, this means that getDefaultSession() is returning null.
Then we look at getDefaultSession() and it is simply returning the the value of factory. ThisgetDefaultSession implies that factory is null. How come? Because your code is not initializing it!!
I can see you are attempting to initialize it in a constructor. But that can only work if you call the constructor. And you don't!
A better solution is to use a static method to do the initialization; e.g.
public class HibernateUtil {
private static SessionFactory factory = initFactory();
#SuppressWarnings("deprecation")
private static initFactory() {
try {
return new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getDefaultSession() {
return factory;
}
}
With this session handler:
public class SessionHandler {
private static SessionFactory DBContext;
static {
try {
DBContext = HibnerateConfiguration.config().buildSessionFactory();
}
catch(Throwable t) {
throw new ExceptionInInitializerError(t);
}
}
/*
* Returns a session anyway. If currently no session exist, open a new one;
* If there is a current session, use the existing one.
*/
#Override
public Session getSession() {
try {
return DBContext.getCurrentSession();
}
catch (HibernateException he) {
logger.error("session already exist.");
return DBContext.getCurrentSession();
}
}
public void close() {
DBContext.close();
}
}
and the following create and get methods:
public Serializable create(T type_entity) {
Session session = getSessionHandler().getSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Serializable result = session.save(type_entity);
tx.commit();
return result;
} catch (HibernateException ex) {
ex.printStackTrace();
if (tx!=null) tx.rollback();
throw ex;
} finally {
getSessionHandler().close();
}
}
#SuppressWarnings("unchecked")
public T get(Serializable id) throws InvalidRequestException {
Session session = getSessionHandler().getSession();
Transaction tx = session.beginTransaction();
tx.commit();
try {
Object obj = session.get(_classtype, id);
if (obj == null) {
throw new InvalidRequestException(String.format("requested object with id %s does not exist.", id));
} else {
return (T)obj;
}
} catch(HibernateException ex) {
ex.printStackTrace();
if (tx!=null) tx.rollback();
throw ex;
} finally {
getSessionHandler().close();
}
}
When I create an object that returns me id = 4, and if immediately I make a request on browser that eventually ask for the new object of id 4, I have to wait for a few seconds (last time I tried is > 3 seconds).
When the id is returned from the create, the data should already exist. However the get returns null. I highly suspect the get is using the old cache which then is updated every a few seconds, but I have no idea how to fix it.
Let me know if any info is required and I am happy to provide them.
I have the following situation with Java persistence:
public ReturnCodes startWork() {
sessionBackup = (BaseService<Backup>) ctx.lookup("XYZ/BackupServiceImpl/local");
Backup backup = new Backup();
backup.setStatus(BackupStatus.EXECUTING);
....
sessionBackup.save(Backup) //at this point is not actualy saved into DB
....//try to connect somewhere
if ( !ConnectSuccess) {
sessionBackup.remove(backup);
return ReturnCodes.REQUESTABORT
}
....
}
#Stateless
public class BackupServiceImpl extends BaseServiceImpl<Backup> implements
BaseService<Backup>
{
#Override
protected Class<Backup> getEntityClass()
{
return Backup.class;
}
}
And the save and remove methods of BaseServiceImpl:
public abstract class BaseServiceImpl<T extends Serializable> implements
BaseService<T>
{
protected EntityManagerFactory emf;
public T save(T entity)
{
EntityManager em = emf.createEntityManager();
em.persist(entity);
return entity;
}
public void remove(T entity)
{
EntityManager em = emf.createEntityManager();
try
{
final Method method = getEntityClass().getMethod("getId");
final String id = (String) ((T) method.invoke(entity));
entity = em.find(getEntityClass(), id);
em.remove(entity);
}
catch (final Exception ex)
{
logger.log(Level.WARNING, "Unexpected error", ex);
}
}
}
I don't want to save into the DB in case ConnectSuccess fails, but the remove method fails to find the entity (because is not yet into the DB), and after returning ReturnCodes.REQUESTABORT the entity is saved.
How can I cancel the save?
In general in this case you do a setRollbackOnly().
You may also throw an exception which will trigger the rollbackonly.
See http://www.developerscrappad.com/547/java/java-ee/ejb3-x-jpa-when-to-use-rollback-and-setrollbackonly/
By the way doing this in your code:
catch (final Exception ex)
{
logger.log(Level.WARNING, "Unexpected error", ex);
}
is too broad and will block rollback functionality.
I have written this Hibernate object DAO, however with this approach, it is using session per update approach (which I don't think it's right).
The reason why I don't think its right because I am running into problems with my User class, which contains collections that are lazily fetched. Since when retrieving each User from the DAO, the session is closed. Therefore I cannot get my collections.
From time to time, it is also doing a lot of unnecessary updates to the table because the object is detached.
So are there any ways of fixing my DAO, like using getCurrentSession()?
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.test.util.DataAccessLayerException;
import org.test.util.HibernateUtil;
public abstract class AbstractDao {
protected Session session;
protected Transaction tx;
public AbstractDao() {
HibernateUtil.buildIfNeeded();
}
protected void saveOrUpdate(Object obj) {
try {
startOperation();
session.saveOrUpdate(obj);
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateUtil.close(session);
}
}
protected void delete(Object obj) {
try {
startOperation();
session.delete(obj);
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateUtil.close(session);
}
}
protected Object find(Class clazz, Long id) {
Object obj = null;
try {
startOperation();
obj = session.load(clazz, id);
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateUtil.close(session);
}
return obj;
}
protected List findAll(Class clazz) {
List objects = null;
try {
startOperation();
Query query = session.createQuery("from " + clazz.getName());
objects = query.list();
tx.commit();
} catch (HibernateException e) {
handleException(e);
} finally {
HibernateUtil.close(session);
}
return objects;
}
protected void handleException(HibernateException e) throws DataAccessLayerException {
HibernateUtil.rollback(tx);
throw new DataAccessLayerException(e);
}
protected void startOperation() throws HibernateException {
session = HibernateUtil.openSession();
tx = session.beginTransaction();
}
}
HibernateUtil
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static Log log = LogFactory.getLog(HibernateUtil.class);
private static SessionFactory sessionFactory;
private static SessionFactory configureSessionFactory()
throws HibernateException {
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
return sessionFactory;
}
public static SessionFactory buildIfNeeded()
throws DataAccessLayerException {
if (sessionFactory != null) {
return sessionFactory;
}
try {
return configureSessionFactory();
} catch (HibernateException e) {
throw new DataAccessLayerException(e);
}
}
public static SessionFactory buildSessionFactory()
throws HibernateException {
if (sessionFactory != null) {
closeFactory();
}
return configureSessionFactory();
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
public static Session openSession() throws HibernateException {
buildIfNeeded();
return sessionFactory.openSession();
}
public static void closeFactory() {
if (sessionFactory != null) {
try {
sessionFactory.close();
} catch (HibernateException ignored) {
log.error("Couldn't close SessionFactory", ignored);
}
}
}
public static void close(Session session) {
if (session != null) {
try {
session.close();
} catch (HibernateException ignored) {
log.error("Couldn't close Session", ignored);
}
}
}
public static void rollback(Transaction tx) {
try {
if (tx != null) {
tx.rollback();
}
} catch (HibernateException ignored) {
log.error("Couldn't rollback Transaction", ignored);
}
}
}
Good approach is to add close method to your DAO(AbstractDao) and call it the end of your "unit of work".
And, please, no static references to session, session is not thread safe
Here is a brilliant explanation with sample: Link
You can hold a static Session member in HibernateUtil. Lazy initialized.
An close the session whenever you want, but until it isn't closed, you'll keep using it.