일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- github clone
- visualstudio code
- PHPStorm
- 데이터베이스
- DataGrip
- cmd
- Python
- import data
- github token
- database
- 에러
- 클론
- OrCAD 다운로드
- MySQL
- console창
- csv
- 파이썬
- Visual Studio Code
- error
- clone
- vscode
- run sql script
- php
- 단축키
- error 해결
- localhost
- 오류
- 깃 토큰
- 따옴표 삭제
- jupyter
Archives
- Today
- Total
개발 노트
10/28 JPA 연관관계, oBootJpa02 프로젝트 본문
프로젝트 기반 JAVA 응용 SW개발 : 22.07.19~23.01.20/Spring
10/28 JPA 연관관계, oBootJpa02 프로젝트
hayoung.dev 2022. 11. 16. 18:27JPA 연관관계
단 웬만하면 다대다는 쓰지 않는다.
일대다도 쓰지 않는다.
(다로 끝나는 건 안쓴다고 생각하면 된다.)
다대일 또는 일대일을 쓴다.
즉시 로딩, 지연 로딩은 jpa 성능을 좋게 하는데에 중요함.
[oBootJpa02]
java > com.oracle.oBootJpa02(package)에 controller, domain, repository, service (package) 생성
resource > static > index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="/members/new">Member 신규 생성</a><p>
<a href="/members">Member List 조회</a>
</body>
</html>
controller > MemberController.java (class)
package com.oracle.oBootJpa02.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.oracle.oBootJpa02.domain.Member;
import com.oracle.oBootJpa02.service.MemberService;
@Controller
public class MemberController {
private static final Logger logger = LoggerFactory.getLogger(MemberController.class);
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@GetMapping(value="/members/new")
public String createForm() {
System.out.println("MemberController /members/new start.. ");
return "members/createMemberForm";
}
@PostMapping(value = "/memberSave")
public String memberSave(Member member) {
System.out.println("MemberController create start.. ");
System.out.println("member.getTeamname()->"+member.getTeam());
System.out.println("member.getName()->"+member.getName());
memberService.memberSave(member);
return "redirect:/";
}
@GetMapping(value = "/members")
public String listMember(Model model) {
List<Member> memberList = memberService.getListAllMember();
System.out.println("memberList.get(0).getName()->"+memberList.get(0).getName());
System.out.println("memberList.get(0).getTeam().getName()->"+memberList.get(0).getTeam().getName());
// System.out.println("memberList.get(1).getName()->"+memberList.get(1).getName());
// System.out.println("memberList.get(1).getTeam().getName()->"+memberList.get(1).getTeam().getName());
model.addAttribute("memberList", memberList);
return "members/memberList";
}
@GetMapping(value = "/memberModifyForm")
public String memberModify(Long id, Model model) {
System.out.println("MemberController memberModify id->"+id);
Member member = memberService.findByMember(id);
System.out.println("member.get().getId()->"+member.getId());
System.out.println("member.get().getName()->"+member.getName());
System.out.println("member.get().getTeam().getName()->"+member.getTeam().getName());
model.addAttribute("member", member);
return "members/memberModify";
}
/* post방식 */
@PostMapping(value = "/members/memberUpdate")
public String memberUpdate(Member member, Model model) {
System.out.println("MemberController memberUpdate id->"+member.getId());
System.out.println("MemberController memberUpdate member.getName->"+member.getName());
System.out.println("MemberController memberUpdate member.getTeamname->"+member.getTeamname());
memberService.memberUpdate(member);
return "redirect:/members";
}
}
service > MemberService.java (class)
package com.oracle.oBootJpa02.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.oracle.oBootJpa02.domain.Member;
import com.oracle.oBootJpa02.repository.MemberRepository;
@Service
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
public Member memberSave(Member member) {
System.out.println("MemberService join member.getName()->"+member.getName());
memberRepository.memberSave(member);
return member;
}
// 전체회원 조회
public List<Member> getListAllMember() {
List<Member> listMember = memberRepository.findAll();
System.out.println("MemberService getListAllMember listMember.size()->"+listMember.size());
return listMember;
}
public Member findByMember(Long memberId) {
Member member1 = memberRepository.findByMember(memberId);
System.out.println("MemberService findByMember member1.getId()->"+member1.getId());
System.out.println("MemberService findByMember member1.getName()->"+member1.getName());
System.out.println("MemberService findByMember member1.getTeam().getName()->"
+member1.getTeam().getName());
return member1;
}
public void memberUpdate(Member member) {
System.out.println("MemberService memberUpdate member.getName()->"+member.getName());
System.out.println("MemberService memberUpdate member.getTeamname()->"+member.getTeamname());
memberRepository.updateByMember(member);
return;
}
}
repository > MemberRepository.java (interface)
package com.oracle.oBootJpa02.repository;
import java.util.List;
import com.oracle.oBootJpa02.domain.Member;
public interface MemberRepository {
Member memberSave(Member member);
List<Member> findAll();
Member findByMember(Long memberId);
int updateByMember(Member member);
}
repository > JpaMemberRepository (class, MemberRepository 인터페이스 상속)
package com.oracle.oBootJpa02.repository;
import java.util.List;
import javax.persistence.EntityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.oracle.oBootJpa02.domain.Member;
import com.oracle.oBootJpa02.domain.Team;
@Repository
public class JpaMemberRepository implements MemberRepository {
private final EntityManager em;
@Autowired
public JpaMemberRepository(EntityManager em) {
this.em = em;
}
@Override
public Member memberSave(Member member) {
// 팀 (DB에) 저장
Team team = new Team();
team.setName(member.getTeamname());
em.persist(team);
//회원 저장
member.setTeam(team);
em.persist(member); /* DB에 저장 */
return member;
}
@Override
public List<Member> findAll() {
List<Member> memberList = em.createQuery("select m from Member m", Member.class)
.getResultList();
return memberList;
}
@Override
public Member findByMember(Long memberId) {
// Entity PK
Member member = em.find(Member.class, memberId);
return member;
}
@Override
public int updateByMember(Member member) {
int result = 0;
System.out.println("JpaMemberRepository updateByMember member.getId()->"+member.getId());
Member member3 = em.find(Member.class, member.getId());
if( member3 != null) {
// 팀 저장
System.out.println("JpaMemberRepository updateByMember member.getTeamid()->"
+member.getTeamid());
Team team = em.find(Team.class, member.getTeamid());
if (team != null) {
System.out.println("JpaMemberRepository updateByMember member.getTeamname()->"+
member.getTeamname());
team.setName(member.getTeamname());
em.persist(team);
}
//회원 저장
System.out.println("JpaMemberRepository updateByMember member.getName()->"+member.getName());
member3.setTeam(team); // 단방향 연관관계 설정, 참조 저장
member3.setName(member.getName()); // 단방향 연관관계 설정, 참조 저장
em.persist(member3);
result = 1; /* 성공하면 결과값을 1로 보내준다. */
} else {
result = 0; /* 성공하면 결과값을 0로 보내준다. */
System.out.println("JpaMemberRepository updateByMember No Exist..");
}
return result;
}
}
domain > Member.java
package com.oracle.oBootJpa02.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import lombok.Data;
//Entity
//table->member2
//Long id (PK)
//String name
//Long sal
//Getter/Setter/ToString
@Entity
@Data
@SequenceGenerator(name = "member_seq_gen", // 객체 SEQ
sequenceName = "member_seq_generator", // DB SEQ
initialValue = 1, //보통 1로 설정
allocationSize = 1 //보통 1로 설정
)
@Table(name = "member2")
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "member_seq_gen"
)
@Column(name = "member_id" , precision = 10)
private Long id; /* pk이거나 시퀸스 사용 시에는 long 타입을 권장 */
@Column(name = "username" , length = 50)
private String name ;
private Long sal;
// 관계 설정
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
// 실제Column X --> Buffer용도
@Transient
private Long teamid;
@Transient
private String teamname;
}
domain > Team.java
package com.oracle.oBootJpa02.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import lombok.Data;
//Entity
//table->Team
//Long team_id (PK)
//String name(column-->teamname)
//Getter/Setter/ToString
// 1) 객체 SEQ team_seq_gen(PK에 할당)
// 2) DB SEQ team_seq_generator
@Entity
@Data
@SequenceGenerator(
name = "team_seq_gen",
sequenceName = "team_seq_generator", //매핑할 DB 시퀀스 이름
initialValue = 1,
allocationSize = 1
)
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "team_seq_gen")
private Long team_id;
@Column(name = "teamname")
private String name;
}
resources > application.properties
server.port=8384
# Oracle Connect
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=scottjpa
spring.datasource.password=tiger
# Jpa Setting
spring.jpa.show-sql=true
# *** Operation --> create / none
spring.jpa.hibernate.ddl-auto=create
resources > createMemberForm.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>JPA 회원 등록2</h1>
<div class="container">
<form action="/memberSave" method="post">
<!-- ID : <input type="text" id="id" name="id" required="required"> -->
회원이름 : <input type="text" id="name" name="name" placeholder="회원이름을 입력하세요"><p>
팀 이름 : <input type="text" id="name" name="teamname" placeholder="팀이름을 입력하세요">
<button type="submit">등록</button>
</form>
</div> <!-- /container -->
</body>
</html>
resources > memberList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<div class="container">
<div>
<table border="1">
<thead>
<tr>
<th>No</th>
<th>회원이름</th>
<th>팀 이름</th>
</tr>
</thead>
<tbody>
<tr th:each="member : ${memberList}">
<td th:text="${member.id}"></td>
<!-- html > 검사로 확인해보면 예를들어 첫번째 값은 /memberModifyForm?id=1 이다. -->
<td><a th:href="@{/memberModifyForm(id=${member.id})}" th:text="${member.name}"></a></td>
<td th:text="${member.team.name}"></td>
</tr>
</tbody>
</table>
</div>
</div> <!-- /container -->
</body>
</html>
resources > memberModify.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>JPA2 회원 수정</h1>
<div class="container">
<!-- 읽을때는 get, 저장할 땐 post 방식을 사용한다. -->
<form action="/members/memberUpdate" method="post">
<!-- ID : <input type="text" id="id" name="id" required="required"> -->
<input type="hidden" name="id" th:value="${member.id}">
<input type="hidden" name="teamid" th:value="${member.team.team_id}">
회원이름 : <input type="text" id="name" name="name" th:value="${member.name}" ><p>
팀 이름 : <input type="text" id="name" name="teamname" th:value="${member.team.name}"><p>
<button type="submit">회원 수정 처리</button>
</form>
</div> <!-- /container -->
</body>
</html>
출력 결과
객체를 선언해주면 거기에 맵핑할 테이블의 컬럼 명을 자동으로 설정해준다. (team_id가 자동으로 생겼다.)
fk로 연관돼있다.
member에 관한 모든 정보를 가져와서 돌리기 때문에 성능이 좋아진다.
반응형