오늘의 취지는 JPA 배우기 앞서 JPA의 흐름을 흉내 내보는 코드를 작성해보기로 하였음..
위의 그림은유저와 취미의 중간테이블을 두고 다대다 관계를 형성한 설계도다.
JPA 를 사용하면 손 쉽게 관계를 맺고 데이터를 사용할 수 있지만 JPA를 사용하지 않고 이와 같은 기능이 될 수 있게 구현해보자..
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member {
private Integer id;
private String name;
private Integer age;
// 취미가 들어갈 default list 생성..
private List<MemberHobby> hobbies = new ArrayList<>();
// Member class 생성자가 만들어질때.. id 는 Auto Increment 대용 생성..
// 나머지 필드 주입.. hobbies 는 default list 생성..
public Member(String name, Integer age) {
this.id = Store.memberIndex++;
this.name = name;
this.age = age;
this.hobbies = new ArrayList<>();
}
}
@NoArgsConstructor
@Getter
public class Hobby {
private Integer id;
private String name;
// 멤버들이 들어갈 default list 생성..
private List<MemberHobby> members;
// 위의 Member 와 같음..
public Hobby(Integer id, String name, Member member) {
if(id == null) this.id = Store.hobbyIndex++;
else this.id = id;
this.name = name;
this.members = new ArrayList<>();
}
}
public class Store {
public static List<Member> members = new ArrayList<>();
public static Integer memberIndex = 0;
public static List<Hobby> hobbies = new ArrayList<>();
public static Integer hobbyIndex = 0;
}
@Getter
public class MemberHobby {
// 중간테이블 이니 member 와 hobby 가 들어갈 변수 선언..
private Member member;
private Hobby hobby;
// 생성될 때.. 필드에 주입 해주고..
// 해당하는 member 의 취미리스트에 들어온 변수를 추가 하고..
// 해당하는 hobby 의 멤버리스트에 들어온 변수를 추가 함..
public MemberHobby(Member member, Hobby hobby) {
this.member = member;
this.hobby = hobby;
member.getHobbies().add(this);
hobby.getMembers().add(this);
}
}
// Controller
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
// 받아온 값을 MemberRequest mapping 후..
//record 에서 Member 형식으로 생성.. 후 서비스로 넘김..
public void save(@RequestBody MemberRequest member){
memberService.save(member.toEntity());
}
// Service
// 멤버 리스트에 추가..
public void save(Member member){
Store.members.add(member);
}
// MemberRequest
public record MemberRequest(String name, Integer age) {
public Member toEntity(){
return new Member(name, age);
}
}
// Controller
@GetMapping
public List<MemberResponse> findAll(){
return memberService.findAll();
}
// Service
// 현재 등록되어 있는 멤버 들을 순환하면서..
// 해당 되는 멤버들을 MemberResponse 형식으로 만들어서 리스트 생성해서 출력..
public List<MemberResponse> findAll(){
return Store.members
.stream()
.map(MemberResponse::new)
.toList();
}
// MemberResponse
@Getter
public class MemberResponse {
// 멤버필드 그대로 사용..
private Integer id;
private String name;
private Integer age;
private List<HobbyDto> hobbies = new ArrayList<>();
// 생성될 때 Member 를 받고.. 필드에 주입..
// 다만.. hobbies 는 순환 참조가 이루어지기 때문에..
// 처리를 해주자..
public MemberResponse(Member member){
this.id = member.getId();
this.age = member.getAge();
this.name = member.getName();
// 생성될 때 넣어준 멤버의 Hobbies를 순환하면서..
// 각각의 hobby를 가져오고..
// 가져온 hobby 를 HobbyDto 형식으로 재 생성해서..
// 리스트로 생성..
this.hobbies = member.getHobbies()
.stream()
.map(MemberHobby -> MemberHobby.getHobby())
.map(hobby -> new HobbyDto(hobby))
.toList();
}
@Getter
@AllArgsConstructor
@NoArgsConstructor
class HobbyDto{
private Integer id;
private String name;
public HobbyDto(Hobby hobby){
this.id = hobby.getId();
this.name = hobby.getName();
}
public HobbyDto toDto(Hobby hobby){
return new HobbyDto(hobby.getId(), hobby.getName());
}
}
}
// Controller
@PostMapping
public void save(@RequestBody HobbyRequest request){
service.save(request);
}
// Service
public void save(HobbyRequest request){
Hobby hobby = new Hobby(null, request.getName(), null);
Store.hobbies.add(hobby);
}
// Controller
@PostMapping("/connect")
public void save(@RequestBody ConnectRequest request) {
service.connect(request);
}
// Service
public void connect(ConnectRequest request) {
// 입력해준 memberId로 member 정보를 찾아온 뒤..
Member member = memberService.findById(request.memberId());
// 등록된 hobbies를 순환하면서..
// 각각의 hobby 에서 hobbyid 와 받아온 hobbyId 가 비교된 첫번째대상을..
// 가져옴
Hobby hobby = Store.hobbies.stream()
.filter(h -> h.getId().equals(request.hobbyId()))
.findFirst()
.get();
// 해당하는 member와 hobby 를 넣어줌..
// 넣어줌과 동시에 멤버의 취미리스트와, 취미의 멤버리스트로 들어가게 됨..
new MemberHobby(member, hobby);
}
// ConnectRequest
public record ConnectRequest(Integer memberId, Integer hobbyId) {
}
public List<HobbyResponse> findByLikeName(String name) {
List<HobbyResponse> hobbyStream = Store.hobbies.stream()
.filter(h -> h.getName().contains(name))
.map(hobby -> new HobbyResponse(hobby))
.toList();
return hobbyStream;
}
이런식으로 조회 할거임...