nosi.base.ActiveRecord.BaseActiveRecord Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of igrp-core Show documentation
Show all versions of igrp-core Show documentation
IGRP Framework is a powerful and highly customizable platform developed by the Operational Nucleus for the Information Society (NOSi) to create web applications, it provides out of box, several modules to make easy to create stand-alone, production-grade web applications: authentication and access-control, business processes automation, reporting, page builder with automatic code generation and incorporation of the Once-Only-Principle, written in Java. IGRP Framework WAR - Contains some keys resources that give UI to IGRP Framework and others supports files.
package nosi.base.ActiveRecord;
import java.io.Serializable;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.persistence.Id;
import javax.persistence.NoResultException;
import javax.persistence.Transient;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import jakarta.xml.bind.annotation.XmlTransient;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.jpa.QueryHints;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.gson.annotations.Expose;
import nosi.core.webapp.Core;
import nosi.core.webapp.databse.helpers.Connection;
import nosi.core.webapp.databse.helpers.DatabaseMetadaHelper;
import nosi.core.webapp.databse.helpers.ORDERBY;
import nosi.core.webapp.databse.helpers.ParametersHelper;
import nosi.core.webapp.databse.helpers.DatabaseMetadaHelper.Column;
import nosi.core.webapp.helpers.StringHelper;
import static nosi.base.ActiveRecord.HibernateUtils.setSessionAudit;
/**
* @author: Emanuel Pereira
* 29 Jun 2017
*/
@SuppressWarnings("unchecked")
public abstract class BaseActiveRecord implements ActiveRecordIterface, Serializable {
private static final long serialVersionUID = -2681026559103646326L;
@Expose(serialize = false)
@JsonIgnore
protected String sql="";
@Expose(serialize = false) @JsonIgnore
protected String alias;
@Expose(serialize = false) @JsonIgnore
protected String connectionName;
@Expose(serialize = false) @JsonIgnore
private boolean whereIsCall = false;
@Expose(serialize = false) @JsonIgnore
private transient ResolveColumnNameQuery recq;
@Expose(serialize = false) @JsonIgnore
private int limit = -1;
@Expose(serialize = false) @JsonIgnore
private int offset = -1;
@Expose(serialize = false) @JsonIgnore
private transient List parametersMap;
@Expose(serialize = false) @JsonIgnore
private String schema = null;
@Expose(serialize = false) @JsonIgnore @JsonFormat(shape=JsonFormat.Shape.ARRAY)
private List error;
@Expose(serialize = false) @JsonIgnore
private boolean isReadOnly = false;
@Expose(serialize = false) @JsonIgnore
private transient CriteriaBuilder builder = null;
@Expose(serialize = false) @JsonIgnore
private transient CriteriaQuery criteria = null;
@Expose(serialize = false) @JsonIgnore
private transient Root root = null;
@Expose(serialize = false) @JsonIgnore
private String tableName;
@Expose(serialize = false) @JsonIgnore
private Class className;
@Expose(serialize = false) @JsonIgnore
private transient T classNameCriteria;
@Expose(serialize = false) @JsonIgnore
private boolean showError = true;
@Expose(serialize = false) @JsonIgnore
private boolean showTracing = true;
@Expose(serialize = false) @JsonIgnore
private String columnsSelect = "";
@Expose(serialize = false) @JsonIgnore
private boolean keepConnection = false;
@Expose(serialize = false) @JsonIgnore
private String applicationName;
private String distinctByColumn;
private boolean isDistinctBy=false;
private boolean isShowConsoleSql=false;
private static final String QUOTE = "'";
protected BaseActiveRecord() {
this.classNameCriteria = (T) this;
this.className = this.getClassType();
if(this.className!=null) {
this.setTableName(this.className.getSimpleName());
this.setAlias("obj_"+this.className.getSimpleName().toLowerCase());
}
this.recq = new ResolveColumnNameQuery(this.getClass());
this.error = new ArrayList<>();
}
@Override
public T where(String condition) {
if(!this.whereIsCall) {
this.sql += " WHERE "+condition;
this.whereIsCall = true;
}
return (T) this;
}
protected T filterWhere(String condition) {
this.sql += condition;
return (T) this;
}
@Override
public T where() {
return this.where("1=1");
}
@Override
public T and() {
if(!this.whereIsCall)
this.where();
this.sql += " AND ";
return (T) this;
}
@Override
public T or() {
if(!this.whereIsCall)
this.where();
this.sql += " OR ";
return (T) this;
}
@Override
public T where(String name, String operator, String value) {
return this.whereObject(name,name, operator, value,String.class);
}
@Override
public T where(String name, String operator, String[] values) {
if(values!=null) {
String[] valuesT = this.normalizeStringValues(values);
String value = this.applyToInCondition(valuesT);
this.where("");
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" "+value+" ");
}
return (T) this;
}
@Override
public T where(String name, String operator, Integer[] values) {
return this.whereObject(name, operator, values);
}
@Override
public T where(String name, String operator, Double[] values) {
return this.whereObject(name, operator, values);
}
@Override
public T where(String name, String operator, Float[] values) {
return this.whereObject(name, operator, values);
}
@Override
public T where(String name, String operator, Short[] values) {
return this.whereObject(name, operator, values);
}
@Override
public T where(String name, String operator, Short value) {
return this.whereObject(name,name, operator, value,Short.class);
}
@Override
public T where(String name, String operator, Integer value) {
return this.whereObject(name,name, operator, value,Integer.class);
}
@Override
public T where(String name, String operator, Float value) {
return this.whereObject(name,name, operator, value,Float.class);
}
@Override
public T where(String name, String operator, Double value) {
return this.whereObject(name,name, operator, value,Double.class);
}
@Override
public T where(String name, String paramName, String operator, Short value) {
return this.whereObject(name,paramName, operator, value,Short.class);
}
@Override
public T where(String name, String operator, Date value) {
return this.whereObject(name,name, operator, value,Date.class);
}
/**
* Compares if is not null the name string, then it adds IS NOT NULL to query
* if(Core.isNotNull(name))
* return ...name)+" IS NOT NULL "
*/
@Override
public T andWhereNotNull(String name) {
if(Core.isNotNull(name)) {
this.and();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" IS NOT NULL ");
}
return (T) this;
}
/**
* Depending in the operator, it call andWhereIsNull or andWhereNotNull
*
* @param name column name
* @param operator - can be "isnull" or "notnull"
* @return this instance
*/
public T andWhere(String name, String operator) {
if(Core.isNull(operator))
return (T) this;
if(operator.equalsIgnoreCase("isnull")){
return this.andWhereIsNull(name);
}else if( operator.equalsIgnoreCase("notnull")) {
return this.andWhereNotNull(name);
}
return (T) this;
}
/**
* Compares if is not null the name string, then it adds IS NULL to query
* if(Core.isNotNull(name))
* return ...name)+" IS NULL "
*/
@Override
public T andWhereIsNull(String name) {
if(Core.isNotNull(name)) {
this.and();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" IS NULL ");
}
return (T) this;
}
@Override
public T andWhere(String name, String operator, String value) {
return this.andWhereObject(name,name, operator, value, String.class);
}
@Override
public T andWhere(String name, String operator, Number value) {
return this.andWhereObject(name,name, operator, value, Number.class);
}
@Override
public T andWhere(String name, String operator, String[] values) {
if(values!=null) {
String value="('')";
if(values.length>0){
String[] valuesT = this.normalizeStringValues(values);
value = this.applyToInCondition(valuesT);
}
this.and();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" "+value+" ");
}
return (T) this;
}
/**
* Compares if is not null the name string, then it adds IS NOT NULL to query
* if(Core.isNotNull(name))
* return ...name)+" IS NOT NULL "
*/
@Override
public T orWhereNotNull(String name) {
if(Core.isNotNull(name)) {
this.or();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" IS NOT NULL ");
}
return (T) this;
}
/**
* Compares if is not null the name string, then it adds IS NULL to query
* if(Core.isNotNull(name))
* return ...name)+" IS NULL "
*/
@Override
public T orWhereIsNull(String name) {
if(Core.isNotNull(name)) {
this.or();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" IS NULL ");
}
return (T) this;
}
@Override
public T andWhere(String name, String operator, Integer[] values) {
return this.andWhereObject(name, operator, values);
}
@Override
public T andWhere(String name, String operator, Double[] values) {
return this.andWhereObject(name, operator, values);
}
@Override
public T andWhere(String name, String operator, Float[] values) {
return this.andWhereObject(name, operator, values);
}
@Override
public T andWhere(String name, String operator, Short[] values) {
return this.andWhereObject(name, operator, values);
}
@Override
public T andWhere(String name, String operator, Short value) {
return this.andWhereObject(name,name, operator, value, Short.class);
}
@Override
public T andWhere(String name, String paramName, String operator, Short value) {
return this.andWhereObject(name,paramName, operator, value, Short.class);
}
@Override
public T andWhere(String name, String operator, Integer value) {
return this.andWhereObject(name,name, operator, value, Integer.class);
}
@Override
public T andWhere(String name, String operator, Float value) {
return this.andWhereObject(name,name, operator, value, Float.class);
}
@Override
public T andWhere(String name, String operator, Double value) {
return this.andWhereObject(name,name, operator, value, Double.class);
}
@Override
public T andWhere(String name, String operator, Date value) {
return this.andWhereObject(name,name, operator, value, Date.class);
}
@Override
public T orWhere(String name, String operator, String value) {
return this.orWhereObject(name,name, operator, value, String.class);
}
@Override
public T orWhere(String name, String operator, Short value) {
return this.orWhereObject(name,name, operator, value, Short.class);
}
@Override
public T orWhere(String name, String paramName, String operator, Short value) {
return this.orWhereObject(name,paramName, operator, value, Short.class);
}
@Override
public T orWhere(String name, String operator, String[] values) {
return this.orWhereObject(name, operator, values);
}
@Override
public T orWhere(String name, String operator, Integer[] values) {
return this.orWhereObject(name, operator, values);
}
@Override
public T orWhere(String name, String operator, Double[] values) {
return this.orWhereObject(name, operator, values);
}
@Override
public T orWhere(String name, String operator, Float[] values) {
return this.orWhereObject(name, operator, values);
}
@Override
public T orWhere(String name, String operator, Short[] values) {
return this.orWhereObject(name, operator, values);
}
@Override
public T orWhere(String name, String paramName,String operator, Integer value) {
return this.orWhereObject(name,paramName, operator, value, Integer.class);
}
@Override
public T orWhere(String name, String operator, Integer value) {
return this.orWhereObject(name,name, operator, value, Integer.class);
}
@Override
public T orWhere(String name, String operator, Float value) {
return this.orWhereObject(name,name, operator, value, Float.class);
}
@Override
public T orWhere(String name, String operator, Double value) {
return this.orWhereObject(name,name, operator, value, Double.class);
}
@Override
public T orWhere(String name, String operator, Date value) {
return this.orWhereObject(name,name, operator, value, Date.class);
}
@Override
public T having(String name, String operator, String value) {
return this.havingObject(name, operator, value, String.class);
}
@Override
public T having(String name, String operator, Integer value) {
return this.havingObject(name, operator, value, Integer.class);
}
@Override
public T having(String name, String operator, Double value) {
return this.havingObject(name, operator, value, Double.class);
}
@Override
public T having(String name, String operator, Float value) {
return this.havingObject(name, operator, value, Float.class);
}
@Override
public T having(String name, String operator, Short value) {
return this.havingObject(name, operator, value, Short.class);
}
@Override
public T having(String name, String operator, Date value) {
return this.havingObject(name, operator, value, Date.class);
}
@Override
public T where(RestrictionImpl restriction) {
this.parametersMap.addAll(restriction.getParametersMap());
this.sql+=" WHERE ("+restriction.getRestriction()+")";
return (T) this;
}
@Override
public T andWhere(RestrictionImpl restriction) {
this.parametersMap.addAll(restriction.getParametersMap());
this.sql+=" AND ("+restriction.getRestriction()+")";
return (T) this;
}
@Override
public T orWhere(RestrictionImpl restriction) {
this.parametersMap.addAll(restriction.getParametersMap());
this.sql+=" OR ("+restriction.getRestriction()+")";
return (T) this;
}
@Transient
@XmlTransient
public String getSql() {
return sql;
}
public void setSql(String sql) {
this.sql = sql;
}
@Transient
protected String getAlias() {
return alias;
}
protected void setAlias(String alias) {
this.alias = alias;
}
@Transient
protected String generateSql() {
return " SELECT "+(Core.isNull(this.columnsSelect)?(" "+this.getAlias()):this.columnsSelect)+" FROM "+this.getTableName()+" "+this.getAlias()+" ";
}
@Transient
protected String generateSqlCount() {
return " SELECT count("+this.getAlias()+") FROM "+this.getTableName()+" "+this.getAlias()+" ";
}
@Transient
protected String generateSqlCountDistinctBy() {
return " SELECT count("+this.distinctByColumn+") FROM "+this.getTableName()+" "+this.getAlias()+" "+this.sql;
}
@Transient
protected String generateSqlAggregate(String columnName, String aggregate) {
return " SELECT "+ aggregate +"("+recq.resolveColumnName(this.getAlias(),columnName)+") FROM " + this.getTableName() + " " + this.getAlias() + " ";
}
@Transient
protected Class getClassType(){
ParameterizedType genericType = (ParameterizedType) this.getClass().getGenericSuperclass();
return (Class) genericType.getActualTypeArguments()[0];
}
@Transient
protected String getTableName() {
return this.tableName;
}
protected void setTableName(String tableName) {
this.tableName = tableName;
}
private void addParameter(String name, String paramName, Object value, Class> classType) {
Column c = new Column();
c.setColumnMap(paramName);
c.setName(name);
c.setDefaultValue(value);
c.setType(classType);
this.parametersMap.add(c);
}
private String[] normalizeStringValues(String[] values) {
for (int i = 0; i < values.length; i++) {
values[i] = QUOTE + values[i] +QUOTE;
}
return values;
}
private String applyToInCondition(Object[] values) {
return String.join(",", Arrays.toString(values)).replace("[", "(").replace("]", ")");
}
private T whereObject(String name, String operator, Object[] values) {
if(values!=null) {
this.where("");
String value = this.applyToInCondition(values);
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" "+value+" ");
}
return (T) this;
}
private T whereObject(String name, String paramName, String operator, Object value, Class> classType) {
if (Core.isNotNull(value)) {
this.where("");
String paramName_ = recq.removeAlias(paramName);
if (operator.equalsIgnoreCase("like") || StringHelper.removeSpace(operator).equalsIgnoreCase("notlike")) {
this.filterWhere("UPPER(" + recq.resolveColumnName(this.getAlias(), name) + ") " + operator + " :" + paramName_ + " ");
this.addParameter(name, paramName_, value.toString().toUpperCase(), classType);
} else {
this.filterWhere(recq.resolveColumnName(this.getAlias(), name) + " " + operator + ":" + paramName_ + " ");
this.addParameter(name, paramName_, value, classType);
}
}
return (T) this;
}
private T andWhereObject(String name, String operator, Object[] values) {
if(values!=null) {
String value = this.applyToInCondition(values);
this.and();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" "+value+" ");
}
return (T) this;
}
private T andWhereObject(String name,String paramName,String operator,Object value,Class> classType) {
if(Core.isNotNull(value)) {
String paramName_ = recq.removeAlias(paramName);
this.and();
if(operator.equalsIgnoreCase("like") || StringHelper.removeSpace(operator).equalsIgnoreCase("notlike")) {
this.filterWhere("UPPER("+recq.resolveColumnName(this.getAlias(),name)+") "+operator+" :"+paramName_+" ");
this.addParameter(name,paramName_,value.toString().toUpperCase(),classType);
}else {
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" :"+paramName_+" ");
this.addParameter(name,paramName_,value,classType);
}
}
return (T) this;
}
private T orWhereObject(String name,String paramName,String operator,Object value,Class> classType) {
if(Core.isNotNull(value)) {
String paramName_ = recq.removeAlias(paramName);
this.or();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+":"+paramName_+" ");
this.addParameter(name,paramName_,value,classType);
}
return (T) this;
}
private T orWhereObject(String name, String operator, Object[] values) {
if(values!=null) {
String value = this.applyToInCondition(values);
this.or();
this.filterWhere(recq.resolveColumnName(this.getAlias(),name)+" "+operator+" "+value+" ");
}
return (T) this;
}
private T havingObject(String name,String operator,Object value,Class> classType) {
if(Core.isNotNull(value)) {
this.filterWhere(" HAVING "+recq.resolveColumnName(this.getAlias(),name)+" "+operator+":"+recq.removeAlias(name)+" ");
this.addParameter(name,recq.removeAlias(name), value,classType);
}
return (T) this;
}
@Override
public T setConnectionName(String connectionName) {
this.connectionName = connectionName;
return (T) this;
}
@Transient
@XmlTransient
@Override
public String getConnectionName() {
if(Core.isNotNullOrZero(getApplicationName()) && Core.isNull(this.connectionName)) {
this.connectionName=this.defaultConnection(getApplicationName());
return this.connectionName;
}
return Core.isNotNull(this.connectionName) ? this.connectionName:this.defaultConnection();
}
@Transient
@XmlTransient
public String getApplicationName() {
return this.applicationName;
}
protected void setParameters(TypedQuery query) {
if(this.parametersMap!=null && !this.parametersMap.isEmpty()) {
this.parametersMap.forEach(col->ParametersHelper.setParameter(query, col.getDefaultValue(), col));
}
}
@Override
public T find() {
this.whereIsCall = false;
this.sql = "";
this.parametersMap = new ArrayList<>();
this.error = new ArrayList<>();
return (T) this;
}
@Transient
protected String getPrimaryKey() {
Field[] fields = this.className.getDeclaredFields();
for(Field field:fields) {
if(field.isAnnotationPresent(Id.class)) {
return field.getName();
}
}
return null;
}
@Override
public T where(String name, String paramName, String operator, String value) {
return this.whereObject(name, paramName, operator, value,String.class);
}
@Override
public T where(String name, String paramName, String operator, Integer value) {
return this.whereObject(name, paramName, operator, value,Integer.class);
}
@Override
public T where(String name, String paramName, String operator, Float value) {
return this.whereObject(name, paramName, operator, value,Float.class);
}
@Override
public T where(String name, String paramName, String operator, Double value) {
return this.whereObject(name, paramName, operator, value,Double.class);
}
@Override
public T where(String name, String paramName, String operator, Date value) {
return this.whereObject(name, paramName, operator, value,Date.class);
}
/**This andWhere has paramName to change if not equal to the column name
* @param paramName - use it when you have a method like "lower(" . The variable cannot have "("
* {@code dao.find().andWhere("lower(dominio)","dominio", "=", domainsName.toLowerCase())
* .andWhere("lower(valor)","valor", "=", key.toLowerCase()).one();
}
*/
@Override
public T andWhere(String name, String paramName, String operator, String value) {
return this.andWhereObject(name, paramName, operator, value,String.class);
}
@Override
public T andWhere(String name, String paramName, String operator, Integer value) {
return this.andWhereObject(name, paramName, operator, value,Integer.class);
}
@Override
public T andWhere(String name, String paramName, String operator, Float value) {
return this.andWhereObject(name, paramName, operator, value,Float.class);
}
@Override
public T andWhere(String name, String paramName, String operator, Double value) {
return this.andWhereObject(name, paramName, operator, value,Double.class);
}
@Override
public T andWhere(String name, String paramName, String operator, Date value) {
return this.andWhereObject(name, paramName, operator, value,Date.class);
}
@Override
public T orWhere(String name, String paramName, String operator, String value) {
return this.orWhereObject(name, paramName, operator, value,String.class);
}
@Override
public T orWhere(String name, String paramName, String operator, Float value) {
return this.orWhereObject(name, paramName, operator, value,Float.class);
}
@Override
public T orWhere(String name, String paramName, String operator, Double value) {
return this.orWhereObject(name, paramName, operator, value,Double.class);
}
@Override
public T orWhere(String name, String paramName, String operator, Date value) {
return this.orWhereObject(name, paramName, operator, value,Date.class);
}
public RestrictionImpl restriction() {
return new RestrictionImpl(this.getClass(),this.getAlias());
}
@Override
public T orderBy(String... orderByNames) {
return this.orderBy(new String[][] {orderByNames});
}
@Override
public T orderBy(String[]... orderByNames) {
return this.orderBy(orderByNames,null);
}
private T orderBy(String[][] orderByNames, String defaultOrder) {
if(orderByNames!=null) {
StringBuilder c = new StringBuilder(" ORDER BY ");
int i=1;
for(String[] names:orderByNames) {
String order = names[names.length-1];
String[] newNames;
if(!order.equalsIgnoreCase(ORDERBY.ASC) && !order.equalsIgnoreCase(ORDERBY.DESC)) {
order = Core.isNotNull(defaultOrder)?defaultOrder:ORDERBY.ASC;
newNames = Arrays.copyOf(names, names.length);
}else{
newNames = Arrays.copyOf(names, names.length-1>=1?names.length-1:names.length);
}
for(int j=0;j findAll(CriteriaQuery criteria) {
List list = null;
Session s = this.getSession();
try {
if(!s.getTransaction().isActive()) {
s.beginTransaction();
}
TypedQuery query = s.createQuery(criteria);
if(!this.keepConnection)
query.setHint(QueryHints.HINT_READONLY, true);
this.setParameters(query);
list = query.getResultList();
}catch (Exception e) {
this.keepConnection = false;
this.setError(e);
} finally {
this.closeSession(s);
}
return list;
}
@Override
public T findOne(CriteriaQuery criteria) {
T t = null;
Session s = this.getSession();
try {
if(!s.getTransaction().isActive()) {
s.beginTransaction();
}
TypedQuery query = s.createQuery(criteria);
query.setMaxResults(1);
if(!this.keepConnection)
query.setHint(QueryHints.HINT_READONLY, true);
this.setParameters(query);
t = query.getSingleResult();
}catch (Exception e) {
if(!(e instanceof NoResultException)) {
this.keepConnection = false;
this.setError(e);
}
} finally {
this.closeSession(s);
}
return t;
}
@Override
public T findOne(Object value) {
if(value!=null) {
this.find();
final var primaryKey = this.getPrimaryKey();
this.whereObject(primaryKey, primaryKey, "=",value,Object.class);
return this.one();
}
return null;
}
@Override
public T one() {
this.limit = 1;
List list = this.all();
return (list!=null && !list.isEmpty())?list.get(0):null;
}
@Override
public List findAll() {
this.find();
return this.all();
}
@Override
public List all() {
this.sql = this.generateSql()+this.sql;
List list = null;
Session s = this.getSession();
try {
if(!s.getTransaction().isActive()) {
s.beginTransaction();
}
if(this.isShowConsoleSql) {
Core.log(this.getSql());
System.out.println(this.getSql());
}
TypedQuery query = s.createQuery(this.getSql(), this.className);
if(this.offset > -1) {
query.setFirstResult(offset);
}
if(this.limit > -1) {
query.setMaxResults(limit);
}
if(!this.keepConnection)
query.setHint(QueryHints.HINT_READONLY, true);
this.setParameters(query);
list = query.getResultList();
}catch (Exception e) {
this.keepConnection = false;
this.setError(e);
} finally {
this.closeSession(s);
}
return list;
}
public List