简体   繁体   English

javax.persistence.PersistenceException:org.hibernate.MappingException:未知实体:it。*。PoolStateResult | 将结果映射到DTO(不是实体)

[英]javax.persistence.PersistenceException: org.hibernate.MappingException: Unknown entity: it.*.PoolStateResult | Map a result in a DTO (not an Entity)

Using: 使用:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>1.5.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>1.5.8.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>1.5.8.RELEASE</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

this is my DTO. 这是我的DTO。 It is not an Entity on DB. 它不是DB上的实体。 I want to use it only for mapping 我想只用它来映射

public class PoolStateResult {

    private Integer totalCodes;
    private Integer assignedCodes;
    private Integer availableCodes;

    private Date startDateValidate;
    private Date endDateValidate;

constructors
getters and setters

this is the content of DAO 这是DAO的内容

    Query q = em.createNativeQuery("  SELECT p.start_validity_date as startDateValidate, "
            + " p.end_validity_date as endDateValidate, "
            + " (SELECT count(*) from POOL_CODES p WHERE p.id_pool = :poolCode) as totalCodes, "
            + " (SELECT count(*) "
            + " from VOUCHER v "
            + " WHERE v.id_reference_pool = :poolCode "
            + " AND v.status = 'ASSEGNATO') as assignedCodes, "
            + " (SELECT count(*) "
            + " from VOUCHER v, POOL_CODES p "
            + " WHERE v.id_reference_pool = p.id_pool "
            + " AND v.id_reference_pool = :poolCode "
            + " AND v.status = 'ASSEGNATO' "
            + " and p.end_validity_date < sysdate) as availableCodes "
            + " from POOL_CODES p "
            + " WHERE p.id_pool = :poolCode",PoolStateResult.class);

    q.setParameter("poolCode", "poolCode"); 
    return (PoolStateResult) q.getSingleResult();       

I add this package in configuration class 我在配置类中添加了这个包

entityManagerFactory.setPackagesToScan(
                env.getProperty("entitymanager.packages.to.scan"),

this is the exception 这是例外

javax.persistence.NoResultException: No entity found for query
    at org.hibernate.jpa.internal.QueryImpl.getSingleResult(QueryImpl.java:532)

Is there a way to force the mapping automatically as for all entity tables or the only way, with hibernate, for these types of queries is writing the mapping? 有没有办法像所有实体表一样自动强制映射,或者使用hibernate的唯一方法是为这些类型的查询编写映射? Is this the best and only way to map a non-entity Java object using Hibernate? 这是使用Hibernate映射非实体Java对象的最佳和唯一方法吗?

 @SqlResultSetMapping(
               name="getPoolStateResult",
               classes={
                  @ConstructorResult(
                       targetClass=PoolStateResult.class,
                         columns={
                            @ColumnResult(name="totalCodes", type=Integer.class),
                            @ColumnResult(name="assignedCodes", type=Integer.class),
                            @ColumnResult(name="availableCodes", type=Integer.class),
                            @ColumnResult(name="startDateValidate", type=Date.class),
                            @ColumnResult(name="endValidityDate", type=Date.class)
                            }
                  )
               }
              )

Then, where would the advantages of hibernate in this case? 那么,在这种情况下hibernate的优势在哪里呢?

Thanks 谢谢

No JPA and Hibernate can't automatically map a query result to a DTO without any mapping information. 没有任何映射信息,JPA和Hibernate都无法自动将查询结果映射到DTO。 You either map the result programmatically or you define a constructor call in an @SqlResultSetMapping , as you did in your example. 您可以以编程方式映射结果,也可以在@SqlResultSetMapping定义构造函数调用,就像在示例中所做的那样。

You don't need to do that if you want to map the result to an entity. 如果要将结果映射到实体,则不需要这样做。 Hibernate then tries to use the mapping definition of the entity to map the query result. 然后,Hibernate尝试使用实体的映射定义来映射查询结果。 So, your query result needs to return all entity attributes and they have to have the same name as you use in your entity mapping. 因此,您的查询结果需要返回所有实体属性,并且它们必须与您在实体映射中使用的名称相同。 I explained that in more details in a series of blog posts about @SqlResultMapping . 关于@SqlResultMapping一系列博客文章中有更详细的解释。

Regarding the benefits of using Hibernate for such a query: Hibernate doesn't provide you any benefits if this is the only database interaction you perform in a transaction. 关于使用Hibernate进行此类查询的好处:如果这是您在事务中执行的唯一数据库交互,则Hibernate不会为您提供任何好处。 But it allows you to use this query within a Hibernate session and therefore within the same transaction as all other operations Hibernate performs in that session. 但它允许您在Hibernate会话中使用此查询,因此在与Hibernate在该会话中执行的所有其他操作相同的事务中。

Try to alter a bit your query creation: 尝试改变您的查询创建:

1) Add the NEW package.Class to the select list 1)NEW package.Class添加到选择列表

String queryString = 
         "SELECT new com.mypackage.PoolStateResult("
             +  "p.start_validity_date as startDateValidate, "
             + " p.end_validity_date as endValidityDate, "
            + " (SELECT count(*) from POOL_CODES p WHERE p.id_pool = :poolCode) as totalCodes, "
            + " (SELECT count(*) "
            + ")"
            + " from VOUCHER v " 
               ...

2) Use the createNativeQuery method to which you pass the sql mapping name as the second param: 2)使用createNativeQuery方法将sql映射名称作为第二个参数传递给它:

em.createNativeQuery(queryString, "getPoolStateResult");

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

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