Hibernate criteriaQuery condizione su id wrapper

di il
3 risposte

Hibernate criteriaQuery condizione su id wrapper

Ciao a tutti.

Sto provando a fare questo esercizio:

Ho una classe Materia e la sua classe wrapper MateriaId.

La classe MateriaId contiente una sola variabile di tipo stringa "nome" con i relativi getter and setter e gli @Override di hashCode ed equals.

La classe Materia contiene le seguenti variabili
private MateriaId id = null;
private String descrizione = null;

getter, setter, hashcode ed equals e due acceleratori getNome e setNome che agiscono sull'oggetto id.

Come esercizio sto cercando di implementare un metodo che a transaction aperta, in base a determinate condizioni, interroghi la tabella.
Ho importato hibernate e sto cercando di gestire un metodo per fare una ricerca condizionata sulla tabella materia.
Dopo qualche tentativo ho implementato questo metodo che dovrebbe prendere in input un oggetto materia e restituire un oggetto List <Materia>
Questo il codice.

private List<Materia> retriveInTransaction(Materia materia) {
		CriteriaBuilder builder = session.getCriteriaBuilder();
		CriteriaQuery<Materia> criteriaQuery = builder.createQuery(Materia.class);
		Root<Materia> root = criteriaQuery.from(Materia.class);		
		List<Predicate> predicateList = new ArrayList<Predicate>();
		if(materia.getNome()!=null) {
			predicateList.add(builder.like(root.get("id"),"%"+materia.getNome()+"%"));
		}
		if(materia.getDescrizione()!=null) {
			predicateList.add(builder.like(root.get("descrizione"),"%"+materia.getDescrizione()+"%"));
		}		
		List<Materia> result= new ArrayList<Materia>();		
		criteriaQuery.where(builder.and(predicateList.toArray(new Predicate[predicateList.size()])));
		Query<Materia> query = session.createQuery(criteriaQuery);
		result= query.list();
		return result;
	}
	
A guardare i log di hibernate le condizioni sembrano corrette ma ho eccezione sulla riga query.list();
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of percorsoPackage.MateriaId.nome
il problema se ho capito bene è che gli stoo passando id mentre lui si aspetta nome.

Potreste spiegarmi come mai query.list() mi da questa eccezione?

3 Risposte

  • Re: Hibernate criteriaQuery condizione su id wrapper

    Ciao,

    Ho riprovato a scirvere da zero le classi e fatto vari tentativi ma non ne sono uscito, ho provato ad mettere la domanda anche stackoverflow (dove ho dettagliato meglio il problema https://stackoverflow.com/questions/61468577/query-list-hibernate-exception-getter-method-of-property) se ho news vi aggiorno.
  • Re: Hibernate criteriaQuery condizione su id wrapper

    Premesso che CriteriaQuery l'ho usato pochissimo e, comunque, non ho mai avuto a che fare con strutture fatte in quel modo (non vedo traccia di annotazioni che descrivano il fatto che quelle siano delle @Entity, né che la chiave sia un @Embeddable), generalmente si usa embeddare una classe quando la chiave non è un valore singolo, ma è composta da più campi (in quel caso di parla di @EnbeddedId o si fa ricorso a @IdClass). Non si capisce perchè tu abbia recluso quell'unico campo all'interno di una classe a sé stante.

    Quel che vedo e che, secondo me, potrebbe dar fastidio ad Hibernate è il campo "token" che è definito "pubblico". Prova a renderlo privato ed accederci solo usando il metodo getter:
    
    if(user.getId()!=null) {
       predicateList.add(builder.like(root.get("id"),"%"+user.getId().token+"%"));
    }
    
    Qui modifica la chiamata così:
    
    if(user.getId()!=null) {
       predicateList.add(builder.like(root.get("id"),"%"+user.getId().getToken()+"%"));
    }
    
    Comunque, nei log dovrebbe esserci qualcosa di un po' più dettagliato riguardao all'eccezione... tipo lo stackTrace, che magari rimanda ad una eccezione annidata un po' più esplicativa.

    Ciao.
  • Re: Hibernate criteriaQuery condizione su id wrapper

    Due spiegazioni giusto per precisare.
    Sono un gran ignorantone e sto iniziando a giocare con Java perché dopo anni ho un po di tempo la sera e mi sono messo a riprendere in mano un vecchio corso (ottobre 2015) dove negli esercizi c'era questa casistica che ovviamente non ha senso. Nel corso di allora si usa Critteria (deprecato dal 2018) e non CritteriaBuilder. Siccome mi da fastidio cercare di imparare usando metodi deprecati ho provato con metodi analogi. Preciso che usando l'oggetto Critteria per costruire la query non ho eccezioni e l'esecuzione è consistente.

    Ho abilitato un po di log di hibernate qui lo stuck completo
    
    
    Hibernate: 
        /* select
            generatedAlias0 
        from
            ApplicationUser as generatedAlias0 
        where
            generatedAlias0.id like :param0 */ select
                applicatio0_.token as token1_0_,
                applicatio0_.description as descript2_0_ 
            from
                ApplicationUser applicatio0_ 
            where
                applicatio0_.token like ?
    14:13:46.601 [main] ERROR org.hibernate.property.access.spi.GetterMethodImpl - HHH000122: IllegalArgumentException in class: com.azienda.progettoCorso.model.ApplicationUserId, getter method of property: token
    14:13:46.611 [main] DEBUG org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl - JDBC transaction marked for rollback-only (exception provided for stack trace)
    java.lang.Exception: exception just for purpose of providing stack trace
    	at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.markRollbackOnly(JdbcResourceLocalTransactionCoordinatorImpl.java:324)
    	at org.hibernate.engine.transaction.internal.TransactionImpl.markRollbackOnly(TransactionImpl.java:203)
    	at org.hibernate.internal.AbstractSharedSessionContract.markForRollbackOnly(AbstractSharedSessionContract.java:396)
    	at org.hibernate.internal.ExceptionConverterImpl.handlePersistenceException(ExceptionConverterImpl.java:297)
    	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
    	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1542)
    	at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.list(CriteriaQueryTypeQueryAdapter.java:96)
    	at com.azienda.progettoCorso.dao.DaoHibernate.retriveUserInTransaction(DaoHibernate.java:395)
    	at com.azienda.progettoCorso.dao.DaoHibernate.retrieve(DaoHibernate.java:377)
    	at com.azienda.progettoCorso.dao.TestDao.testToken(TestDao.java:78)
    	at com.azienda.progettoCorso.dao.TestDao.main(TestDao.java:39)
    javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.azienda.progettoCorso.model.ApplicationUserId.token
    14:13:46.614 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - rolling back
    	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1542)
    	at org.hibernate.query.criteria.internal.compile.CriteriaQueryTypeQueryAdapter.list(CriteriaQueryTypeQueryAdapter.java:96)
    	at com.azienda.progettoCorso.dao.DaoHibernate.retriveUserInTransaction(DaoHibernate.java:395)
    	at com.azienda.progettoCorso.dao.DaoHibernate.retrieve(DaoHibernate.java:377)
    	at com.azienda.progettoCorso.dao.TestDao.testToken(TestDao.java:78)
    	at com.azienda.progettoCorso.dao.TestDao.main(TestDao.java:39)
    Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.azienda.progettoCorso.model.ApplicationUserId.token
    	at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:65)
    	at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValue(AbstractComponentTuplizer.java:59)
    	at org.hibernate.tuple.component.AbstractComponentTuplizer.getPropertyValues(AbstractComponentTuplizer.java:65)
    	at org.hibernate.tuple.component.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:92)
    	at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:443)
    	at org.hibernate.type.ComponentType.nullSafeGetValues(ComponentType.java:384)
    	at org.hibernate.type.ComponentType.nullSafeSet(ComponentType.java:337)
    	at org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:53)
    	at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:648)
    	at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:2120)
    	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2034)
    	at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2012)
    	at org.hibernate.loader.Loader.doQuery(Loader.java:953)
    	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354)
    	at org.hibernate.loader.Loader.doList(Loader.java:2838)
    	at org.hibernate.loader.Loader.doList(Loader.java:2820)
    	at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2652)
    	at org.hibernate.loader.Loader.list(Loader.java:2647)
    	at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506)
    	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:396)
    	at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219)
    	at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1404)
    	at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1565)
    	at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1533)
    	... 5 more
    Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    	at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:42)
    	... 28 more
    14:13:46.616 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
    14:13:46.616 [main] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl - Initiating JDBC connection release from afterTransaction
    
    
    Sono andato in debugg entrando dentro l'oggetto da cui viene l'eccezione e l'eccezione sembra venga data quando costruisce l'alias del token (vedo che gli viene passata la stringa '%1%' che è quella della colonna token del record che sta leggendo.

    ApplicationUser
    package com.azienda.progettoCorso.model;
    
    import java.io.Serializable;
    
    public class ApplicationUser implements Serializable{
    	private static final long serialVersionUID = 1L;
    
    	private ApplicationUserId id = new ApplicationUserId();
    	private String description = null;
    	
    	public ApplicationUserId getId() {
    		return id;
    	}
    	
    	public void setId(ApplicationUserId id) {
    		this.id = id;
    	}
    
    	public String getDescription() {
    		return description;
    	}
    
    	public void setDescription(String description) {
    		this.description = description;
    	}
    
    }
    
    ApplicationUserId
    package com.azienda.progettoCorso.model;
    
    import java.io.Serializable;
    
    public class ApplicationUserId implements Serializable{
    
    	private static final long serialVersionUID = 1L;
    	
    	private String token=null;
    
    	public String getToken() {
    		return token;
    	}
    
    	public void setToken(String token) {
    		this.token = token;
    	}
    
    	@Override
    	public int hashCode() {
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + ((token == null) ? 0 : token.hashCode());
    		return result;
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		ApplicationUserId other = (ApplicationUserId) obj;
    		if (token == null) {
    			if (other.token != null)
    				return false;
    		} else if (!token.equals(other.token))
    			return false;
    		return true;
    	}
    
    }
    
    metodo che da eccezione
    private List<ApplicationUser> retriveUserInTransaction(ApplicationUser user) {
    		CriteriaBuilder builder = session.getCriteriaBuilder();
    		CriteriaQuery<ApplicationUser> criteriaQuery = builder.createQuery(ApplicationUser.class);
    		Root<ApplicationUser> root = criteriaQuery.from(ApplicationUser.class);		
    		List<Predicate> predicateList = new ArrayList<Predicate>();
    		if(user.getId()!=null) {
    			predicateList.add(builder.like(root.get("id"),"%"+user.getId().getToken()+"%"));
    		}
    		if(user.getDescription()!=null) {
    			predicateList.add(builder.like(root.get("description"),"%"+user.getDescription()+"%"));
    		}		
    		List<ApplicationUser> result= new ArrayList<ApplicationUser>();		
    		criteriaQuery.where(builder.and(predicateList.toArray(new Predicate[predicateList.size()])));
    		Query<ApplicationUser> query = session.createQuery(criteriaQuery);
    		result= query.list();
    		return result;
    	}
    
    ho provato adichiarare l'oggetto Private come consigliato ma il problema persiste
Devi accedere o registrarti per scrivere nel forum
3 risposte