1. JPA table간 join 올바르게 사용하기

entity 정의

user:diary , user:result 는 일:다 관계이다.

Hibernate에서 양방향 관계는 두 엔티티 간에 서로 참조가 있는 경우를 의미합니다. 양방향 관계를 설정하면 한 엔티티에서 다른 엔티티로의 참조와 동시에 그 역방향인 다른 엔티티에서의 참조도 유지. 이는 관계를 탐색하거나 쿼리할 때 편의성을 제공합니다.

Hibernate에서 양방향 관계를 설정하는 방법은 두 엔티티 간에 서로를 참조하도록 필드를 추가하고, 그에 따라 매핑을 설정하는 것입니다. 주로 @ManyToOne, @OneToMany, @OneToOne, @ManyToMany와 같은 어노테이션을 사용하여 관계를 정의하게 됩니다.

예를 들어, 양방향 일대다 관계를 갖는 두 엔티티가 있다고 가정해보겠습니다: UserEntityResultEntity.

@Entity
@Table(name = "user")
public class UserEntity {
    // ... 다른 필드들

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ResultEntity> results = new HashSet<>();

    // ... 다른 메소드들
}

@Entity
@Table(name = "result")
public class ResultEntity {
    // ... 다른 필드들

    @ManyToOne
    @JoinColumn(name = "user_id")
    private UserEntity user;

    // ... 다른 메소드들
}

위의 코드에서 UserEntity 클래스에는 results 필드가 있고, ResultEntity 클래스에는 user 필드가 있습니다. @OneToMany@ManyToOne 어노테이션을 사용하여 양방향 관계를 설정했습니다. mappedBy 속성은 연관관계의 주인을 설정하는데, UserEntityResultEntity에 대한 연관관계의 주인이므로 mappedBy에는 user 필드를 가리키는 문자열을 설정

이렇게 설정하면 UserEntity를 저장할 때 해당 유저와 연관된 ResultEntity도 자동으로 저장되며, ResultEntity를 저장할 때에도 해당 결과와 연관된 UserEntity가 저장됩니다. 또한, 양쪽에서 서로를 참조할 수 있게 되어, 특정 유저에 대한 결과를 얻거나, 특정 결과에 대한 유저를 찾는 등의 작업이 용이

2. Treemap 사용하기

프로필 페이지 날짜 순서대로 보내주기

TreeMap은 Java의 컬렉션 프레임워크에서 제공하는 클래스 중 하나로, 키를 기준으로 정렬된 맵을 나타냅니다. 이 클래스는 SortedMap 인터페이스를 구현하고 있으며, 내부적으로 레드-블랙 트리(Red-Black Tree)라는 자료 구조를 사용하여 키를 정렬하고 관리합니다.

레드-블랙 트리는 균형 잡힌 이진 검색 트리로, 각 노드는 빨간색 또는 검은색으로 표시되어 있습니다. 이 트리는 삽입, 삭제, 검색에 대한 연산을 효율적으로 수행할 수 있도록 설계되어 있습니다. 따라서 TreeMap은 키에 대한 정렬된 순서를 유지하면서 데이터를 저장할 수 있습니다.

TreeMap은 다양한 메서드를 제공하여 정렬된 맵에서 데이터를 조작하고 탐색할 수 있도록 합니다. 예를 들면, firstKey()는 가장 작은 키를 반환하고, lastKey()는 가장 큰 키를 반환합니다. 또한 headMap(), tailMap(), subMap() 등의 메서드를 사용하여 부분 맵을 생성할 수 있습니다.

아래는 간단한 TreeMap의 사용 예시입니다:

import java.util.TreeMap;

public class TreeMapExample {
    public static void main(String[] args) {
        // TreeMap 생성
        TreeMap<String, Integer> treeMap = new TreeMap<>();

        // 데이터 추가
        treeMap.put("Apple", 10);
        treeMap.put("Orange", 5);
        treeMap.put("Banana", 8);
        treeMap.put("Grapes", 15);

        // 정렬된 순서로 출력
        for (String key : treeMap.keySet()) {
            System.out.println(key + ": " + treeMap.get(key));
        }
    }
}

이 예시에서는 과일 이름을 키로 하고 각 과일의 개수를 값으로 하는 TreeMap을 생성하고, 키를 기준으로 정렬된 순서로 데이터를 출력하는 간단한 프로그램입니다.

@GetMapping("/dashboard")
    public ResponseEntity<?> dashboard(@AuthenticationPrincipal UserEntity userEntity) {
        try{
            log.info("Dashboard start");
            log.info("userEntity : {}",userEntity);
            if(userEntity==null)
                return ResponseEntity.badRequest().body("로그인 후 이용해주세요.");
            // 대시보드 정보 저장(유저 정보, 날짜 정보 등 저장해야함)
            // 대시보드 정보 불러오기(유저 정보, 날짜 정보 등 저장해야함)
            // 대시보드 정보 수정(유저 정보, 날짜 정보 등 저장해야함)
            List<ResultEntity> userResultList = dashbaordService.dashboard(userEntity);

            log.info("user의 dashboard list::{}",userResultList);

            TreeMap<String, DashboardDTO> resultMap = new TreeMap<>();

            for (ResultEntity result : userResultList) {
                ResultDTO resultDTO = new ResultDTO();
                resultDTO.setId(result.getId());
                resultDTO.setPictureDiary(result.getPictureDiary());
                resultDTO.setSentiment(result.getSentiment());
                resultDTO.setPositiveRatio(result.getPositiveRatio());
                resultDTO.setNegativeRatio(result.getNegativeRatio());
                resultDTO.setNeutralRatio(result.getNeutralRatio());
                resultDTO.setDate(result.getDate());
                resultDTO.setRecommendedGif(result.getRecommendedGif());

                // Create or update DashboardDTO based on date
                DashboardDTO dashboardDTO = resultMap.computeIfAbsent(String.valueOf(result.getDate()), k -> DashboardDTO.builder().build());

                // Set ResultDTO in DashboardDTO
                dashboardDTO.setResult(resultDTO);
            }

            return ResponseEntity.ok().body(resultMap);
        }catch(Exception e) {
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }

트리 맵을 써서 유저의 id로 result 테이블에서 추출한 값들을 정렬하여서 보내주었습니다.

computeIfAbsent