【问题标题】:javax.persistence.PersistenceException: org.hibernate.MappingException: Unknown entity: it.*.PoolStateResult | Map a result in a DTO (not an Entity)javax.persistence.PersistenceException:org.hibernate.MappingException:未知实体:it.*.PoolStateResult |将结果映射到 DTO(不是实体)
【发布时间】:2017-12-15 08:18:37
【问题描述】:

使用:

<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>

这是我的 DTO。它不是数据库上的实体。我只想将它用于映射

public class PoolStateResult {

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

    private Date startDateValidate;
    private Date endDateValidate;

constructors
getters and setters

这是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();       

我在配置类中添加了这个包

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

这是个例外

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

有没有办法像所有实体表一样自动强制映射,或者对于这些类型的查询,使用休眠的唯一方法是编写映射? 这是使用 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)
                            }
                  )
               }
              )

那么,这种情况下hibernate的优势在哪里呢?

谢谢

【问题讨论】:

  • 您在问题描述中提到的异常与映射问题无关,而是与使用q.getSingleResult();有关。你看,当数据库中没有符合你的选择条件的记录时,这个方法会抛出一个异常。
  • 我确定我在数据库中有结果。如果我对 Db 执行查询,它可以工作。还编写映射 IT 作品。
  • p.end_validity_date as endValidityDate - DTO 中没有名为 endValidityDate 的成员变量。这可能是问题吗?
  • 您是否尝试过手动运行此精确查询并查看结果?
  • @Cashbee 我编辑了问题是一样的。

标签: java hibernate jpa pojo dto


【解决方案1】:

没有任何映射信息,没有 JPA 和 Hibernate 无法自动将查询结果映射到 DTO。您要么以编程方式映射结果,要么在 @SqlResultSetMapping 中定义构造函数调用,就像您在示例中所做的那样。

如果要将结果映射到实体,则无需这样做。 Hibernate 然后尝试使用实体的映射定义来映射查询结果。因此,您的查询结果需要返回所有实体属性,并且它们必须与您在实体映射中使用的名称相同。我在series of blog posts about @SqlResultMapping 中更详细地解释了这一点。

关于使用 Hibernate 进行此类查询的好处: 如果这是您在事务中执行的唯一数据库交互,Hibernate 不会为您提供任何好处。但它允许您在 Hibernate 会话中使用此查询,因此在与 Hibernate 在该会话中执行的所有其他操作相同的事务中。

【讨论】:

  • 谢谢。关于@SqlResultSetMapping:EclipseLink-->把它放在classpath中的任意一个类; Hibernate-->把它放在任何用@Entity注解的类中;对吗?
  • 我不确定 EclipseLink 但它适合 Hibernate。如果将注释放入 package-info.java 或非实体类中,它会忽略注释
【解决方案2】:

尝试稍微改变一下您的查询创建:

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) 使用您将 sql 映射名称作为第二个参数传递给的 createNativeQuery 方法:

em.createNativeQuery(queryString, "getPoolStateResult");

【讨论】:

  • 嗨,编写映射 IT 工作,即使不更改查询。问题正是我是否可以在不编写映射器而仅使用 DTO PoolStateResult(例如实体)的情况下获得相同的结果
  • 你可以尝试在Query上设置:.setResultTransformer(Transformers.aliasToBean(PoolStateResult .class))
  • setResultTransformer 已弃用或在 hibernate 5 中不存在
猜你喜欢
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2019-07-25
  • 2017-09-17
  • 2021-10-28
相关资源
最近更新 更多