104일차_SpringBoot

서창민·2023년 8월 9일
0

SpringBoot

목록 보기
8/13
post-thumbnail

23.08.09 104일차

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속성을 추가하여 상호 호출 고리를 끊어야 한다.

  • join 테이블의 view 표현

앞서 @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 인터페이스에서 쿼리문을 작성할때

다른 테이블명_칼럼명을 적용하면 다른 테이블의 값을 가져와서 사용할 수 있다.

profile
Back-end Developer Preparation Students

1개의 댓글

comment-user-thumbnail
2023년 8월 9일

훌륭한 글 감사드립니다.

답글 달기