스프링 데이터 JPA에는 다중 테이블 쿼리에 대한 두 가지 구현 방법이 있습니다. 첫 번째는 최대 절전 모드 캐스케이드 쿼리를 사용하여 구현하는 것이며, 두 번째는 연결된 테이블 쿼리 후 결과를 수신하기 위해 결과 세트 인터페이스를 작성하는 것입니다. 두 번째 방법은 다음과 같습니다.
1. 일대일 매핑
엔티티 userInfo : 사용자.
엔티티 주소 : 홈 주소.
여기서, 일대일 협회는 외국 키 방법을 통해 달성됩니다 (한 엔티티는 외국 키를 통해 다른 엔티티의 주요 키와 관련이 있습니다).
엔티티 클래스
1. 엔티티 클래스 userInfo.java
package com.johnfnash.learn.domain; import java.io.serializable; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.table; 클래스 userInfo는 시리얼화할 수있는 {private static final long serialversionuid = 8283950216116626180L; @id @generatedValue (전략 = GenerationType.Identity) private long userId; 개인 문자열 이름; 사적인 int 연령; 개인 문자열 섹스; 개인 문자열 이메일; // 주소와의 연관 개인 긴 주소 지체; public userInfo () {super (); } public userInfo (문자열 이름, int 연령, 문자열 섹스, 문자열 이메일, long jusdricid) {super (); this.name = 이름; this.age = age; this.sex = 섹스; this.email = 이메일; this.addressid = addressID; } // getter, setter @override public String toString () {return string.format ( "userInfo [userInfo [userInfo [userInd =%d, name =%s, age =%s, sex =%s, email =%s]", userId, 이름, 나이, 섹스, 이메일); }} 2. 엔티티 클래스 주소. 자바
패키지 com.johnfnash.learn.domain; import javax.persistence.entity; import javax.persistence.generatevalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.table;@endity @id (tb_address ") @generatedValue (전략 = GenerationType.identity) 개인 긴 주소 지체; 개인 문자열 영역 코드; 개인 문자열 국가; 개인 문자열 주; 개인 문자열 도시; 개인 문자열 영역; 개인 문자열 세부 사항 Address; 공개 주소 () {super (); } 공개 주소 (문자열 영역 코드, 문자열 국가, 문자열 지방, 문자열 도시, 문자열 영역, String detailAddress) {super (); this.areacode = areaCode; this.country = 국가; this.province = 지방; this.city = 도시; this.area = 영역; this.detailAddress = detailAddress; } // getter, setter @override public string toString () {return "address"addressID = " + wass }} 다오 레이어
1. userinforepository.java
package com.johnfnash.learn.repository; import java.util.list; import org.springframework.data.jpa.repository.jparepository; import org.sprameframework.data.jpa.repository.query; import com.johnfnash.learn.learin.userinfo; com.johnfnash.learn.domain.viewinfo; public interface userinforepository jparepository <userInfo, long> {@Query = "select com.johnfnash.learn.domain.viewInfo (u, a) userInfo u, a aaddressid = aaddressid")). findViewInfo ();} 참고 : ViewInfo 클래스는 다중 테이블 쿼리 결과 세트를 수신하는 데 사용됩니다 (New + Full Class Name 생성자 사용)
코드는 다음과 같습니다.
package com.johnfnash.learn.domain; import java.io.serializable; public class viewinfo serializable {private static final long serialversionuid = -6347911007178390219L; 개인 userinfo userinfo; 개인 주소 주소; public viewInfo () {} public viewInfo (userInfo userInfo) {주소 주소 = 새 주소 (); this.userinfo = userInfo; address = 주소; } public viewInfo (주소 주소) {userInfo userInfo = new userInfo (); this.userinfo = userInfo; address = 주소; } public viewInfo (userInfo userInfo, 주소 주소) {this.userInfo = userInfo; address = 주소; } // getter, setter} 2. 주소 예로. 자바
package com.johnfnash.learn.repository; import org.springframework.data.jpa.repository.jparepository; import com.johnfnash.learn.domain.address; public interface addressRepository 확장 jparepository <address, long> {}. 테스트 코드
package com.johnfnash.learn; import java.util.list; import org.junit.after; import org.junit.before; import org.junit.test; import org.junit.runner.runwith; import org.springframework.beans.annotation.Autowize; org.springframework.boot.test.context.springboottest; import org.springframework.test.context.junit4.springrunner; import com.johnfnash.learn.comain.address; import com.johnfnash.learn.comain.userinfo; import com.johnfnash.learn.domain.viewinfo; import com.johnfnash.learn.repository.addressrepository; import com.johnfnash.learn.repository.userinforepository; @runwith (springrunner.class) @springboottpublic classeStests {@autiredouseouseouseouseouseouseousinfortoritation userinforepository; @autowired Private AddressRepository AddressRepository; @public void init () {주소 addr1 = 새 주소 ( "027", "cn", "hubei", "wuhan", "wuchang", "123 street"); 주소 addr2 = 새 주소 ( "023", "CN", "Chongqing", "Chongqing", "Yubei", "123 Road"); addressRepository.save (addr1); addressRepository.save (addr2); userInfo user1 = new userInfo ( "zs", 21, "male", "[email protected]", addr1.getAddressId ()); userInfo user2 = new userInfo ( "ww", 25, "male", "[email protected]", addr2.getAddressId ()); userinforepository.save (user1); userinforepository.save (user2); } @after public void deleteall () {userinforepository.deleteall (); addressRepository.deleteAll (); } @test public void testQuery () {list <viewInfo> viewInfos = userInforepository.findViewInfo (); for (viewInfo viewInfo : viewInfos) {system.out.println (viewInfo.getUserInfo ()); System.out.println (viewInfo.getAddress ()); }}}쿼리 관련 SQL은 다음과 같습니다.
Hibernate : col_0_0_, col_0_0_, asser1_.address_id as tb_user userinfo0_ cross join tb_address address1_ as userinfo0_.address_id = address1_.address_idhibernate : userinfo0_.user_.id as user_id1_4. userInfo0_.address_id as address_2_4_0_, userInfo0_.age as Age3_4_0_, userInfo0_.email as aven userInfo0_.user_id =? hibernate : 주소 0_.address_id as address_1_3_0_, ardeper0_.area as area2_3_0_, ardept0_.area_code as area_cod3_3_0_, city4_3_0_, asdress0_0_, countres0_0_. detail_a6_3_0_, tb_aaddress jand userInfo0_.email as aven4_4_0_, userInfo0_.name as name5_4_0_, userInfo0_.sex as sex6_4_0_ as tb_user userInfo0_ here userInfo0_.user_id =? hibernate : jodce0_.address_id as _1_30_, as as as as as ad AREA2_3_0_, arear_cod3_3_0_, astress0_.city as city4_3_0_, asserd. address0_.address_id =? hibernate : userinfo0_.user_id as user_id1_4_, userinfo0_.address_id as jands_2_4_, userInfo0_.age as age3_4_, userInfo0_.email, userInfo0_.name As Name5_.name as as resourInfo0_.name을 선택하십시오. tb_user userinfo0_hibernate의 sex6_4_ : address0_.address_id as address_1_3_, ardess_1_3_, area2_3_, ardeper0_.area_code as area_cod3_3_, ardesent0_.city As City5_3_, Ass detail_a6_3_, address0_.province as as province7_3_에서 tb_address address0_
쿼리 결과는 다음과 같습니다.
userInfo [userId = 1, name = zs, age = 21, sex = male, [email protected]]
주소 [addressID = 1, AreaCode = 027, Country = CN, Province = Hubei, City = Wuhan, Area = Wuchang, DetailAddress = 123 Street]
userInfo [userId = 2, name = ww, age = 25, sex = male, [email protected]]
주소 [addressID = 2, AreaCode = 023, Country = CN, 지방 = chongqing, city = chongqing, area = yubei, detailAddress = 123 Road]
2. 다수의 매핑
엔티티 저자 : 저자.
엔티티 북 : 책
여기서는 협회 테이블을 통해 다수의 협회가 달성됩니다.
엔티티 클래스
엔티티 클래스 : author.java
package com.johnfnash.learn.domain; import java.io.serializable; import javax.persistence.entity; import javax.persistence.generatedvalue; import javax.persistence.id; @entitypublic class exaurtements serializable {private static final long serialversionuid = 1227555555585566; @id @generatedvalue 개인 정수 ID; 개인 문자열 이름; 공개 저자 () {super (); } 공개 저자 (문자열 이름) {super (); this.name = 이름; } // getter, setter @override public String toString () {return string.format ( "author [id =%s, name =%s]", id, name); }} book.java 엔티티 클래스
package com.johnfnash.learn.domain; import java.io.serializable; import javax.persistence.entity; import javax.persistence.generatedValue; import javax.persistence.id; @entityPublic 클래스 책상 Serializable {private static final long serialionuid = -2470510857424220408L; @id @generatedvalue 개인 정수 ID; 개인 문자열 이름; public book () {super (); } public book (문자열 이름) {super (); this.name = 이름; } // getter, setter @override public String toString () {return string.format ( "Book [id =%s, name =%s]", id, name); }} 엔티티 클래스 Bookauthor.java
package com.johnfnash.learn.domain; import javax.persistence.entity; import javax.persistence.id; import javax.persistence.idclass; import javax.persistence.table;@entity@idclass (bookauthorpk.class) @table (public _ public inste {@id private inste; @id 개인 정수 authorid; public bookauthor () {super (); } public bookauthor (정수 Bookid, Integer Authorid) {super (); this.bookid = bookid; this.authorid = authorid; } // getter, setter}참고 : @idclass 주석을 사용하여 Union 기본 키 클래스를 지정하여 엔티티 클래스의 여러 속성을 매핑하십시오. 이 조인트 1 차 키 클래스의 코드는 다음과 같습니다.
package com.johnfnash.learn.domain; import java.io.serializable; public class bookauthorpk는 직렬화 가능한 {private static final long serialversionuid = -1158141803682305656L; 개인 정수 Bookid; 개인 정수 authorid; 공개 정수 getBookId () {return bookid; } public void setBookId (정수 Bookid) {this.bookid = bookid; } public Integer getauthorid () {return authorid; } public void setauthorid (정수 authorid) {this.authorid = authorid; }} 다오 레이어
BookRepository.java
package com.johnfnash.learn.repository; import java.util.list; import org.springframework.data.jpa.repository.jparepository; import org.springframework.data.jpa.repository.qupositor.qupository. import interface <proverpositorate johnfosatory, gublend johnfositorate jporitory; integer> {@Query (NativeQuery = true, value = "B.Id, B.name, Group_Concat (a.name)을 책 B, 저자 A, Book_Author BA" + "a, BOK_AUTHOR BA" + "where B.Id = ba.book_id 및 b.name like? 메모:
1) 여기에서, aviretquery = true 기본 SQL은 쿼리에 사용된다고 지정합니다 (개인적으로 복잡한 쿼리에 네이티브 SQL을 사용하는 것이 낫다고 생각합니다.
2) 여기에서 MySQL의 내장 기능 Group_Concat은 행으로 변환하는 데 사용되며 HQL은 직접 인식 할 수 없습니다. 원인 : org.hibernate.queryexception : 노드의 데이터 유형 없음 : org.hibernate.hql.internal.ast.tree.methodnode 오류가 발생할 수 있습니다.
jparepository.java
package com.johnfnash.learn.repository; import org.springframework.data.jpa.repository.jparepository; import com.johnfnash.learn.domain.author; public interface awortrepository는 jparepository <저자, integer> {{}를 확장합니다. Bookauthorrepository.java
package com.johnfnash.learn.repository; import org.springframework.data.jpa.repository.jparepository; import com.johnfnash.learn.domain.bookauthor; public interface bookauthorrepository는 jparepository <bookauthor, intger> {{}를 확장합니다. 테스트 코드
package com.johnfnash.learn; import static org.assert.assertequals; import java.util.list; import org.junit.after; import org.junit.before; import org.junit.test; import org.junit.runner.runwith; import; org.springframework.bean.beans.annotation.autowired; import org.springframework.test.test.springboottest; import org.springframework.test.context.junit4.springrunner; import com.johnfnash.learn.learain.author; import; com.johnfnash.learn.domain.book; import com.johnfnash.learn.comain.bookauthor; import com.johnfnash.learn.repository.authorrepository; import com.johnfnash.learn.bookauthorrepository; import com.johnfnash.learn.repository.bookRepository; @runwith (springrunner.class) @springboottestpublic class bookrepositoryTests {@autowired private bookrepository bookrepository; @autowired private ortherrepository 저자 직장; @autowired 개인 Bookauthorrepository Bookauthorrepository; @public void init () {저자 루이스 = 새로운 저자 ( "루이스"); 저자 Mark = 새로운 저자 ( "Mark"); 저자 Peter = New Author ( "Peter"); 저자 직원 .Save (Lewis); authorrepository.save (Mark); 저자 리포지토리 .SAVE (Peter); Book Spring = New Book ( "Spring In Action"); Book SpringBoot = New Book ( "Spring Boot in Action"); BookRepository.save (스프링); BookRepository.save (SpringBoot); BookAuthorRepository.save (New Bookauthor (Spring.getId (), Lewis.getId ())); BookAuthorRepository.save (New Bookauthor (Spring.getId (), Mark.getId ())); BookauthorRepository.save (새 Bookauthor (springboot.getid (), mark.getid ())); BookauthorRepository.save (새 Bookauthor (springboot.getid (), peter.getid ())); } @after public void deleteall () {bookauthorrepository.deleteall (); BookRepository.deleteall (); authorrepository.deleteall (); } @test public void findall () {AsserTequals (BookRepository.findall (). size (), 2); AsserTequals (asurethrepository.findall (). size (), 3); List <Object []> books = BookRepository.FindByNameCantaining ( "Spring%"); for (object [] book : books) {for (Object : Book) {System.out.print (Object + ","); } system.out.println (); }}}findall 메소드를 실행 한 후 쿼리의 관련 SQL은 다음과 같습니다.
Hibernate : B.ID, B.Name, Group_Concat (A.Name)을 책 B, 저자 A, BOOK_AUTHOR BA B.ID = BA.BOOK_ID 및 A.ID = BA.AUTHOR_ID 및 B.name Like에서 선택하십시오. B.Id, B.name의 그룹
출력 결과는 다음과 같습니다.
3652, Spring in Action, Lewis, Mark,
3653, Spring Boot in Action, Mark, Peter,
위는이 기사의 모든 내용입니다. 모든 사람의 학습에 도움이되기를 바랍니다. 모든 사람이 wulin.com을 더 지원하기를 바랍니다.