简体   繁体   中英

Spring data JPA - return an Object from a Group Query

i would like to know hot to return an object from a Group by query.

I have this query in my repository interface

@Query(value = "SELECT data, objectId, stampo, min(rendimento) as rendimento from rendimenti where objectId=:objectId "
            + "and stampo=:mold group By data, objectId, stampo order by data DESC LIMIT 0,1", nativeQuery = true)
    Wrapper findByObjectAndMold(@Param("objectId") int objecId, @Param("mold") String mold);

This query should return a single Object (or none), running it on the DB works. I created a Wrapper object to take the result

public class Wrapper {

    @Column(name="rendimento")
    private Performance performance;

    private int objectId;

    @Column(name="stampo")
    private String mold;

    @Column(name="data")
    private Date date;

//getters and setters
}

I'm getting this exception

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Unknown entity: javax.persistence.Tuple; nested exception is org.hibernate.MappingException: Unknown entity: javax.persistence.Tuple] with root cause

org.hibernate.MappingException: Unknown entity: javax.persistence.Tuple

So i think the query cannot be mapped to my wrapper...

So i changed the query method in this way

@Query(value = "SELECT data, objectId, stampo, min(rendimento) as rendimento from rendimenti where objectId=:objectId "
            + "and stampo=:mold group By data, objectId, stampo order by data DESC LIMIT 0,1", nativeQuery = true)
    Object[] findByObjectAndMold(@Param("objectId") int objecId, @Param("mold") String mold);

and then i tried to take the Array elements

Object[] o = repository(object.getObjectId(), mold);
        logger.debug("Wrapper is " + o.toString());
        if(o != null){
            Date date = (Date) o[0];
            logger.debug("La data è : " + date);
            float performance = (float) o[3];

but, i'm getting a casting error..

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.Date

Which is the correct way to do it?

First solution for manipulating Object[]

if your tables or Wrapper are not Entities and/or you cannot use JPQL then create a constructor in wrapper class that takes all need parameters as Object s. It is good idea to put put default non-arg constructor also because some other stuff might need it.

 public Wrapper(Object o1, Object o2 ... ) { //means NOT varargs but as //many args you need, all as objects this.performance = (Performance)o1; this.id = (Integer)o2; ... } 

Then if using Java8 it easy to convert with Stream using your original Object[].

 List<Wrapper> wrappers = Arrays.stream(yourObjectArray) .map( arr -> new Wrapper(arr[0], arr[1], ...)) // the rs possible args .collect(Collectors.toList()); 

Just check that args in costructor are in the same order as fetched by query to Object[] . Of course you can also change order inside .map() but it only will mess things up in my opinion.

Second solution use JPA NEW

requires that all related tables and Wrapper are entities and JPQL is available. Again create a constructor for Wrapper but now wioth real types so no casting anymore

 public Wrapper(Performance o1, Integer o2 ... ) { //means NOT varargs but as //many args you need, all as real types they are this.performance = o1; this.id = o2; ... } 

Then it would be as easy as creating JPQL TypedQuery - for example - as

 TypedQuery<Wrapper> tq = em.createQuery( " SELECT NEW Wrapper(E.Performance, E.id ...) FROM yourquerystuff " , Wrapper.class); List<Wrapper> wrappers = tq.getResultList(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM