Need help with issue I am facing since I moved from Hibernate 5.x to 6.2. The code which has been working without any issue before is failing now. Here is an example for the query which is failing.
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();
}
This was failing with error
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)
I modified the query and added 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
and now it failing with following error
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)
Here is my class 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;
}
}
and the key
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;
}
}
Please help.
My previous answer was incorrect.
The real reason is:
earth_distance()
function, since you have not registered it as a known SQL function. Hibernate 6 currently insists on knowing the types of all constructor arguments.commodityInfo
. But even if you fix that, it still won't work, because Hibernate still won't know the type of the earth_distance()
function.So the solution is to use a FunctionContributor
to register this SQL function and its return type.
Now, I suspect that DynamicInstantiationAssemblerInjectionImpl
is being a bit too fussy here, and that we could improve it to handle your case where not every argument type is known. So I will open an issue about that.