我需要帮助解决我从Hibernate 5.x迁移到6.2后遇到的问题。以前一直没有任何问题的代码现在失败了。下面是一个失败的查询示例。
public List<MarketCommodityInfo> getMarketCommodityInfoForCommodities(Double longitude, Double latitude,
Integer page) {
return getEntityManager().createQuery(
"SELECT new org.kisanag.model.mandi.MarketCommodityInfo (mci, earth_distance(ll_to_earth(m.latitude, m.longitude), ll_to_earth(:latitude, :longitude)) / :conversion AS distance) FROM MarketCommodityInfo mci JOIN mci.id.market m JOIN mci.id.commodity c WHERE earth_distance(ll_to_earth(m.latitude, m.longitude),ll_to_earth(:latitude, :longitude)) < :within * :conversion ORDER BY distance, mci.id.arrivalDate, c.name",
MarketCommodityInfo.class)
.setParameter("latitude", latitude)
.setParameter("longitude", longitude)
.setParameter("within", 200)
.setParameter("conversion", 1000)
.setMaxResults(pageSize)
.setFirstResult(page * pageSize)
.getResultList();
}
此操作因错误而失败
Caused by: java.lang.IllegalStateException: Could not determine appropriate instantiation strategy - no matching constructor found and one or more arguments did not define alias for bean-injection
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl.resolveAssembler(DynamicInstantiationResultImpl.java:197)
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl.createResultAssembler(DynamicInstantiationResultImpl.java:106)
at org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping.resolveAssemblers(StandardJdbcValuesMapping.java:53)
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:78)
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:64)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:341)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:168)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.list(JdbcSelectExecutorStandardImpl.java:93)
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:31)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$0(ConcreteSqmSelectQueryPlan.java:109)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:302)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:243)
at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:521)
at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:367)
at org.hibernate.query.sqm.internal.QuerySqmImpl.list(QuerySqmImpl.java:1084)
at org.hibernate.query.Query.getResultList(Query.java:119)
我修改了查询并添加了commodityInfo
SELECT new org.kisanag.model.mandi.MarketCommodityInfo (mci AS *commodityInfo*, earth_distance(ll_to_earth(m.latitude, m.longitude), ll_to_earth(:latitude, :longitude)) / :conversion AS distance) FROM MarketCommodityInfo mci JOIN mci.id.market m JOIN mci.id.commodity c WHERE earth_distance(ll_to_earth(m.latitude, m.longitude),ll_to_earth(:latitude, :longitude)) < :within * :conversion ORDER BY distance, mci.id.arrivalDate, c.name
现在它失败了,出现以下错误
Caused by: org.hibernate.query.sqm.sql.internal.InstantiationException: Unable to determine dynamic instantiation injection strategy for org.kisanag.model.mandi.MarketCommodityInfo#commodityInfo
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationAssemblerInjectionImpl.lambda$new$0(DynamicInstantiationAssemblerInjectionImpl.java:82)
at org.hibernate.internal.util.beans.BeanInfoHelper.visitBeanInfo(BeanInfoHelper.java:55)
at org.hibernate.internal.util.beans.BeanInfoHelper.visitBeanInfo(BeanInfoHelper.java:48)
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationAssemblerInjectionImpl.<init>(DynamicInstantiationAssemblerInjectionImpl.java:35)
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl.resolveAssembler(DynamicInstantiationResultImpl.java:208)
at org.hibernate.sql.results.graph.instantiation.internal.DynamicInstantiationResultImpl.createResultAssembler(DynamicInstantiationResultImpl.java:106)
at org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping.resolveAssemblers(StandardJdbcValuesMapping.java:53)
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:78)
at org.hibernate.sql.results.internal.ResultsHelper.createRowReader(ResultsHelper.java:64)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.doExecuteQuery(JdbcSelectExecutorStandardImpl.java:341)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.executeQuery(JdbcSelectExecutorStandardImpl.java:168)
at org.hibernate.sql.exec.internal.JdbcSelectExecutorStandardImpl.list(JdbcSelectExecutorStandardImpl.java:93)
at org.hibernate.sql.exec.spi.JdbcSelectExecutor.list(JdbcSelectExecutor.java:31)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.lambda$new$0(ConcreteSqmSelectQueryPlan.java:109)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.withCacheableSqmInterpretation(ConcreteSqmSelectQueryPlan.java:302)
at org.hibernate.query.sqm.internal.ConcreteSqmSelectQueryPlan.performList(ConcreteSqmSelectQueryPlan.java:243)
at org.hibernate.query.sqm.internal.QuerySqmImpl.doList(QuerySqmImpl.java:521)
at org.hibernate.query.spi.AbstractSelectionQuery.list(AbstractSelectionQuery.java:367)
at org.hibernate.query.sqm.internal.QuerySqmImpl.list(QuerySqmImpl.java:1084)
at org.hibernate.query.Query.getResultList(Query.java:119)
这里是我的类MarketCommodityInfo
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import jakarta.persistence.Transient;
@Entity
public class MarketCommodityInfo {
@EmbeddedId
public MarketCommodityInfoKey id;
public Double minPrice;
public Double modalPrice;
public Double maxPrice;
public String unit;
@Transient
public Double distance;
public MarketCommodityInfo() {
}
public MarketCommodityInfo(MarketCommodityInfo commodityInfo, Double distance) {
this.id = commodityInfo.id;
this.minPrice = commodityInfo.minPrice;
this.modalPrice = commodityInfo.modalPrice;
this.maxPrice = commodityInfo.maxPrice;
this.unit = commodityInfo.unit;
this.distance = distance;
}
}
还有钥匙
import java.io.Serializable;
import java.util.Date;
import jakarta.persistence.Embeddable;
import jakarta.persistence.OneToOne;
@Embeddable
public class MarketCommodityInfoKey implements Serializable {
public Date arrivalDate;
@OneToOne
public Commodity commodity;
@OneToOne
public Market market;
public MarketCommodityInfoKey() {
}
public MarketCommodityInfoKey(Date arrivalDate, Commodity commodity, Market market) {
this.arrivalDate = arrivalDate;
this.commodity = commodity;
this.market = market;
}
@Override
public String toString() {
return "MarketCommodityInfoKey [arrivalDate=" + arrivalDate + ", commodity=" + commodity + ", market="
+ market + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((arrivalDate == null) ? 0 : arrivalDate.hashCode());
result = prime * result + ((commodity == null) ? 0 : commodity.hashCode());
result = prime * result + ((market == null) ? 0 : market.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MarketCommodityInfoKey other = (MarketCommodityInfoKey) obj;
if (arrivalDate == null) {
if (other.arrivalDate != null)
return false;
} else if (!arrivalDate.equals(other.arrivalDate))
return false;
if (commodity == null) {
if (other.commodity != null)
return false;
} else if (!commodity.equals(other.commodity))
return false;
if (market == null) {
if (other.market != null)
return false;
} else if (!market.equals(other.market))
return false;
return true;
}
}
请帮帮我
1条答案
按热度按时间kcugc4gi1#
更新
我之前的回答是错误的。
真实的的原因是:
1.第一次尝试(使用构造函数注入)不起作用,因为Hibernate无法确定
earth_distance()
函数的返回类型,因为您没有将其注册为已知的SQL函数。Hibernate 6目前坚持知道所有构造函数参数的类型。1.第二次尝试(使用字段注入)也不起作用,因为没有名为
commodityInfo
的字段。但是即使你修复了这个问题,它 * 仍然 * 不会工作,因为Hibernate * 仍然 * 不知道earth_distance()
函数的类型。因此,解决方案是使用
FunctionContributor
来注册此SQL函数及其返回类型。现在,我怀疑
DynamicInstantiationAssemblerInjectionImpl
在这里有点过于繁琐,我们可以改进它以处理不是每个参数类型都已知的情况。所以我会就此开个会。