简体   繁体   English

Spring Data JPA-从组查询返回对象

[英]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. 我想知道很热,可以通过查询从Group返回对象。

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 然后我尝试采用Array元素

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[] 操作Object[]第一个解决方案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. 如果您的表或Wrapper不是Entities和/或您不能使用JPQL则在wrapper类中创建一个构造函数,该构造函数将所有需要的参数作为Object It is good idea to put put default non-arg constructor also because some other stuff might need it. 最好放置默认的非arg构造函数,因为其他一些东西可能需要它。

 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[]. 然后,如果使用Java8则可以使用原始Object []轻松进行Stream转换。

 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[] . 只需检查costructor中的args是否与查询Object[]所获取的顺序相同。 Of course you can also change order inside .map() but it only will mess things up in my opinion. 当然,您也可以在.map()更改顺序,但是在我看来,这只会使事情变得混乱。

Second solution use JPA NEW 第二种解决方案使用JPA NEW

requires that all related tables and Wrapper are entities and JPQL is available. 要求所有相关表和包装器都是实体,并且JPQL可用。 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 然后,就像创建JPQL TypedQuery一样简单-

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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