์๋ ํ์ธ์,
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(์ด๋ฆ = "์ฐธ๊ฐ์")
๊ณต๊ฐ ์์
์ฐธ๊ฐ์ {
@OneToOne(์บ์ค์ผ์ด๋ = CascadeType.DETACH, ๊ฐ์ ธ์ค๊ธฐ = FetchType.EAGER, targetEntity = ServiceType.class)
@JoinTable(์ด๋ฆ = "PARTICIPANT_SERVICES", joinColumns = @JoinColumn(์ด๋ฆ = "PARTICIPANT_ID", referencedColumnName = "PARTICIPANT_ID"), inverseJoinColumns = @JoinColumn(์ด๋ฆ = "SERVICE_TYPE_ID", referencedColumnName = "SERVICE_TYPE_ID"))
๊ฐ์ธ ๋ชฉ๋ก
@OneToMany(mappedBy = "participant")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
private List<ParticipantRegionCountry> participantRegionCountries;
๊ฒํฐ/์ธํฐ
}
@์ค์ฌ
@Table(์ด๋ฆ = "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();
์์ธ:
์ต๋ ์ ์ ๋ชจ๋ : CONTACT_NAME5_6_๋ฟ๋ง participan0_.CONTACT_PHONE๋ก PARTICIPANT_ID1_6_, BUSINESS_NAME2_6_ ๊ฐ์ participan0_.BUSINESS_NAME, BUSINESS_TYPE_ID9_6_ ๊ฐ์ participan0_.BUSINESS_TYPE_ID, CITY_ID10_6_ ๊ฐ์ participan0_.CITY_ID, CONTACT_ADDRESS3_6_ ๊ฐ์ participan0_.CONTACT_ADDRESS, CONTACT_EMAIL4_6_ ๊ฐ์ participan0_.CONTACT_EMAIL, participan0_.CONTACT_NAME๋ก ๊ตฌ๋ถ participan0_.PARTICIPANT_ID์ ์ ํ CONTACT_PHONE6_6_, participan0_.COUNTRY_ID REGION_ID17_6_ ๊ฐ์ 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๋ก์ participan0_.USER_NAME์ USER_NAME8_6_์ผ๋ก, participan0_1_.SERVICE_TYPE_ID๋ฅผ SERVICE_TYPE_ID1_12_๋ก PARTICIPANT participan0_ ์ผ์ชฝ ์ธ๋ถ ์กฐ์ธ 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 ๋ด๋ถ ์กฐ์ธ ๋ฐ ((? , ?)์ ์ฐธ๊ฐ์2_.REGION_ID)
์ต๋ ์ ์ ๋ชจ๋: servicetyp0_.SERVICE_TYPE_ID๋ฅผ SERVICE_TYPE_ID1_18_0_๋ก ์ ํํ๊ณ servicetyp0_.SERVICE_TYPE_NAME์ SERVICE_TYPE_NAME2_18_0_์ผ๋ก SERVICE_TYPE servicetyp0_์์ ์ ํํฉ๋๋ค. ์ฌ๊ธฐ์ 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์ setter
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(๋ค์ดํฐ๋ธ ๋ฉ์๋)์์
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์ setter
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์ ์์ฑ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ฏ๋ก ์์ฑ์ผ๋ก ์ ์๋ ๊ด๊ณ๊ฐ ์์ผ๋ฉด ์ค์ ๋ก ์์๋ก ๊ฒฐํฉํ ์ ์์ต๋๋ค.
๋ ๋ง์ SQL์ ์ฌ์ฉํ ์ ์๋ JpaSqlQuery๋ก ์ด๋ํ์ง ์๋ ํ.