JPA 없이 JPA 흉내내기

이동명·2023년 7월 12일
1

# ERD

오늘의 취지는 JPA 배우기 앞서 JPA의 흐름을 흉내 내보는 코드를 작성해보기로 하였음..

위의 그림은유저와 취미의 중간테이블을 두고 다대다 관계를 형성한 설계도다.

JPA 를 사용하면 손 쉽게 관계를 맺고 데이터를 사용할 수 있지만 JPA를 사용하지 않고 이와 같은 기능이 될 수 있게 구현해보자..

# Member


@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<>();
    }
}

# Hobby


@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<>();
    }

}

# Store (DB 대용)

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;

}

# MemberHobby (중간테이블 구현)


@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;
}

이런식으로 조회 할거임...

profile
Web Developer

0개의 댓글