我有3个不同的实体:Partner
是主要实体,Offer
是合作伙伴的要约(多对一),Location
是合作伙伴中的任何位置。
@Entity
class ObjectLocation(@ManyToOne var place: Place, var partnerId: String) {
constructor() : this(Place(), "")
@Id
var id: String = IDGenerator.longId()
// other fields omitted
...
}
@Entity
class Offer(var partnerId: String, ...) {
constructor() : this(...)
@Id
var id: String = IDGenerator.longId()
...
}
@Entity
class Partner(...) {
constructor() : this(...)
@Id
var id: String = IDGenerator.longId()
...
}
因此,我需要按“地点”条件查找所有“要约”。我已经尝试过了:
Specification {
root: Root<Offer>, criteriaQuery: CriteriaQuery<*>, criteriaBuilder: CriteriaBuilder ->
val objectLocationRoot = criteriaQuery.from(ObjectLocation::class.java)
val objectCityId: Expression<String> = objectLocationRoot
.get<Place>("place")
.get<City>("parentCity")
.get<String>("id")
val objectPartnerId: Expression<String> = objectLocationRoot.get<String>("partnerId")
val offerPartnerId: Expression<String> = root.get<String>("partnerId")
val goodLocations: Predicate = criteriaBuilder.equal(objectCityId, cityId)
val objQuery: Subquery<String> = criteriaQuery.subquery(String::class.java)
.select(objectPartnerId)
.where(goodLocations)
return@Specification criteriaBuilder.equal(objQuery, offerPartnerId)
}
但这只给了我以下例外:
antlr.NoViableAltException: unexpected token: where
at org.hibernate.hql.internal.antlr.HqlBaseParser.fromRange(HqlBaseParser.java:1519) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.fromClause(HqlBaseParser.java:1343) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.selectFrom(HqlBaseParser.java:1063) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.queryRule(HqlBaseParser.java:748) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.subQuery(HqlBaseParser.java:3910) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:967) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3549) [hibernate-core-5.2.17.Final.jar:5.2.17.Final]
....
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: where near line 1, column 175
[select generatedAlias0 from com.arkell.entity.Offer as generatedAlias0, com.arkell.entity.geo.ObjectLocation as generatedAlias1 where
(select generatedAlias1.partnerId from where generatedAlias1.place.parentCity.id=:param0)=generatedAlias0.partnerId]; nested exception is java.lang.IllegalArgumentException:
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: where near line 1, column 175 [select generatedAlias0
from com.arkell.entity.Offer as generatedAlias0, com.arkell.entity.geo.ObjectLocation as generatedAlias1 where
(select generatedAlias1.partnerId from where generatedAlias1.place.parentCity.id=:param0)=generatedAlias0.partnerId]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:367)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:227)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
如何找到其伙伴所在城市的所有优惠?
答案 0 :(得分:0)
哦,这很简单。
Specification {
root: Root<Offer>, criteriaQuery: CriteriaQuery<*>, criteriaBuilder: CriteriaBuilder ->
val objectLocationRoot: Root<ObjectLocation> = criteriaQuery.distinct(true).from(ObjectLocation::class.java)
return@Specification criteriaBuilder.and(
criteriaBuilder.equal(root.get<String>("partnerId"), objectLocationRoot.get<String>("partnerId")),
criteriaBuilder.equal(objectLocationRoot.get<Place>("place")
.get<City>("parentCity")
.get<String>("id")("streetType"), cityId)
)
}