
org.javabeanstack.data.DataNativeQuery Maven / Gradle / Ivy
The newest version!
/*
* JavaBeanStack FrameWork
*
* Copyright (C) 2017 Jorge Enciso
* Email: [email protected]
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.javabeanstack.data;
import org.javabeanstack.data.model.DataQueryModel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.javabeanstack.error.ErrorManager;
import org.javabeanstack.exceptions.SessionError;
import org.javabeanstack.security.model.IUserSession;
import org.javabeanstack.util.Fn;
import org.javabeanstack.util.Strings;
import static org.javabeanstack.util.Fn.iif;
import org.javabeanstack.util.LocalDates;
import static org.javabeanstack.util.Strings.occurs;
import static org.javabeanstack.util.Strings.isNullorEmpty;
/**
* Esta clase abstrae funcionalidades que permiten ejecutar sentencias nativas
* sobre la base de datos.
*
* @author Jorge Enciso
*/
public class DataNativeQuery implements IDataNativeQuery {
private static final Logger LOGGER = Logger.getLogger(DataNativeQuery.class);
private boolean queryCreated;
private String querySentence;
private String columnExpr;
private String[] columnList;
private String entityExpr;
private String fromEntity;
private String[] entityList;
private String filterExpr;
private String[] filterExprList;
private String orderExpr;
private String[] orderList;
private String groupExpr;
private String[] groupList;
private String filterGroupExpr;
private String[] filterGroupList;
private final LinkedList joinParams = new LinkedList();
private Map queryParams = new HashMap<>();
private IDataLink dataLink;
private final Map queryConstants = new HashMap<>();
private int first;
private int maxResult;
private IDataNativeQuery subQueryFrom;
private String subQueryFromSentence;
private String subQueryAlias;
private boolean applyDBQueryFilter = true;
/**
* Asigna la lista de columnas
*
* @param columns Son las columnas de la sentencia select
* @return objeto dataNativeQuery con la asignación de las columnas
*/
@Override
public IDataNativeQuery select(String columns) {
columnExpr = columns;
queryCreated = false;
columnList = null;
columnList = setColumnLabel(columnExpr);
return this;
}
/**
* Asigna la/s entidad/es desde donde se extraeran la información.
*
* @param entities es la lista de entidades (tablas o vistas) forman parte
* de from, inner join
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery from(String entities) {
entityExpr = entities;
fromEntity = entities;
subQueryAlias = null;
subQueryFrom = null;
entityList = null;
queryCreated = false;
joinParams.clear();
filterExpr = null;
filterExprList = null;
orderExpr = null;
orderList = null;
groupExpr = null;
groupList = null;
filterGroupExpr = null;
filterGroupList = null;
return this;
}
/**
* Asigna la/s entidad/es desde donde se extraeran la información.
*
* @param query objeto IDataNativeQuery cuya sentencia es utilizada como
* subquery dentro de la clausula FROM.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery from(IDataNativeQuery query, String alias) {
subQueryAlias = alias;
subQueryFrom = query;
entityExpr = "";
entityList = null;
fromEntity = null;
joinParams.clear();
queryCreated = false;
return this;
}
/**
* Asigna la/s entidad/es desde donde se extraeran la información.
*
* @param query objeto IDataNativeQuery cuya sentencia es utilizada como
* subquery dentro de la clausula FROM.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery from(String query, String alias) {
subQueryAlias = alias;
subQueryFromSentence = query;
entityExpr = "";
entityList = null;
fromEntity = null;
joinParams.clear();
queryCreated = false;
return this;
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param entity es la lista de entidad (tabla o vista)
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery join(String entity, String joinExpr) {
joinParams.add(new JoinParam(entity, joinExpr, "INNER JOIN"));
queryCreated = false;
return this;
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery join(IDataNativeQuery subquery, String alias, String joinExpr) {
joinParams.add(new JoinParam(subquery, alias, joinExpr, "INNER JOIN"));
queryCreated = false;
return this;
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param entity es la lista de entidad (tabla o vista)
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery innerJoin(String entity, String joinExpr) {
return join(entity, joinExpr);
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery innerJoin(IDataNativeQuery subquery, String alias, String joinExpr) {
return join(subquery, alias, joinExpr);
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param entity entidad (tabla o vista)
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery leftJoin(String entity, String joinExpr) {
joinParams.add(new JoinParam(entity, joinExpr, "LEFT OUTER JOIN"));
queryCreated = false;
return this;
}
/**
* Asigna la/s entidad/es que formarán parte del join
*
* @param joinExpr la expresión del join.
* @return objeto dataNativeQuery con la asignación de las entidades
*/
@Override
public IDataNativeQuery leftJoin(IDataNativeQuery subquery, String alias, String joinExpr) {
joinParams.add(new JoinParam(subquery, alias, joinExpr, "LEFT OUTER JOIN"));
queryCreated = false;
return this;
}
/**
* Asigna los filtros en la expresión where.
*
* @param filterExpr son los filtros
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery where(String filterExpr) {
this.filterExpr = filterExpr;
this.filterExpr += getDBFilterExpr();
this.filterExprList = null;
queryCreated = false;
return this;
}
/**
* Asigna los filtros en la expresión where.
*
* @param filterExpr son los filtros
* @param params son los parametros del query
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery where(String filterExpr, Map params) {
this.filterExpr = filterExpr;
this.filterExpr += getDBFilterExpr();
this.filterExprList = null;
queryCreated = false;
addParams(params);
return this;
}
/**
* Asigna los filtros en la expresión where.
*
* @param dataExpr son los filtros
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery where(IDataExpression dataExpr) {
this.filterExpr = dataExpr.getSentence();
this.filterExpr += getDBFilterExpr();
this.filterExprList = null;
queryCreated = false;
if (!dataExpr.getSentenceParams().isEmpty()) {
addParams(dataExpr.getSentenceParams());
}
return this;
}
/**
* Asigna los filtros en la expresión where.
*
* @param dataExpr son los filtros
* @param params son los parametros del query
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery where(IDataExpression dataExpr, Map params) {
this.filterExpr = dataExpr.getSentence();
this.filterExpr += getDBFilterExpr();
this.filterExprList = null;
queryCreated = false;
addParams(params);
return this;
}
private String getDBFilterExpr(){
String result="";
if (getApplyDBFilter()
&& this.getDataLink() != null
&& (this.getDataLink().getUserSession() != null || !isNullorEmpty(this.getDataLink().getToken()))
&& !this.getDataLink().getPersistUnit().equals(IDBManager.CATALOGO)){
String operador = isNullorEmpty(filterExpr) ? "" : " and ";
try {
String entityExp = getEntityList()[0];
int pos = entityExp.indexOf(' ') > 0 ? entityExp.indexOf(' ') : entityExp.length();
String entity = entityExp.substring(0,pos);
String entityAlias = Strings.substr(entityExp, pos+1);
IDBFilter dbFilter = getDataLink().getDBLinkInfo().getDBFilter();
Class clazz = getClassModel(dbFilter.getModelPackagePath(), entity);
if (clazz != null){
String alias = entityAlias;
if (isNullorEmpty(alias)){
alias = entity;
}
String filter = dbFilter.getFilterExpr(clazz, alias.trim());
if (!isNullorEmpty(filter)){
result = operador + filter;
}
}
}
catch (Exception exp){
result = "";
}
}
return result;
}
/**
* Devuelve la clase del entity solicitado
* @param packagePath camino de busqueda de paquetes (lista de paquetes separado por ;)
* @param entity entidad
* @return la clase del entity solicitado
*/
public static Class getClassModel(String packagePath, String entity){
String className = "";
String[] partes = entity.split("_");
for (String parte : partes) {
className += Strings.capitalize(parte).trim();
}
if (packagePath == null){
return null;
}
String[] path = packagePath.split(";");
Class clazz=null;
for (String packages : path) {
String classPath = packages.trim() + "." + className;
try{
clazz = Class.forName(classPath);
break;
}
catch (ClassNotFoundException ex){
//continua con la busqueda
}
}
return clazz;
}
/**
* Asigna la expresión order by
*
* @param columnOrder lista de columnas por la que se va a ordenar el select
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery orderBy(String columnOrder) {
orderExpr = columnOrder;
queryCreated = false;
orderList = setColumnLabel(orderExpr);
return this;
}
/**
* Asigna la expresión group by
*
* @param columnGroup lista de columnas group by
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery groupBy(String columnGroup) {
groupExpr = columnGroup;
groupList = setColumnLabel(groupExpr);
queryCreated = false;
return this;
}
/**
* Asigna la expresión having
*
* @param filterExpr filtros having
* @return objeto dataNativeQuery con la asignación de la expresión
*/
@Override
public IDataNativeQuery having(String filterExpr) {
filterGroupExpr = filterExpr;
queryCreated = false;
return this;
}
/**
* Agrega valores a los parámetros de la sentencia
*
* @param key nombre del parámetro
* @param value valor del parámetro
* @return objeto dataNativeQuery con la asignación de los parámetros
*/
@Override
public IDataNativeQuery addParam(String key, Object value) {
queryParams.put(key, value);
return this;
}
/**
* Asigna los parámetros de la sentencia
*
* @param params Map conteniendo los parámetros
* @return objeto dataNativeQuery con la asignación de los parámetros
*/
@Override
public IDataNativeQuery addParams(Map params) {
setQueryParams(params);
return this;
}
/**
* Asigna los parámetros de la sentencia
*
* @param params Map conteniendo los parámetros
* @return objeto dataNativeQuery con la asignación de los parámetros
*/
@Override
public IDataNativeQuery setQueryParams(Map params) {
queryParams = params;
return this;
}
/**
* Crear la sentencia select a partir de todas los parámetros previos
* recibidos
*/
@Override
public void createQuery() {
querySentence = "SELECT " + columnExpr + " \r\n";
String fromExpr = getFromExpr();
querySentence += " FROM " + fromExpr + "\r\n";
if (Strings.isNullorEmpty(filterExpr)){
filterExpr = getDBFilterExpr();
}
if (!Strings.isNullorEmpty(filterExpr)) {
querySentence += " WHERE " + filterExpr + " \r\n";
}
if (!Strings.isNullorEmpty(groupExpr)) {
querySentence += " GROUP BY " + groupExpr + " \r\n";
}
if (!Strings.isNullorEmpty(filterGroupExpr)) {
querySentence += " HAVING " + filterGroupExpr + " \r\n";
}
if (!Strings.isNullorEmpty(orderExpr)) {
querySentence += " ORDER BY " + orderExpr + " \r\n";
}
setQueryConstants();
querySentence = Strings.textMerge(querySentence, queryConstants);
setDefaultParams();
queryCreated = true;
}
/**
* Devuelve la expresión from
* @return expresión from
*/
@Override
public final String getFromExpr() {
String fromExpr = "";
// Generar from desde un subquery
if (subQueryFrom != null) {
subQueryFrom.createQuery();
String subQuerySentence = subQueryFrom.getQuerySentence();
fromExpr = "("+subQuerySentence+") "+subQueryAlias+ " ";
fromExpr += getJoinExpr();
return fromExpr;
}
// Generar from desde una sentencia subquery
if (!isNullorEmpty(subQueryFromSentence)) {
String subQuerySentence = subQueryFromSentence;
fromExpr = "("+subQuerySentence+") "+subQueryAlias+ " ";
fromExpr += getJoinExpr();
return fromExpr;
}
String schema = dataLink.getDao().getSchema(dataLink.getPersistUnit());
String joinEntityExpr = getJoinEntityExpr();
entityExpr = fromEntity + iif(joinEntityExpr.isEmpty(), "", ", ");
// Si no existe los parámetros de joins y la lista de entidades es mayor a 1,
// generar la expresión de joins en forma automática.
if (joinParams.isEmpty() && getEntityList().length > 1) {
try {
fromExpr = dataLink.getEntitiesRelation(entityExpr, "", schema);
} catch (Exception exp) {
ErrorManager.showError(exp, LOGGER);
}
} // Si existe los parámetros de join crear la expresión a partir de sus parámetros.
else if (!joinParams.isEmpty()) {
fromExpr = getEntityWithSchema(this.fromEntity);
fromExpr += getJoinExpr();
} else {
fromExpr = getEntityWithSchema(this.fromEntity);
}
return fromExpr;
}
/**
* Devuelve la expresión join
* @return expresión join
*/
protected final String getJoinExpr(){
String result="";
String entity;
for (JoinParam param : joinParams) {
if (param.joinSubquery != null){
param.joinSubquery.createQuery();
result += " \r\n" + param.joinType
+ " (" + param.joinSubquery.getQuerySentence() + ") "
+ param.joinSubqueryAlias
+ " on " + param.joinExpr;
}
else{
entity = getEntityWithSchema(param.joinEntity);
result += " \r\n" + param.joinType + " " + entity + " on " + param.joinExpr;
}
}
return result;
}
/**
* Devuelve la entidad con el prefijo del schema de la base
* @param entity nombre de la entidad
* @return la entidad con el prefijo del schema de la base
*/
protected final String getEntityWithSchema(String entity) {
if (occurs(".", entity) == 0) {
entity = "{schema}." + entity;
}
return entity;
}
/**
* Crear la sentencia select a partir de todas los parámetros previos
* recibidos
*/
@Override
public String createQuerySentence() {
if (queryCreated) {
return querySentence;
}
this.createQuery();
return querySentence;
}
/**
* Agrega valores de parametros constantes (ej. :true=true, :false=false
* etc, :idempresa)
*/
protected void setDefaultParams() {
if (queryParams == null){
queryParams = new HashMap();
}
if (Strings.findString(":true", querySentence.toLowerCase()) >= 0) {
queryParams.put("true", true);
}
if (Strings.findString(":false", querySentence.toLowerCase()) >= 0) {
queryParams.put("false", false);
}
if (!queryParams.containsKey("idempresa")) {
if (Strings.findString(":idempresa", querySentence.toLowerCase()) >= 0) {
if (getDataLink().getUserSession() != null || !isNullorEmpty(getDataLink().getToken())) {
queryParams.put("idempresa", getDataLink().getIdCompany());
}
}
}
if (!queryParams.containsKey("idcompany")) {
if (Strings.findString(":idcompany", querySentence.toLowerCase()) >= 0) {
if (getDataLink().getUserSession() != null || !isNullorEmpty(getDataLink().getToken())) {
queryParams.put("idcompany", getDataLink().getIdCompany());
}
}
}
if (!queryParams.containsKey("today")) {
if (Strings.findString(":today", querySentence.toLowerCase()) >= 0) {
queryParams.put("today", LocalDates.today());
}
}
if (!queryParams.containsKey("now")) {
if (Strings.findString(":now", querySentence.toLowerCase()) >= 0) {
queryParams.put("now", LocalDates.now());
}
}
}
/**
* Asigna valores constantes a ciertos parámetros que serán reemplazadas al
* crear la sentencia.
*/
private void setQueryConstants() {
String schema = (String) dataLink.getPersistUnitProp().get("hibernate.default_schema");
queryConstants.put("schema", schema);
String schemaCat = (String) dataLink.getDao().getPersistUnitProp(IDBManager.CATALOGO).get("hibernate.default_schema");
queryConstants.put("schemacatalog", schemaCat);
//TODO revisar sgte. linea ver buscar en hibernate.dialect
String motordatos = (String) dataLink.getPersistUnitProp().get("jbs.dbengine");
if ("POSTGRES".equals(motordatos)) {
queryConstants.put("true", "true");
queryConstants.put("false", "false");
} else {
queryConstants.put("true", "1");
queryConstants.put("false", "0");
}
// Asignar las constantes de fecha y hora
if (Fn.inList(motordatos, "SQLSERVER", "Microsoft SQL Server", "SYBASE")) {
queryConstants.put("now", "getdate()");
queryConstants.put("today", "CONVERT(date, GETDATE())");
} else if (Fn.inList(motordatos, "ORACLE", "ORACLE8")) {
queryConstants.put("now", "sysdate");
queryConstants.put("today", "TRUNC(sysdate)");
} else if ("POSTGRES".equals(motordatos)) {
queryConstants.put("now", "now()");
queryConstants.put("today", "date_trunc('day', now())");
} else if ("DB2".equals(motordatos)) {
queryConstants.put("now", "CURRENT_TIMESTAMP");
queryConstants.put("today", "CURRENT DATE");
}
}
/**
* Ejecuta la sentencia y devuelve una lista de registros
*
* @return devuelve una lista de registros
* @throws org.javabeanstack.exceptions.SessionError
*/
@Override
public List execQuery() throws SessionError {
return execQuery(this.dataLink);
}
/**
* Ejecuta la sentencia y devuelve una lista de registros
*
* @param first
* @param maxResult
* @return devuelve una lista de registros
* @throws org.javabeanstack.exceptions.SessionError
*/
@Override
public List execQuery(int first, int maxResult) throws SessionError {
this.first = first;
this.maxResult = maxResult;
return execQuery(this.dataLink);
}
/**
* Ejecuta la sentencia y devuelve un registro
*
* @return devuelve un registro
* @throws org.javabeanstack.exceptions.SessionError
*/
@Override
public IDataQueryModel execQuerySingle() throws SessionError {
this.first = 0;
this.maxResult = 1;
List result = execQuery(this.dataLink);
if (result == null || result.isEmpty()){
return new DataQueryModel();
}
if (result.get(0) == null){
return new DataQueryModel();
}
return result.get(0);
}
/**
* Ejecuta la sentencia y devuelve una lista de registros
*
* @param dataLink objeto acceso a los datos.
* @return devuelve una lista de registros
* @throws org.javabeanstack.exceptions.SessionError
*/
@Override
public List execQuery(IDataLink dataLink) throws SessionError {
List result = new ArrayList<>();
try {
if (!queryCreated) {
createQuery();
}
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy