package com.fitbank.common.hb; import java.io.Serializable; import java.math.BigDecimal; import java.sql.Date; import java.sql.Timestamp; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.hibernate.LockMode; import org.hibernate.Query; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.type.Type; import com.fitbank.common.Helper; import com.fitbank.common.exception.FitbankException; import com.fitbank.common.logger.FitbankLogger; import org.apache.commons.lang.StringUtils; import org.hibernate.FlushMode; import org.hibernate.LockOptions; import org.hibernate.type.StandardBasicTypes; /** * Clase utilitaria para armar sentencias y obtener resultados a consultas a la * base de datos con Hibernate. * * @param Tipo de los resultados * * @author Fitbank * @version 2.0 */ public final class UtilHB { /** * Session de hibernate empleada en la consulta */ private final Session session; /** * Map auxiliar empleado para el manejo de Parámetros */ private Map map; /** * Sentencia HQL a ejecutar */ private String sentence; /** * Indicador de si la consulta requiere manejar Cache */ private boolean cacheable = false; /** * Indicador de si la consulta es de Lectura solamente */ private boolean readonly = false; /** * Tipo de Bloqueo pesimista que debe aplicarse a la consulta */ private LockOptions lockOptions; /** * Modo de hacer flush antes de ejecutar el query. */ private FlushMode flushMode = null; /** * Alias de la variable a bloquear */ private String alias; /** * Página en la que se encuentra la consulta */ private Integer page = null; /** * Número de registros por página */ private Integer recordperpage = null; /** * Referencia al Log. */ private static final Logger LOGGER = FitbankLogger.getLogger(); /** * Crea una nueva instancia de UtilHB * */ public UtilHB() { this(null, LockOptions.NONE, null); } public UtilHB(Session pSession) { this(null, pSession, LockOptions.NONE, null); } /** * Crea una nueva instancia con una sentencia a ejecutar. * * @param pSentence */ public UtilHB(String pSentence) { this(pSentence, LockOptions.NONE, null); } public UtilHB(String pSentence, LockMode pLockMode, String pAlias) { this(pSentence, Helper.getSession(), pLockMode, pAlias); } public UtilHB(String pSentence, LockOptions pLockOptions, String pAlias) { this(pSentence, Helper.getSession(), pLockOptions, pAlias); } public UtilHB(String pSentence, Session pSession) { this(pSentence, pSession, LockOptions.NONE, null); } public UtilHB(String pSentence, FlushMode flushMode) { this(pSentence, Helper.getSession(), LockOptions.NONE, flushMode, null); } /** * Crea una nueva instancia con una sentencia a ejecutar. * * @param pSentence Sentencia a ejecutar * @param pSession Sesion * @param pLockMode Tipo de Bloqueo Pesismista * @param pAlias Variable a bloquear */ public UtilHB(String pSentence, Session pSession, LockMode pLockMode, String pAlias) { this.sentence = pSentence; this.map = new HashMap(); this.session = pSession; this.lockOptions = new LockOptions(pLockMode); this.alias = pAlias; } /** * Crea una nueva instancia con una sentencia a ejecutar. * * @param pSentence Sentencia a ejecutar * @param pSession Sesion * @param pLockMode Tipo de Bloqueo Pesismista * @param pAlias Variable a bloquear */ public UtilHB(String pSentence, Session pSession, LockOptions pLockOptions, String pAlias) { this.sentence = pSentence; this.map = new HashMap(); this.session = pSession; this.lockOptions = pLockOptions; this.alias = pAlias; } public UtilHB(String pSentence, Session pSession, LockOptions pLockOptions, FlushMode flushMode, String pAlias) { this.sentence = pSentence; this.map = new HashMap(); this.session = pSession; this.lockOptions = pLockOptions; this.flushMode = flushMode; this.alias = pAlias; } // public String getSentence() { return this.sentence; } public void setSentence(String pSentence) { this.map.clear(); this.sentence = pSentence; } public boolean isCacheable() { return this.cacheable; } public void setCacheable(boolean cacheable) { this.cacheable = cacheable; } public boolean isReadonly() { return this.readonly; } public void setReadonly(boolean readonly) { this.readonly = readonly; } public Integer getPage() { return this.page; } public void setPage(Integer pPage) { this.page = pPage; } public Integer getRecordperpage() { return this.recordperpage; } public void setRecordperpage(Integer pRecordperpage) { this.recordperpage = pRecordperpage; } // public List getList() { return this.getList(true); } /** * Retorna una lista de entidades o arreglos. * * @param pNoDataFound lanza o no la excepcion (true=ejecuta, false=ignora) * * @return lista */ public List getList(boolean pNoDataFound) { List result = this.buildQuery().list(); if (result == null || result.isEmpty()) { if (pNoDataFound) { throw new FitbankException("HB004", "CONSULTA NO TIENE REGISTROS"); } else { return new ArrayList(); } } return result; } /** * Retorna: un entity si la sentencia retorna un entity, si es un conjunto * de campos de una o mas tablas retorna un Array. *
    *
  1. Objeto que contiene una entidad si la sentencia retorna un entity *
    * sentencia ==> from com.test.Test as t where t.pk.c1 = :valor1
  2. *
  3. Array que contiene una entidad si la sentencia retorna mas de un * campo *
    * sentencia ==> select t.c1,t.c2...t.c3 from com.test.Test as t
  4. *
  5. Array que contiene una entidades o campos cuando existe junturas. * sentencia ==> from com.test.Test a,from com.test.Testuno b where * a.pk=b.pk * and b.pk.lenguage = 'ES'
  6. *
* * @return */ public Object getObject() { return this.buildQuery().uniqueResult(); } /** * Retorna un entity dada la clave primaria. * * @param Tipo de la entidad, tomado del parametro clase * @param clase Clase de la entidad * @param key Clave primaria * * @return El objeto */ public T getObjectByKey(Class clase, Serializable key) { Object obj = this.lockOptions == null || this.lockOptions.equals(LockOptions.NONE) ? this.session.get(clase, key) : this.session.get(clase, key, this.lockOptions); if (!this.cacheable) { if (this.lockOptions == null || this.lockOptions.equals(LockOptions.NONE)) { if (obj != null) { this.session.refresh(obj); } } else { this.session.refresh(obj, this.lockOptions); } } return (T) obj; } /** * Retorna una lista de entidades o arreglos. * * @return */ public List getResults() { return this.buildQuery().list(); } /** * Retorna un resultset sobre el cual se puede iterar. * * @return */ public ScrollableResults getScroll() { Query q = this.buildQuery(); q.setReadOnly(true); return q.scroll(ScrollMode.FORWARD_ONLY); } /** * Retorna un resultset sobre el cual se puede iterar. * * @param pMode * Modo permitidos para la iteracion: FORWARD_ONLY, SCROLL_SENSITIVE, * SCROLL_INSENSITIVE * * @return */ public ScrollableResults getScroll(ScrollMode pMode) { return this.buildQuery().scroll(pMode); } /** * Fija un criterio BigDecimal a la sentencia. El nombre del parametro debe * ser igual al del where de la sentencia. * * @param pParameter * @param pBigdecimal */ public void setBigDecimal(String pParameter, BigDecimal pBigdecimal) { if (pBigdecimal == null) { this.map.put(pParameter, StandardBasicTypes.BIG_DECIMAL); } else { this.map.put(pParameter, pBigdecimal); } } /** * Fija un criterio Data a la sentencia. El nombre del parametro debe ser * igual al del where de la sentencia. * * @param pParameter * @param pDate */ public void setDate(String pParameter, Date pDate) { this.map.put(pParameter, pDate); } /** * Fija un criterio Integer a la sentencia. El nombre del parametro debe ser * igual al del where de la sentencia. * * @param pParameter * @param pInteger */ public void setInteger(String pParameter, Integer pInteger) { if (pInteger == null) { this.map.put(pParameter, StandardBasicTypes.INTEGER); } else { this.map.put(pParameter, pInteger); } } /** * Fija un criterio Integer a la sentencia. El nombre del parametro debe ser * igual al del where de la sentencia. * * @param pParameter * @param pLong */ public void setLong(String pParameter, Long pLong) { if (pLong == null) { this.map.put(pParameter, StandardBasicTypes.LONG); } else { this.map.put(pParameter, pLong); } } /** * Fija un criterio string de la sentencia. El nombre del parametro debe ser * igual al del where de la sentencia. * * @param pParameter * @param pString */ public void setString(String pParameter, String pString) { this.map.put(pParameter, pString); } /** * Fija un criterio Timestamp a la sentencia. El nombre del parametro debe * ser * igual al del where de la sentencia. * * @param pParameter * @param pTimestamp */ public void setTimestamp(String pParameter, Timestamp pTimestamp) { this.map.put(pParameter, pTimestamp); } /** * Setea valores de parametros definidos previamente en una sentencia. * * @param pMparamters * Map con el nombre del parametro y el valor del mismo. */ public void setParametersValue(Map pMparamters) { Iterator itr = pMparamters.keySet().iterator(); while (itr.hasNext()) { String key = itr.next(); Object value = pMparamters.get(key); if (value == null) { throw new FitbankException("GEN025", "NO SE HA ENVIADO VALOR PARA EL PARAMETRO {0}", key); } LOGGER.debug("parametro " + key + " valor " + value + " " + value.getClass()); if (value instanceof String) { this.setString(key, (String) value); } else if (value instanceof Integer) { this.setInteger(key, (Integer) value); } else if (value instanceof Long) { this.setLong(key, (Long) value); } else if (value instanceof BigDecimal) { this.setBigDecimal(key, (BigDecimal) value); } else if (value instanceof Timestamp) { this.setTimestamp(key, (Timestamp) value); } else if (value instanceof Date) { this.setDate(key, (Date) value); } } } private Query buildQuery() { if (this.sentence == null) { throw new FitbankException("HB005", "SENTENCIA INVALIDA"); } Query qry = this.session.createQuery(this.sentence); qry.setCacheable(this.cacheable); String[] param = qry.getNamedParameters(); for (String parameter : param) { Object obj = this.map.get(parameter); if (obj == null) { throw new FitbankException("HB006", "VALOR NO ENVIADO {0}", parameter); } else if (obj instanceof Type) { qry.setParameter(parameter, null, (Type) obj); LOGGER.debug("UtilHB.execute null " + parameter); } else { if (obj instanceof Date) { qry.setDate(parameter, (Date) obj); } else if (obj instanceof Timestamp) { qry.setTimestamp(parameter, (Timestamp) obj); } else { qry.setParameter(parameter, obj); } } } qry.setReadOnly(this.readonly); if (this.lockOptions != null && !this.lockOptions.equals(LockOptions.NONE) && StringUtils.isNotBlank(this.alias)) { qry.setLockMode(this.alias, this.lockOptions.getLockMode()); } if (this.flushMode != null) { qry.setFlushMode(this.flushMode); } if ((this.page != null) && (this.recordperpage != null) && (this.page > 0) && (this.recordperpage > 0)) { if (this.page > 1) { qry.setFirstResult((this.page - 1) * this.recordperpage); } qry.setMaxResults(this.recordperpage + 1); } return qry; } /** * Definir el tipo de flush a usar antes de ejecutar este HQL. * @param flushmode Tipo de Flush (MANUAL, COMMIT, etc). */ public void setFlushMode(FlushMode flushmode) { this.flushMode = flushmode; } /** * Obtener el tipo de flush, a usar antes de ejecutar este HQL. * @return Tipo de Flush (MANUAL, COMMIT, etc). */ public FlushMode getFlushMode() { return this.flushMode; } /** * Definir el tipo de bloqueo, segun un alias en el HQL. * @param lockOptions Tipo de Bloqueo (READ, UPGRADE, NONE, etc). * @param pAlias Alias de la referencia a usar en el bloqueo. */ public void setLockOptions(LockOptions lockOptions, String pAlias) { this.lockOptions = lockOptions; this.alias = pAlias; } /** * Obtener el tipo de bloqueo definido pare este HQL. * @return Tipo de Bloqueo definido en el HQL. */ public LockOptions getLockOptions() { return this.lockOptions; } }