你好,
我想用leftJoin(EntityPath<P> target).on(Predicate condition)
符号执行左连接。
这是我的实体:
@Entity(name = "CLASSROOM")
public class Classroom {
// [...]
}
@Entity(name = "STUDENT")
public class Student {
@Column(name = "NAME")
private String name;
<strong i="9">@ManyToOne</strong>
@JoinColumn(name = "CLASSROOM_ID")
private Classroom classroom;
// [...]
}
这是一个不起作用的示例查询:
QClassroom classroom = QClassroom.classroom;
QStudent student = QStudent.student;
query.from(classroom)
.leftJoin(student).on(classroom.eq(student.classroom))
.where(student.name.eq("antoine"))
.list(classroom)
这是错误日志:
org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [select classroom
from com.my.personnal.path.entity.Classroom classroom
left join STUDENT student with classroom = student.classroom
where student.name = ?1]
当然,对于这个例子,我可以做这样的事情:
query.from(student)
.leftJoin(student.classroom, classroom)
.where(student.name.eq("antoine"))
.list(classroom)
...但我真正的查询比这更大,我不能以query.from(student)
开始查询。
我做错了什么?
我正在使用 QueryDsl 3.6.6
它应该是
QClassroom classroom = QClassroom.classroom;
QStudent student = QStudent.student;
query.from(classroom)
.leftJoin(classroom.students, student)
.where(student.name.eq("antoine"))
.list(classroom)
为此,您需要在课堂上逆向映射学生
好的,谢谢,这可能是一个解决方案,但实际上我有两个限制:
.from(classroom)
开始我的查询Student
实体中的ManyToOne
关联链接起来(没有双向关联)有了这两个限制,是否有可能加入我的两个实体?
这也应该有效
query.from(student, classroom)
.where(
student.classroom.eq(classroom),
student.name.eq("antoine"))
.list(classroom)
如果还没有解决,请重新打开
嗨蒂莫,
抱歉重新打开这个问题,但我有一个类似的问题,无法接受你上面描述的解决方案。
我的架构:
校园班
<strong i="9">@Entity</strong>
public class Campus {
<strong i="10">@Id</strong>
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(mappedBy = "associatedCampus", cascade = CascadeType.ALL)
private Set<Building> buildings;
... Getters/Setters, Constructors
建筑类
<strong i="14">@Entity</strong>
public class Building {
<strong i="15">@Id</strong>
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String uuid;
<strong i="16">@ManyToOne</strong>
@JoinColumn(name = "associatedCampus")
private Campus associatedCampus;
... Getters/Setters, Constructors
我尝试从 Campus 表加入到 Building 表,但总是遇到我不明白的错误。
错误:java.lang.IllegalArgumentException:building.associatedCampus 不是根路径
从大楼到校园加入绝对没有问题,但从校园到大楼则不然。
例子:
public List<Building> getBuildingsByCampusName(String campusName) {
JPAQuery<Building> query = new JPAQuery<>(em);
QCampus campus = QCampus.campus;
QBuilding building = QBuilding.building;
query.select(building)
.from(building)
.join(building.associatedCampus, campus)
.where(campus.name.like("%" + campusName + "%"));
List<Building> result = query.fetch();
return result;
你能不能给我一个提示,我的问题是什么,或者为什么建筑->校园的反向连接不起作用?
格雷茨
马库斯
我的实体如下:
@实体
@Table(name = "参与者")
公共类参与者{
@OneToOne(cascade = CascadeType.DETACH, fetch = FetchType.EAGER, targetEntity = ServiceType.class)
@JoinTable(name = "PARTICIPANT_SERVICES", joinColumns = @JoinColumn(name = "PARTICIPANT_ID", referencedColumnName = "PARTICIPANT_ID"), inverseJoinColumns = @JoinColumn(name = "SERVICE_TYPE_ID",referencedColumnName = "SERVICE_TYPE_ID"))
私人名单
@OneToMany(mappedBy = "participant")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<ParticipantRegionCountry> participantRegionCountries;
吸气剂 / 吸气剂
}
@实体
@Table(name = "SERVICE_TYPE")
公共类服务类型{
<strong i="20">@Id</strong>
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "SERVICE_TYPE_ID")
private Long id;
@Column(name = "SERVICE_TYPE_NAME")
private String name;
getter / setter
}
当我在参与者实体上查询异常时:
列表
JPQLQuery<Participant> query = new JPAQuery<>(em);
QParticipant participant = QParticipant.participant;
QParticipantRegionCountry participantRegionCountry = QParticipantRegionCountry.participantRegionCountry;
BooleanBuilder predicate = new BooleanBuilder();
predicate.and(participantRegionCountry.region.in(regions));
participants = query.select(participant).from(participant).join(participant.participantRegionCountries, participantRegionCountry).where(predicate).distinct().fetch();
例外:
休眠:选择不同participan0_.PARTICIPANT_ID如PARTICIPANT_ID1_6_,participan0_.BUSINESS_NAME如BUSINESS_NAME2_6_,participan0_.BUSINESS_TYPE_ID如BUSINESS_TYPE_ID9_6_,participan0_.CITY_ID如CITY_ID10_6_,participan0_.CONTACT_ADDRESS如CONTACT_ADDRESS3_6_,participan0_.CONTACT_EMAIL如CONTACT_EMAIL4_6_,participan0_.CONTACT_NAME如CONTACT_NAME5_6_,participan0_.CONTACT_PHONE如CONTACT_PHONE6_6_,participan0_.COUNTRY_ID为COUNTRY_ID11_6_,participan0_.CURRENCY_ID为CURRENCY_ID12_6_,participan0_.LANGUAGE_ID为LANGUAGE_ID13_6_,participan0_.PARTICIPANT_PACK_ID为PARTICIPANT_PACK_14_6_,participan0_.PARTICIPANT_TYPE_ID为PARTICIPANT_TYPE_15_6_,participan0_.PAYMENT_METHOD_TYPE_ID为PAYMENT_METHOD_TY16_6_,participan0_.PROJECTED_VOLUME为PROJECTED_VOLUME7_6_,participan0_.REGION_ID为REGION_ID17_6_, participan0_.USER_NAME as USER_NAME8_6_, participan0_1_.SERVICE_TYPE_ID as SERVICE_TYPE_ID1_12_ from PARTICIPANT participan0_left external join PARTICIPANT_SERVICES par ticipan0_1_ on participan0_.PARTICIPANT_ID=participan0_1_.PARTICIPANT_ID 内连接 SERVICE_TYPE servicetyp1_ on participan0_1_.SERVICE_TYPE_ID=servicetyp1_.SERVICE_TYPE_ID 内连接 PARTICIPANT_REGION_COUNTRY participan2_ 上 participan0_.PARTICIPANT_REGION_COUNTRY participan2_在 participan02_service_TYPE_PARTICIPANT_PARTICIPANT_COUNTRY participan2_ 上 service_TYPE_PARTICIPANT_ID_PARTICIPANT_TYPE_PARTICIPANT_ID_PARTICIPANT_TYPE_PARTICIPANT_ 和 (participan2_.REGION_ID in (? , ?))
休眠:选择 servicetyp0_.SERVICE_TYPE_ID 作为 SERVICE_TYPE_ID1_18_0_, servicetyp0_.SERVICE_TYPE_NAME 作为 SERVICE_TYPE_NAME2_18_0_ from SERVICE_TYPE servicetyp0_ where servicetyp0_.SERVICE_TYPE_ID=?
javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: 无法设置字段值 [com.mycompany.app.spring.orm.model。 ServiceType@4e9e0c6 ] 反射值:[class com.mycompany.app.spring.orm.model.Participant.serviceTypes] com.mycompany.app.spring.orm.model.Participant.serviceTypes 的设置者
在 org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:149)
在 org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:157)
在 org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1423)
在 org.hibernate.query.Query.getResultList(Query.java:146)
在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
在 java.lang.reflect.Method.invoke(Method.java:497)
在 org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:379)
在 com.sun.proxy.$Proxy47.getResultList(来源不明)
在 com.querydsl.jpa.impl.AbstractJPAQuery.getResultList(AbstractJPAQuery.java:160)
在 com.querydsl.jpa.impl.AbstractJPAQuery.fetch(AbstractJPAQuery.java:202)
在 com.mycompany.app.spring.orm.service.ParticipantService.listParticipants(ParticipantService.java:53)
在 com.mycompany.app.App.main(App.java:56)
引起:org.hibernate.PropertyAccessException:无法设置字段值 [com.mycompany.app.spring.orm.model。 ServiceType@4e9e0c6 ] 反射值:[class com.mycompany.app.spring.orm.model.Participant.serviceTypes] com.mycompany.app.spring.orm.model.Participant.serviceTypes 的设置者
在 org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:61)
在 org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:649)
在 org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:205)
在 org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:4711)
在 org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:183)
在 org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:125)
在 org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:1152)
在 org.hibernate.loader.Loader.processResultSet(Loader.java:1011)
在 org.hibernate.loader.Loader.doQuery(Loader.java:949)
在 org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
在 org.hibernate.loader.Loader.doList(Loader.java:2692)
在 org.hibernate.loader.Loader.doList(Loader.java:2675)
在 org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2507)
在 org.hibernate.loader.Loader.list(Loader.java:2502)
在 org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)
在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:392)
在 org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
在 org.hibernate.internal.SessionImpl.list(SessionImpl.java:1490)
在 org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1445)
在 org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1414)
……还有 11 个
引起:java.lang.IllegalArgumentException:无法将 java.util.List 字段 com.mycompany.app.spring.orm.model.Participant.serviceTypes 设置为 com.mycompany.app.spring.orm.model.ServiceType
在 sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
在 sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
在 sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
在 java.lang.reflect.Field.set(Field.java:764)
在 org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:41)
... 30 多个
有什么解决办法吗?
我是 QueryDSL 的新手,但为什么要查询 service_types?
那么自连接应该如何工作?
在这种情况下肯定没有定义任何关系。
JPQL 是基于属性的,因此如果没有关系(定义为属性),那么您就不能真正随意地加入它。
除非你去JpaSqlQuery,在那里你可以使用更多的SQL。