consulta de criterios de hibernación - propiedad de subpropiedad

Estoy usando Spring MVC 3.0 con el complemento jqgrid. Estoy creando la función de búsqueda para jqgrid que envía un objeto json al lado del servidor. Creé una clase java ficticia para analizar el json para el jqgrid cada vez que se activa la búsqueda. Todo está bien hasta este punto.

Estoy creando dinámicamente mi consulta de criterios, ya que el usuario es libre de elegir los criterios de búsqueda (igual, no igual, etc.). Aquí hay un ejemplo de la cadena json enviada por jqgrid.

{
    "groupOp": "AND",
    "rules": [{
        "field": "company",
        "op": "cn",
        "data": "School"},
    {
        "field": "numberOfStudents",
        "op": "eq",
        "data": "2"}]
}​

Esta es la clase de Java utilizada como plantilla para analizar este JSON:

public class JsonJqgridSearchModel {

    public String groupOp;

    public ArrayList<JqgridSearchCriteria> rules;
}

Observe el tipo llamado JqgridSearchCriteria. Esta es una clase que simplemente devuelve una restricción cada vez que llamo a su getRestriction() método. Aquí está el JqgridSearchCriteria clase:

public class JqgridSearchCriteria {

    public String field;

    public String op;

    public String data;

    public SimpleExpression getRestriction(){
        if(op.equals("cn")){
            return Restrictions.like(field, data, MatchMode.ANYWHERE);
        }else if(op.equals("eq")){
            return Restrictions.eq(field, data);
        }else if(op.equals("ne")){
            return Restrictions.ne(field, data);
        }else if(op.equals("lt")){
            return Restrictions.lt(field, data);
        }else if(op.equals("le")){
            return Restrictions.le(field, data);
        }else if(op.equals("gt")){
            return Restrictions.gt(field, data);
        }else if(op.equals("ge")){
            return Restrictions.ge(field, data);
        }else{
            return null;
        }       
    }   
}

Si observa la cadena JSON, verá por qué el campo and datos se utilizan para devolver SimpleExpression a través de getRestriction().

Aquí está la cosa: tengo Objeto-A que tiene Objeto-B como una referencia. Lo que obtengo de la red es Objeto-B.getName() así hay un JqgridSearchCriteria donde el campo=Objeto-B.getName() y el dato es el nombre proporcionado por el usuario. Cuando esto se ejecuta, obtengo una excepción de la siguiente manera:

Internal Error
Sorry, we encountered an internal error.
Details
could not get a field value by reflection getter of tt.edu.sbcs.model.Organization.id
org.hibernate.property.DirectPropertyAccessor$DirectGetter.get(DirectPropertyAccessor.java:62)
org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:230)
org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3852)
org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:3560)
org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:204)
org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243)
org.hibernate.type.EntityType.getIdentifier(EntityType.java:449)
org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:142)
org.hibernate.loader.Loader.bindPositionalParameters(Loader.java:1789)
org.hibernate.loader.Loader.bindParameterValues(Loader.java:1760)
                               .
                               .
                               .**

Aquí hay un fragmento de donde todo se junta.

Criteria criteria = session.createCriteria(CorporateRegistration.class); 
Iterator<JqgridSearchCriteria> iterator = jsonJqgridSearchModel.rules.iterator();
String operation = jsonJqgridSearchModel.groupOp;
if(operation.equals("AND")){
    Conjunction conjunction = Restrictions.conjunction();
    while(iterator.hasNext()){  
        conjunction.add(iterator.next().getRestriction());
    }           
    criteria.add(conjunction);
}//conjunctions are for AND operation
else{
    Disjunction disjunction = Restrictions.disjunction();
    while(iterator.hasNext()){  
        disjunction.add(iterator.next().getRestriction());
    }           
    criteria.add(disjunction);          
}//disjunctions are for OR operations       
    for(Object o: criteria.list()){
        corpRegList.add((CorporateRegistration)o);
    }

También intenté buscar números, pero el valor que aparece es una cadena. ¿Utilizo el createAlias ​​de los criterios? ¿Puedo especificar el tipo de datos de la propiedad llamada datos cuando devuelvo SimpleExpression?

preguntado el 12 de junio de 12 a las 19:06

2 Respuestas

Con respecto a la búsqueda de números, creo que necesitará una propiedad de "tipo" en su clase JqgridSearchCriteria. También en la interfaz de usuario, probablemente querrá adaptar los operadores disponibles para que el usuario no pueda seleccionar "Contiene" para valores numéricos, por ejemplo.

En un sistema similar que acabamos de desarrollar, usamos ['cadena', 'número', 'fecha'] para los tipos de valores de búsqueda. Cada columna que el usuario puede seleccionar para buscar tiene un tipo, por lo que podemos usar javascript para presentar una lista adecuada de operadores.

Esto significará que sabrá emitir correctamente el valor de los criterios de búsqueda al construir los Criterios. Agrega complejidad a su aplicación, pero no veo ninguna alternativa.

Respondido el 13 de junio de 12 a las 15:06

Para aquellos que pueden estar buscando la respuesta, utilicé un subcriterio. Eso es si tienes un criterio llamado A, para este tipo de situaciones se puede decir A.createCriteria(field).add(conjunction); donde el campo se refiere a la propiedad real en la entidad propietaria. Aquí hay algo que creé para permitir una lógica de búsqueda más genérica que es específica del proyecto. Así que cuando llames A.list() tú eres bueno para irte. Es un poco largo pero bastante simple de entender.

public class JqgridSearchCriteria {

    public String field;

    public String op;

    public String data;

    public String dataType;

    public String dataProperty;

    public SimpleExpression getSimpleExpression(String myField, Object o){
        if(op.equals("cn")){
            return Restrictions.like(myField, o.toString(), MatchMode.ANYWHERE);
        }else if(op.equals("eq")){
            return Restrictions.eq(myField, o);
        }else if(op.equals("ne")){
            return Restrictions.ne(myField, o);
        }else if(op.equals("lt")){
            return Restrictions.lt(myField, o);
        }else if(op.equals("le")){
            return Restrictions.le(myField, o);
        }else if(op.equals("gt")){
            return Restrictions.gt(myField, o);
        }else if(op.equals("ge")){
            return Restrictions.ge(myField, o);
        }else{
            return null;
        }       
    }   

    public void addMyRestriction(String groupOperation, Criteria criteria){
        Conjunction conjunction = Restrictions.conjunction();
        Disjunction disjunction = Restrictions.disjunction();
        if(groupOperation.equals("AND")){
            if(dataType.isEmpty()){
                conjunction.add(this.getSimpleExpression(field, data));
                criteria.add(conjunction);
            }else{
                if(dataType.equals("Calendar")){
                    try{
                        DateFormat formatter = new SimpleDateFormat("MMMM dd, yyyy");
                        Date date = (Date)formatter.parse(data);
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(date);
                        conjunction.add(this.getSimpleExpression(field, cal));
                        criteria.add(conjunction);
                    }catch (ParseException e){
                        System.out.println("Exception :"+e);
                    }                   //used for calendar data types 
                }else if(dataType.equals("Long")){
                    Long myLong = Long.parseLong(data);
                    conjunction.add(this.getSimpleExpression(field, myLong));
                    criteria.add(conjunction);
                                        //used for Long data types
                }else if(dataType.equals("Integer")){
                    Integer myInt = Integer.parseInt(data);
                    conjunction.add(this.getSimpleExpression(field, myInt));
                    criteria.add(conjunction);
                                        //used for Integer data types
                }else{
                    conjunction.add(this.getSimpleExpression(dataProperty, data));
                    criteria.createCriteria(field).add(conjunction);
                }                       //used for custom or project specific data types
            }// AND operation used conjunctions
        }else{
            if(dataType.isEmpty()){
                disjunction.add(this.getSimpleExpression(field, data));
                criteria.add(disjunction);
            }else{

                if(dataType.equals("Calendar")){
                    try{
                        DateFormat formatter = new SimpleDateFormat("MMMM dd, yyyy");
                        Date date = (Date)formatter.parse(data);
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(date);
                        disjunction.add(this.getSimpleExpression(field, cal));
                        criteria.add(disjunction);
                    }catch (ParseException e){
                        System.out.println("Exception :"+e);
                    } 
                }else if(dataType.equals("Long")){
                    Long myLong = Long.parseLong(data);
                    disjunction.add(this.getSimpleExpression(field, myLong));
                    criteria.add(disjunction);
                }else if(dataType.equals("Integer")){
                    Integer myInt = Integer.parseInt(data);
                    disjunction.add(this.getSimpleExpression(field, myInt));
                    criteria.add(disjunction);
                }else{
                    disjunction.add(this.getSimpleExpression(dataProperty, data));
                    criteria.createCriteria(field).add(disjunction);
                }
            }           
        }// OR operation used disjunctions
    }
}

Respondido el 22 de junio de 12 a las 18:06

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.