java - Hibernate:JPQL 查询中使用的 native 查询的 BigInteger 与 Long

标签 java hibernate jpa drools jpql

在我们的 Java EE EJB 应用程序中,我们有以下类的 JPA/Hibernate 映射:

@Entity
@Table(name="T")
@TableGenerator( /* all annotation attributes */)
public class T {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name="SEQ_T", nullable = false)
    private long seqT;

    @OneToMany(
        cascade = CascadeType.ALL, 
        orphanRemoval = true,
        mappedBy = "t",
        fetch = FetchType.LAZY
    )
    private List<W> wu;

}

这些是与之相关的类:

@Entity
@Table(name="W")
@TableGenerator( /* all annotation attributes */)
public class W {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name="SEQ_W", nullable = false)
    private long seqW;

    @Column(name="SEQ_T", nullable = false)
    private long seqT;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SEQ_T", insertable = false, updatable = false)
    private T t;

    @OneToMany(
        cascade = CascadeType.ALL, 
        orphanRemoval = true,
        mappedBy = "w",
        fetch = FetchType.LAZY
    )
    private List<WA> wua;
 }

@Entity
@Table(name="WA")
@TableGenerator( /* all annotation attributes */)
public class WA {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    @Column(name="SEQ_W_A", nullable = false)
    private long seqWA;

    @Column(name="SEQ_W", nullable = false)
    private long seqW;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SEQ_W", insertable = false, updatable = false)
    private W w;

}

此外,我们还有一个计划作业,由 TimerService 定期执行。 EJB。 首先,该作业必须了解是否有需要执行的内容,因此它会执行如下所示的 native SQL 查询,根据几个条件从 T 表中恢复 pk 列表:

List<Long> seqTs = (List<Long>)em.createNativeQuery("select SEQ_T from T").getResultList();

哪里emEntityManager 的一个实例。该查询显然不是那么简单,而是非常复杂,因为它源自一些 JOIN以及与其他表的子查询。 如果返回的列表不为空,则作业可以完成其工作,并执行此 JPQL 来加载它操作的实体:

String queryJPQL = "select wu from W wu JOIN FECTCH wu.wua where wu.seqT in :seqTs";
List<Workup> wus = em.createQuery(queryJPQL, W.class)
                     .setParameter("seqTs", seqTs)
                     .getResultList();

执行这个查询是因为即使我们总是需要@OneToMany中的数据关系,如果我们将该关系设置为 EAGER然后执行N+1次查询。相反,使用 JOIN FETCH执行唯一的查询来恢复某种 View ,然后 Hibernate 关联实体和关系。

嗯,问题是当.setParameter()时引发此异常。称为:

Exception in thread "main" java.lang.IllegalArgumentException: Parameter value element [1] did not match expected type [java.lang.Long (n/a)]

在这里阅读了很多帖子,并在Eclipse中设置了断点,我发现不是List<Long>从 native 查询返回,但 List<BigInteger> (根据数据库中PK的 native 类型),没有任何ClassCastException或类似的。为什么这个? 所以,我想我应该之前执行类似的操作:

List<Long> seqTLong = new ArrayList<Long>();
for(BigInteger seqNative : seqTs) 
        seqTLong.add(seqNative.longValue());

并将其传递给查询。 无论如何,这是正确的解决方案吗?安全吗?这是因为我们的应用程序支持 3 个 DB,并且它是由 ANT 在 3 个 JAR 中相应构建的:Oracle、PostgreSQL 和 SQL Server。 我可以假设 PK 的值始终是 BigInteger对于每个数据库?在Oracle中我们使用Number(19) ,在 PostgreSQL 中我们使用 BigInt ...我不记得 SQL Server。 然后,该实体被传递到 DRools,当应用规则时,该作业使用 EntityManager保存数据。这就是为什么我需要加载 JPA 实体,否则我会得到

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist

否则我就得打电话.find()再次对于 DRools 修改的每个事实,并通过调用其他事实的 getter 来设置其属性。这仍然会导致 N+1 查询。

最佳答案

更安全的方法是使用 Number 而不是 BigInteger

List<Long> seqTLong = new ArrayList<Long>();
for(Number seqNative : seqTs) {
        seqTLong.add(seqNative.longValue());
}

关于java - Hibernate:JPQL 查询中使用的 native 查询的 BigInteger 与 Long,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52242999/

相关文章:

java - JPA 连接在 Eclipse 中工作,但在编译时给出 NullPointerException

hibernate - 使用没有关系的 Hibernate/JPA 并避免多次数据库调用

java - 为包含 boolean 字段的持久实体覆盖 hashCode() 的正确方法?

java - 如何从 Hibernate 获取自定义类型的数据库方言?

hibernate - map 构造函数不适用于应用程序销毁

java - Hibernate.initialize(list) 与 setFetchMode

java - JPA Criteria API IN 表达式 参数列表

Java Web 服务 - 必须在新项目中吗?

java - 使用 Java 更新 Solr 中的文档

java - 在 JEditorPane 中显示来自 URL 的 html 图像。可能用 ImageView 吗?