package com.fp.persistence.commondb; import java.sql.Timestamp; import java.util.ResourceBundle; import javax.ejb.NoSuchEntityException; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.SystemException; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; import org.hibernate.HibernateException; import org.hibernate.Session; import bitronix.tm.TransactionManagerServices; import com.fp.common.exception.APPException; import com.fp.common.exception.CommonException; import com.fp.common.helper.BeanManager; import com.fp.common.logger.APPLogger; import com.fp.dto.AbstractDataTransport; import com.fp.dto.data.SaveData; import com.fp.dto.hb.Cache; import com.fp.dto.hb.HibernateBean; import com.fp.dto.hb.History; import com.fp.dto.hb.Log; import com.fp.persistence.commondb.cache.CacheManager; import com.fp.persistence.commondb.exception.CommondbException; import com.fp.persistence.commondb.helper.FormatDates; import com.fp.persistence.commondb.log.Audit; public class PersistenceHelper { /** * Almacena un EntityManager de JPA. */ private static final ThreadLocal threadSession = new ThreadLocal(); /** * Almacena una transaccion de Hibernate. */ // private static final ThreadLocal threadTransaction = new ThreadLocal(); private static final ThreadLocal threadTransaction = new ThreadLocal(); private static final ThreadLocal threadTransactionManager = new ThreadLocal(); private static final ThreadLocal threadEntityTransaction = new ThreadLocal(); private static final ThreadLocal threadcommit = new ThreadLocal(); /** * Retorna una session de hibernate. * * @return s * @throws CommonException * @throws Exception */ public static Session getSession() throws CommondbException { Session s = (Session) PersistenceHelper.threadSession.get().getDelegate(); if (s == null) { throw new CommondbException("COMMONDB-0004", "SESION NO ASOCIADA A UNA TRANSACCION"); } return s; } public static boolean isrollbackonly() { try { UserTransaction ut = PersistenceHelper.threadTransaction.get(); if (ut != null) { int i = ut.getStatus(); if (i == javax.transaction.Status.STATUS_MARKED_ROLLBACK) { return true; } } TransactionManager tm = PersistenceHelper.threadTransactionManager.get(); if (tm != null) { int i = tm.getStatus(); if (i == javax.transaction.Status.STATUS_MARKED_ROLLBACK) { return true; } } return false; } catch (Exception e) { return false; } } /** * Retorna una Connection de tipo sql * * @return Connection * @throws CommonException * @throws Exception */ @SuppressWarnings("deprecation") /* public static Connection getConnection() throws CommondbException { Session s = (Session) PersistenceHelper.threadSession.get().getDelegate(); if (s == null) { throw new CommondbException("COMMONDB-0004", "SESION NO ASOCIADA A UNA TRANSACCION"); } return s.connection(); } */ public static EntityManager getEntityManager() throws CommondbException { EntityManager em = PersistenceHelper.threadSession.get(); if (em == null) { throw new CommondbException("COMMONDB-0004", "SESION NO ASOCIADA A UNA TRANSACCION"); } return em; } /** * Encera y cierra el EntityManager. */ public static void closeSession() { try { EntityManager em = PersistenceHelper.threadSession.get(); if ((em != null)) { em.clear(); } if (em.isOpen()) { em.close(); } PersistenceHelper.threadTransaction.set(null); PersistenceHelper.threadSession.set(null); PersistenceHelper.threadcommit.set(null); PersistenceHelper.threadTransactionManager.set(null); PersistenceHelper.threadEntityTransaction.set(null); } catch (Exception e) { APPLogger.getLogger().error(e); } } /** * Fija una session de hibernate. * * @param session * @throws Exception */ public static boolean getThreadcommit() { if (PersistenceHelper.threadcommit.get() == null) { return true; } return PersistenceHelper.threadcommit.get(); } /** * Fija una session de hibernate. * * @param session * @throws Exception */ public static void setThreadcommit(boolean pDocommit) { PersistenceHelper.threadcommit.set(pDocommit); } /** * Fija una session de hibernate. * * @param session * @throws Exception */ public static void setEntityManager(EntityManager pEntityManager) { PersistenceHelper.threadSession.set(pEntityManager); } /** * Inicia el proceso de una transaccion de hibernate.. * * @throws CommonException * @throws HibernateException * @throws SystemException * @throws NotSupportedException * @throws NamingException * @throws Exception */ public static EntityTransaction beginTransactionLocal() throws HibernateException, CommondbException, NotSupportedException, SystemException, NamingException { EntityTransaction et = PersistenceHelper.getEntityManager().getTransaction(); PersistenceHelper.threadEntityTransaction.set(et); et.begin(); return et; } /** * Inicia el proceso de una transaccion de hibernate.. * * @throws CommonException * @throws HibernateException * @throws SystemException * @throws NotSupportedException * @throws NamingException * @throws Exception */ public static UserTransaction beginTransaction() throws HibernateException, CommondbException, NotSupportedException, SystemException, NamingException { PersistenceHelper.called(); UserTransaction ut = (UserTransaction) new InitialContext().lookup("java:comp/UserTransaction"); PersistenceHelper.threadTransaction.set(ut); ut.begin(); PersistenceHelper.getEntityManager().joinTransaction(); return ut; } public static void beginNewTransaction() throws HibernateException, CommondbException, NotSupportedException, SystemException, NamingException { // WebLogic javax.transaction.TransactionManager // JBOSS java:/TransactionManager TransactionManager tm = null; try { tm = (TransactionManager) new InitialContext().lookup("java:/TransactionManager"); } catch (NameNotFoundException e) { tm = TransactionManagerServices.getTransactionManager(); } PersistenceHelper.threadTransactionManager.set(tm); tm.begin(); PersistenceHelper.getEntityManager().joinTransaction(); } /** * Graba los dml que estan en la transaccion. * * @throws CommonException * @throws Exception */ public static void commitNewTransaction() throws Exception { if (!PersistenceHelper.getThreadcommit()) { PersistenceHelper.rollbackNewTransaction(); return; } if (PersistenceHelper.isrollbackonly()) { PersistenceHelper.called(); throw new APPException("FLIP01", "TRANSACCION NO PERMITE COMMIT"); } TransactionManager tx = PersistenceHelper.threadTransactionManager.get(); try { if ((tx != null)) { try { if (ResourceBundle.getBundle("jndi").getString(Context.INITIAL_CONTEXT_FACTORY) .compareTo("bitronix.tm.jndi.BitronixInitialContextFactory") == 0) { PersistenceHelper.flushTransaction(); PersistenceHelper.getEntityManager().createNativeQuery("commit").executeUpdate(); } } catch (Exception e) { // No hacer nada } tx.commit(); } else { throw new CommondbException("COMMONDB-0005", "TRANSACCION YA APLICADA"); } } finally { PersistenceHelper.getEntityManager().clear(); PersistenceHelper.threadTransactionManager.set(null); } } /** * Graba los dml que estan en la transaccion. * * @throws CommonException * @throws Exception */ public static void commitTransaction() throws CommondbException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException, SystemException, APPException { if (!PersistenceHelper.getThreadcommit()) { PersistenceHelper.rollbackTransaction(); return; } PersistenceHelper.called(); if (PersistenceHelper.isrollbackonly()) { throw new APPException("COMMONDB-0006", "TRANSACCION NO PUEDE SER PROCESADA "); } UserTransaction tx = PersistenceHelper.threadTransaction.get(); try { if ((tx != null)) { tx.commit(); } else { throw new CommondbException("COMMONDB-0005", "TRANSACCION YA APLICADA"); } } finally { PersistenceHelper.getEntityManager().clear(); PersistenceHelper.threadTransaction.set(null); } } /** * Graba los dml que estan en la transaccion. * * @throws CommonException * @throws Exception */ public static void commitTransactionLocal() throws CommondbException, SecurityException, IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException, SystemException, APPException { if (!PersistenceHelper.getThreadcommit()) { PersistenceHelper.rollbackTransaction(); return; } PersistenceHelper.called(); if (PersistenceHelper.isrollbackonly()) { throw new APPException("COMMONDB-0006", "TRANSACCION NO PUEDE SER PROCESADA "); } EntityTransaction tx = PersistenceHelper.threadEntityTransaction.get(); try { if ((tx != null)) { tx.commit(); } else { throw new CommondbException("COMMONDB-0005", "TRANSACCION YA APLICADA"); } } finally { PersistenceHelper.getEntityManager().clear(); PersistenceHelper.threadTransaction.set(null); } } /** * Graba los dml que estan en la transaccion. * * @throws CommondbException */ public static void flushTransaction() throws Exception { if (PersistenceHelper.isrollbackonly()) { PersistenceHelper.called(); throw new APPException("COMMONDB-0006", "TRANSACCION NO PUEDE SER PROCESADA "); } EntityManager em = PersistenceHelper.getEntityManager(); em.flush(); } private static void called() { StackTraceElement st = new Exception().getStackTrace()[2]; StackTraceElement st1 = new Exception().getStackTrace()[1]; APPLogger.getLogger().info( st1.getMethodName().toUpperCase() + "==>>" + st.getClassName() + "." + st.getMethodName() + ":" + st.getLineNumber()); } /** * rollback de los dml que estan dentro de la transaccion. * * @throws SystemException * @throws SecurityException * @throws IllegalStateException * * @throws CommonException */ public static void rollbackTransaction() { PersistenceHelper.called(); UserTransaction tx = PersistenceHelper.threadTransaction.get(); try { if ((tx != null)) { try { PersistenceHelper.getEntityManager().createNativeQuery("rollback").executeUpdate(); } catch (Exception e) { // NO HACER NADA } tx.setRollbackOnly(); tx.rollback(); } } catch (Exception e1) { APPLogger.getLogger().error(e1, e1); } finally { PersistenceHelper.threadTransaction.set(null); } } /** * rollback de los dml que estan dentro de la transaccion. * * @throws SystemException * @throws SecurityException * @throws IllegalStateException * * @throws CommonException */ public static void rollbackTransactionLocal() { PersistenceHelper.called(); EntityTransaction tx = PersistenceHelper.threadEntityTransaction.get(); try { if ((tx != null)) { try { PersistenceHelper.getEntityManager().createNativeQuery("rollback").executeUpdate(); } catch (Exception e) { // NO HACER NADA } tx.setRollbackOnly(); tx.rollback(); } } catch (Exception e1) { APPLogger.getLogger().error(e1, e1); } finally { PersistenceHelper.threadTransaction.set(null); } } /** * rollback de los dml que estan dentro de la transaccion. * * @throws SystemException * @throws SecurityException * @throws IllegalStateException * * @throws CommonException */ public static void rollbackNewTransaction() { Exception e = new Exception(); StackTraceElement s = e.getStackTrace()[1]; APPLogger.getLogger().error(s.getClassName() + "." + s.getMethodName() + ":" + s.getLineNumber()); TransactionManager tx = PersistenceHelper.threadTransactionManager.get(); if (PersistenceHelper.isrollbackonly()) { } try { if ((tx != null)) { try { PersistenceHelper.getEntityManager().createNativeQuery("rollback").executeUpdate(); } catch (Exception ex) { tx.setRollbackOnly(); // NO HACER NADA } tx.setRollbackOnly(); tx.rollback(); } } catch (Exception e1) { APPLogger.getLogger().error(e1, e1); } finally { PersistenceHelper.threadTransactionManager.set(null); } } /** * Retorna verdadero si a la transacci�n se dio un commit; * * @return boolean * @throws Exception */ public static boolean isCommitted() throws Exception { // EntityTransaction tx = PersistenceHelper.threadTransaction.get(); UserTransaction tx = PersistenceHelper.threadTransaction.get(); // if ((tx != null) && !tx.isActive()) { if ((tx != null)) { return false; } return true; } /** * Retorna verdadero si a la transacci�n se dio un commit; * * @return boolean * @throws Exception */ public static boolean isRolledBack() throws Exception { // EntityTransaction tx = PersistenceHelper.threadTransaction.get(); // if ((tx != null) && !tx.isActive()) { UserTransaction tx = PersistenceHelper.threadTransaction.get(); if ((tx != null)) { return false; } return true; } /** * Inserta un registro en la base de datos. * * @param pClassName Nombre de la clase que maneja la persistencia de una * tabla. * @param pBean Bean a insertar. * @throws CommonException * @throws Exception */ public static void save(HibernateBean pBean) throws CommondbException, Exception { EntityManager em = PersistenceHelper.getEntityManager(); Object id = BeanManager.getBeanAttributeValue(pBean, "pk"); if ((id instanceof History)) { if (BeanManager.getBeanAttributeValue(pBean, "datefrom") == null) { Timestamp t = FormatDates.getInstance().getDataBaseTimestamp(); BeanManager.setBeanAttributeValue(pBean, "datefrom", t); } History pk = (History) id; BeanManager.setBeanAttributeValue(pk, "dateto", FormatDates.getDefaultExpiryTimestamp()); } PersistenceHelper.setIngressUser(pBean); PersistenceHelper.setLastupdate(pBean); PersistenceHelper.setCreationDate(pBean); // s.psave(pClassName,pBean); em.persist(pBean); if (pBean instanceof Log) { Audit.insert(pBean); } } /** * Actualiza un registro en la base de datos. * * @param pBean Bean a actualiar. * @throws CommonException * @throws Exception */ public static void update(HibernateBean pBean) throws CommondbException { EntityManager em = PersistenceHelper.getEntityManager(); // pBean = em.merge(pBean); if (!em.contains(pBean)) { throw new NoSuchEntityException(); } } /** * Actualiza o inserta un registro en la base de datos. * * @param pBean Bean a actualiar o insertar. * @throws CommonException * @throws Exception */ public static void saveOrUpdate(HibernateBean pBean) throws CommondbException, Exception { PersistenceHelper.called(); APPLogger.getLogger().info(pBean.getClass().getName()); APPLogger.getLogger().debug(pBean); EntityManager em = PersistenceHelper.getEntityManager(); Object id = BeanManager.getBeanAttributeValue(pBean, "pk"); if ((id instanceof History)) { HibernateBean bean = PersistenceHelper.manageHistory(pBean, id); pBean = em.merge(bean); } else { em.detach(pBean); PersistenceHelper.setModifyUser(pBean); PersistenceHelper.setLastupdate(pBean); PersistenceHelper.setCreationDate(pBean); if (pBean instanceof Cache) { // Limpia el cache de datos internamente obtiene el nombre real del bean sin considerar el paquete. CacheManager cm = CacheManager.getInstance(); cm.clean(pBean.getClass().getName()); } if ((pBean instanceof Log)) { HibernateBean oldbean = em.find(pBean.getClass(), id); if (oldbean != null) { // Graba log de auditoria. Audit.process(pBean, oldbean); } } pBean = em.merge(pBean); } } public static void persist(HibernateBean pBean) throws CommondbException, Exception { EntityManager em = PersistenceHelper.getEntityManager(); PersistenceHelper.setIngressUser(pBean); em.persist(pBean); Audit.insert(pBean); } /** * Metodo que se encarga de caducar un registro que maneja historia. * * @param pBean Bean a caducar. * @throws CommondbException * @throws Exception */ public static void expire(HibernateBean pBean) throws CommondbException, Exception { EntityManager em = PersistenceHelper.getEntityManager(); Object id = BeanManager.getBeanAttributeValue(pBean, "pk"); if ((id instanceof History)) { HibernateBean newbean = (HibernateBean) pBean.cloneMe(); PersistenceHelper.getEntityManager().remove(pBean);; History pk = (History) BeanManager.getBeanAttributeValue(newbean, "pk"); pk.setDateto(FormatDates.getInstance().getDataBaseTimestamp()); em.persist(newbean); } if (pBean instanceof Cache) { // Limpia el cache de la tabla. CacheManager cm = CacheManager.getInstance(); cm.clean(pBean.getClass().getName()); } } /** * Caduca registro persistente. * * @param pBean Bean a caducar. * @throws CommonException * @throws Exception */ public static void delete(HibernateBean pBean) throws CommondbException, Exception { EntityManager em = PersistenceHelper.getEntityManager(); Object id = BeanManager.getBeanAttributeValue(pBean, "pk"); if (id == null) { return; } if (pBean != null) { if ((id instanceof History)) { //Las siguientes 3 lineas corrigen el problema con los registros que manejan auditoria History pk = (History) BeanManager.getBeanAttributeValue(pBean, "pk"); if (pk.getDateto() == null) { pk.setDateto(FormatDates.getDefaultExpiryTimestamp()); } HibernateBean newbean = (HibernateBean) pBean.cloneMe(); PersistenceHelper.expireRecord(newbean, FormatDates.getInstance().getDataBaseTimestamp()); } if (!em.contains(pBean)) { em.remove(em.find(pBean.getClass(), id)); } else { em.remove(pBean); } if (pBean instanceof Log) { Audit.delete(pBean); } } if (pBean instanceof Cache) { // Limpia el cache de la tabla. CacheManager cm = CacheManager.getInstance(); cm.clean(pBean.getClass().getName()); } } /** * Metodo que se encarga del manejo de la historia de registros en la base, * si estos manejan date from date to. * * @param pBean Bena a almacenar en la base de datos. * @return HibernateBean * @throws Exception */ private static HibernateBean manageHistory(HibernateBean pBean, Object pid) throws Exception { EntityManager em = PersistenceHelper.getEntityManager(); Object id = pid; HibernateBean oldbean = null; HibernateBean newbean = pBean; if ((id instanceof History)) { History pk = (History) id; if (pk.getDateto() == null) { // Si es null y existe un registro en la base indica que se da mantenimiento sobre el mismo registro, en // este caso // se elimina de la base. PersistenceHelper.verifyBean(em, pBean, id); // pk.setDateto(null); } if (pk.getDateto() != null) { Object obj = ((AbstractDataTransport)pBean).get("ORIGINALBEAN"); if(obj == null){ em.detach(pBean); newbean = (HibernateBean) pBean.cloneMe(); oldbean = em.find(pBean.getClass(), id); if(oldbean != null){ em.detach(oldbean); } }else{ oldbean = (HibernateBean)obj; } id = BeanManager.getBeanAttributeValue(newbean, "pk"); pk = (History) id; if (pk.getDateto().compareTo(FormatDates.getDefaultExpiryTimestamp()) < 0) { return pBean; } } Timestamp t = FormatDates.getInstance().getDataBaseTimestamp(); if ((pBean instanceof Cache) && (oldbean != null)) { // Limpia el cache de la tabla unicamente si esta dando mantenimiento a un registro. CacheManager cm = CacheManager.getInstance(); cm.clean(pBean.getClass().getName()); } if ((pBean instanceof Log)) { // Graba log de auditoria. if (oldbean != null) { Audit.process(pBean, oldbean); } else { Audit.insert(pBean); } } if ((oldbean != null) && !BeanManager.compareObject(pBean, oldbean)) { PersistenceHelper.expireRecord(oldbean, t); BeanManager.setBeanAttributeValue(newbean, "datefrom", t); } if (BeanManager.getBeanAttributeValue(newbean, "datefrom") == null) { BeanManager.setBeanAttributeValue(newbean, "datefrom", t); } BeanManager.setBeanAttributeValue(pk, "dateto", FormatDates.getDefaultExpiryTimestamp()); PersistenceHelper.setpartition(pk, pk.getDateto()); PersistenceHelper.setModifyUser(newbean); } return newbean; } /** * Si valor de dateto es null y existe un registro en la base indica que se * da mantenimiento sobre el mismo registro, en este caso se elimina el * registro de la base. * * @param em EntityManager utilizado en dml. * @param pBean Referencia al bean persistente. * @param id Pk del bean. * @throws Exception */ private static void verifyBean(EntityManager em, HibernateBean pBean, Object id) throws Exception { try { History pk = (History) id; pk.setDateto(FormatDates.getDefaultExpiryTimestamp()); HibernateBean oldbean = em.find(pBean.getClass(), id); if (oldbean != null) { em.detach(pBean); em.remove(oldbean); } } catch (Exception e) { // No hacer nada } } /** * Metodo que expira un registro en la base de datos. * * @param pOldBean Objeto que contiene el registro de una tabla a expirar. * @param pTimestamp Fecha con la cual se expira un registro. * @throws Exception */ public static void expireRecord(HibernateBean pOldBean, Timestamp pTimestamp) throws Exception { EntityManager em = PersistenceHelper.getEntityManager(); History pk = (History) BeanManager.getBeanAttributeValue(pOldBean, "pk"); pk.setDateto(pTimestamp); PersistenceHelper.setpartition(pk, pTimestamp); em.persist(pOldBean); } /** * Metodo fija la particion en un registro, la particion es yyyymm del campo * dateto. * * @param pHistory Pk de un registro. * @param pTimestamp fecha con la cual se caduca un registro. * @throws Exception */ private static void setpartition(History pHistory, Timestamp pTimestamp) throws Exception { try { BeanManager.setBeanAttributeValue(pHistory, "partition", FormatDates.getPartition(pTimestamp)); } catch (Exception e1) { } } /** * Metodo que separa el objeto de la session de la base de datos. * * @param pBean Objeto a separar de la base de datos. * @throws Exception */ public static void detatch(HibernateBean pBean) throws Exception { if(pBean != null){ PersistenceHelper.called(); EntityManager em = PersistenceHelper.getEntityManager(); em.detach(pBean); } } /** * Fija el usuario de creacion de un registro. * * @param pBean Objeto a almacenar en la base de datos. * @throws Exception */ public static void setIngressUser(HibernateBean pBean) throws Exception { try { BeanManager.setBeanAttributeValue(pBean, "ingressuser", SaveData.getSaveRequest().getUser()); } catch (Exception e) { try { BeanManager.setBeanAttributeValue(pBean, "ingressusercode", SaveData.getSaveRequest().getUser()); } catch (Exception e2) { // Si no existe el campo en el bean no hacer nada. } } } /** * Fija el usuario de creacion de un registro. * * @param pBean Objeto a almacenar en la base de datos. * @throws Exception */ public static void setLastupdate(HibernateBean pBean) throws Exception { try { BeanManager.setBeanAttributeValue(pBean, "lastupdate", SaveData.getSaveRequest().get("accountingdate")); } catch (Exception e) { // Si no existe el campo en el bean no hacer nada. } } /** * Fija el fecha de admision de un registro. * * @param pBean Objeto a almacenar en la base de datos. * @throws Exception */ public static void setCreationDate(HibernateBean pBean) throws Exception { try { if (BeanManager.getBeanAttributeValue(pBean, "creationdate") == null) { BeanManager.setBeanAttributeValue(pBean, "creationdate", SaveData.getSaveRequest().get("accountingdate")); } } catch (Exception e) { // Si no existe el campo en el bean no hacer nada. } } /** * Fija el usuario de creacion de un registro. * * @param pBean Objeto a almacenar en la base de datos. * @throws Exception */ public static void setModifyUser(HibernateBean pBean) throws Exception { try { BeanManager.setBeanAttributeValue(pBean, "modifyuser", SaveData.getSaveRequest().getUser()); } catch (Exception e) { try { BeanManager.setBeanAttributeValue(pBean, "modifyusercode", SaveData.getSaveRequest().getUser()); } catch (Exception e2) { // Si no existe el campo en el bean no hacer nada. } } } public static Query prepareQuery(String pName, Integer pPage, Integer pRecords) throws Exception { Query q = PersistenceHelper.getEntityManager().createNamedQuery(pName); q.setFirstResult((pPage - 1) * pRecords); q.setMaxResults(pRecords); return q; } public static Query prepareQuery(String pName) throws Exception { return PersistenceHelper.getEntityManager().createNamedQuery(pName); } public static Query createQuery(String pJPQL) throws Exception { return PersistenceHelper.getEntityManager().createQuery(pJPQL); } public static Query createNativeQuery(String pSQL) throws Exception { return PersistenceHelper.getEntityManager().createNativeQuery(pSQL); } public static TypedQuery prepareQuery(String pName, Class pType) throws Exception { return PersistenceHelper.getEntityManager().createNamedQuery(pName, pType); } }