gpt4 book ai didi

java - 强制 Hibernate 始终使用默认的无参数构造函数,即使指定了 select 参数

转载 作者:行者123 更新时间:2023-12-01 23:08:15 24 4
gpt4 key购买 nike

首先介绍一些上下文 - 我正在实现一个 API,其中请求包含客户端感兴趣的字段,基本上是直接选择的参数。由于如果不以这种方式进行限制,数据的总体大小会相当大,因此在序列化和传输数据以及限制从数据库检索的数据量时,这样做都会带来明显的性能优势。因此,我尝试在进行数据库查询时传递这些选择。

我面临的问题是,当使用 select 进行查询时,Hibernate 期望存在与 select 参数相对应的特定构造函数。例如,如果我指定只对 BasicInfo 类中的 id(长)和 model(字符串)列感兴趣,那么Hibternate 尝试查找并调用 BasicInfo(int, String) 构造函数。我收到的错误消息表明了这一点:

org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [my.package.BasicInfo]. Expected arguments are: long, java.lang.String [select new my.package.BasicInfo(generatedAlias0.id, generatedAlias0.model) from my.package.BasicInfo as generatedAlias0]

这对我来说不是一个选择。客户端可能希望在一个请求中按此顺序请求模型(字符串)和序列号(也是字符串),而另一个客户端可能希望请求相同字段的顺序相反。由于我只能创建 BasicInfo(String, String) 构造函数的一种组合,因此其中一个请求将以相反的顺序检索数据。即使忽略这个事实,我也必须为可能请求的所有可能字段创建所有可能的构造函数排列,这(由于此类中存在的字段数量)使得效率非常低,甚至是不可能的事情。

我正在寻找的是一种强制 Hibernate 使用默认类构造函数的方法,即使指定了 select 查询参数并使用 setter 来设置请求的字段也是如此。如果不是这样,那么也许另一种方法可以让我在发出每个请求时不从数据库检索完整行数据(然后在发送回客户端之前在应用程序代码中限制它)。

我还尝试注册一个自定义 Hibernate 拦截器并重写其 instantiate 方法,如下所示:

public class CustomInterceptor extends EmptyInterceptor {

@Override
public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
if(entityName.equals(BasicInfo.class.getName()))
return new BasicInfo();
return null;
}

}

希望这会改变对象创建策略。在这种情况下,当我不指定选择参数时,会正确调用此方法。然而,当给定 select 参数时,它根本不会被调用,并且 Hibternate 会尝试直接使用特定参数调用构造函数。

以下是该项目的相关部分:

代码设置选择参数(为了清楚起见,删除了代码中不相关的部分):

CriteriaQuery<T> query = cb.createQuery(responseClass);
Root<T> from = query.from(responseClass);
// Handle select
CriteriaQuery<T> select = null;
if(request.getSelect() != null) {
List<Selection<?>> selectionList = new ArrayList<Selection<?>>();
for(String s : request.getSelect()) {
selectionList.add(from.get(s));
}
select = query.multiselect(selectionList);
} else {
// select all fields
select = query.select(from);
}
TypedQuery<T> typedQuery = em.createQuery(select);
List<T> itemsList = typedQuery.getResultList();

applicaion.yml:

spring:
datasource:
platform: h2
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true

最佳答案

我使用旧的界面并得到结果集为 List<Object[]>只需使用 setProjection(myProjectionList) 。安Object[]不是你想要的,但将其转换为 Map<String, Object>是单行代码,转换为 JSON 后,您可能会看到与不完整对象相同的情况。

不确定它是否适合您的情况以及是否适用于 JPA2 或您正在使用的任何内容。

如果您坚持使用对象,您可以自己创建它们,可能是将字段复制到其“正确”位置,然后调用 new BasicInfo(myRearangedArray)构造函数在固定位置找到每个成员。 AFAIK 这就是 hibernate 在获取完整实体时所做的事情,因此您可以使用它的代码并节省自己编写构造函数的时间。

关于java - 强制 Hibernate 始终使用默认的无参数构造函数,即使指定了 select 参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58390313/

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