gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 06:01:19 33 4
gpt4 key购买 nike

在我们的 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/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com