SpringBoot
## Student
@Data
@Entity
@ToString(exclude="enrolList")
@Table(name="student0809")
public class Student {
@Id
@Column(name="s_sno")
private String sno;
private String sname;
private String year;
@Column(name="s_dept")
private String dept;
@OneToMany(mappedBy="student",fetch=FetchType.EAGER,cascade=CascadeType.ALL)
private List<Enrol> enrolList = new ArrayList<Enrol>();
}
## enrol
@Data
@Entity
@ToString(exclude="student")
@Table(name="enrol0809")
public class Enrol {
@Id @GeneratedValue
private Long idx;
@Transient
private String sno;
@Transient
private String cno;
private String grade;
private String middleTest;
private String finalTest;
@ManyToOne
@JoinColumn(name="s_sno", nullable = false)
private Student student;
}
조인하여 테이블을 조회하는 내용이다.
가장 중요한 설정은 @OneToMany의 mappedBy 속성이다. 양방향 연관관계에서 연관관계의 주인을 지정할때 사용한다.
주의사항
juit으로 조회 테스트를 진행할때 @ToString 이 양방향참조에서 상호 호출을 하게되면 StackOverflowError가 발생한다.
이때에는 @ToString 어노테이션에 exclude속성을 추가하여 상호 호출 고리를 끊어야 한다.
앞서 @OneToMany 에서 주인테이블을 설정하고 @joinColumn을 통해 조인한 태용에서 html 파일의 view로 표현되는 과정을 코드로 봐보자
## 공통 칼럼을 VO로 잡는 방법
package com.jpaProject.k6.university;
import lombok.Data;
@Data
public class StudentEnrolVO {
private Long idx;
private String sno;
private String sname;
private String year;
private String dept;
private String grade;
private String middleTest;
private String finalTest;
}
공통 칼럼을 VO 로 잡아주게 되면 servicce와 List는 아래와 같이 동작하면 view에서 확인 할 수있다.
## service
package com.jpaProject.k6.university;
import java.util.List;
public interface UniversityService {
List<StudentEnrolVO> joinList();
}
# service Impl
package com.jpaProject.k6.university;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UniversityServiceImpl implements UniversityService{
@Autowired
EnrolRepository enrolRepo;
@Override
public List<StudentEnrolVO> joinList() {
List<StudentEnrolVO> join = new ArrayList<StudentEnrolVO>();
List<Enrol> li = (List<Enrol>) enrolRepo.findAll();
for(Enrol m : li) {
StudentEnrolVO vo = new StudentEnrolVO();
vo.setIdx(m.getIdx());
vo.setSno(m.getStudent().getSno());
vo.setSname(m.getStudent().getSname());
vo.setYear(m.getStudent().getYear());
vo.setDept(m.getStudent().getYear());
vo.setGrade(m.getGrade());
vo.setMiddleTest(m.getMiddleTest());
vo.setFinalTest(m.getFinalTest());
join.add(vo);
}
return join;
}
}
위와같이 배열의 값으로 초기화 한 객체에 조인된 Enrol의 필드값을 넣어주고 주인 테이블의 필드값도 호출하여 각 레코드의 값을 구할 수 있다.
이와 마찬가지로 VO를따로 생성하지 않고 Join된 Enrol 클래스를 가지고 바로 레코드를 출력할 수도 있다.
## Service
package com.jpaProject.k6.university;
import java.util.List;
public interface UniversityService {
List<Enrol> enrolJoinList();
}
## ServiceImpl
package com.jpaProject.k6.university;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UniversityServiceImpl implements UniversityService{
@Autowired
EnrolRepository enrolRepo;
@Override
public List<Enrol> enrolJoinList() {
return (List<Enrol>) enrolRepo.findAll();
}
}
VO를 생성하여 가져오는 내용의 코드보다는 훨씬 간결하게 표현할 수 있다.
하지만 따로 연산이나 추가적인 기능들을 사용하게 된다면 새로운 VO로 객체를 생성하여 사용하는것을 추천한다.
또 VO를 만들지 않고 생성한 레코드의 값을 VO 에서 출력하기 위해선 HTML 파일에서 해당 주인 테이블의 레코드 값을 참조하여 불러와야 한다.
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<section>
<br><br>
<div align=center>
<h1> 목록보기 </h1>
<table border=1 width="650" height="200">
<tr align="center">
<th th:text="idx"/>
<th th:text="sno"/>
<th th:text="sname"/>
<th th:text="year"/>
<th th:text="dept"/>
<th th:text="grade"/>
<th th:text="middleTest"/>
<th th:text="finalTest"/>
</tr>
<tr th:each="m : ${li} ">
<td align="center" th:text="${m.idx}" />
<td align="center" th:text="${m.getStudent().sno}"/>
<td align="center" th:text="${m.getStudent().sname}" />
<td align="center" th:text="${m.getStudent().year}" />
<td align="center" th:text="${m.getStudent().dept}" />
<td align="center" th:text="${m.grade}" />
<td align="center" th:text="${m.middleTest}" />
<td align="center" th:text="${m.finalTest}" />
</tr>
</table>
</div>
</section>
</body>
</html>
List<Enrol> findByStudent_SnameContainingOrStudent_SnameContaining(String str1, String str2);
엔티티값을 받아와서 검색하는 방법
Repository 인터페이스에서 쿼리문을 작성할때
다른 테이블명_칼럼명을 적용하면 다른 테이블의 값을 가져와서 사용할 수 있다.
훌륭한 글 감사드립니다.