programing

스프링 데이터: JPA 저장소 findAll()을 사용하여 목록 대신 *Map을 반환하시겠습니까?

i4 2023. 2. 25. 19:45
반응형

스프링 데이터: JPA 저장소 findAll()을 사용하여 목록 대신 *Map을 반환하시겠습니까?

다음과 같은 Spring Data JPA 저장소 인터페이스가 있습니다.

@Repository
public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {

    List<TransactionModel> findAll();
    List<TransactionModel> findByClientId(Long id);
}

컬렉션을 유형으로 반환하지 않고 동일하게 만드는 해결 방법이 있습니까?HashMap<K, V>? Spring Data 클래스를 조사했는데 List <> return values 이외에는 아무것도 찾을 수 없었습니다.

결과를 지도에 변환하기 위한 간단한 라이너 하나를 만드는 것보다 쉬운 해결책을 찾을 수 없을 것 같습니다.Java 8 lamda를 사용하면 간단하고 빠릅니다.

Map<Long, Transaction> transactionMap = transactionList.stream()
         .collect(Collectors.toMap(Transaction::getId, Function.identity()));

비슷한 문제를 해결해야 했고 Patricks의 답변이 도움이 되었지만 어디에 추가할지를 표시하면 개선될 수 있습니다.

JPA repo가 맵을 반환하는 것처럼 보이게 하려면 저장소 인터페이스의 기본 방식으로 이 맵을 정리해야 합니다.사용량이 많은 모든 클래스에서 스트림을 수행할 필요가 없습니다.

@Repository
public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {

    List<TransactionModel> findAll();

    default Map<Long, TransactionModel> findAllMap() {
        return findAll().stream().collect(Collectors.toMap(TransactionModel::getId, v -> v));
    }

    List<TransactionModel> findByClientId(Long id);

    default Map<Long, TransactionModel> findByClientIdMap(Long id) {
        return findByClientId(id).stream().collect(Collectors.toMap(TransactionModel::getId, v -> v));
    }
}

맵은 스프링 데이터 JPA 참조에 기재되어 있는 커스텀 스트림 가능한 래퍼 타입에서 얻을 수 있습니다.

@RequiredArgsConstructor(staticName = "of")
public class TransactionModels implements Streamable<TransactionModel> {
    
    private final Streamable<TransactionModel> streamable;

    @Override
    public Iterator<TransactionModel> iterator() {
        return streamable.iterator();
    }

    public Map<Long, TransactionModel> asMap() {
        return streamable.stream()
            .collect(Collectors.toMap(Transaction::getId, Function.identity()));
    }
}
@Repository
public interface DBReportRepository extends JpaRepository<TransactionModel, Long> {

    TransactionModels findAll();

    TransactionModels findByClientId(Long id);

}

원하는 것을 얻을 수 없는 이유Map<Long, TransactionModel>Spring Data의 방법은 다음과 같습니다.java.util.Map<K,V>에 위임되다org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution대신org.springframework.data.jpa.repository.query.JpaQueryExecution$CollectionExecution디폴트입니다.그리고 자바에서 확장되지 않기 때문에 합리적입니다.하지만 당신의 경우,Map"컬렉션"으로 사용합니다.다행히 원하는 유형을 반환할 수 있는 사용자 지정 메서드로 Spring 데이터 저장소를 확장할 수 있습니다.

다른 솔루션에서는 Java 8 lamda를 사용합니다.

transactionList를 ID별로 그룹화하고 결과를 Map 인스턴스에 저장하는 groupingBy 메서드 수집기 사용

Map<Long, Transaction> transactionMap = transactionList.stream().collect(Collectors.groupingBy(v->v.getId()));

엔티티를 취득한 후 맵을 작성하는 것은 퍼포먼스를 향상시키려 하는 경우에는 해결책이 되지 않습니다.엔티티 전체를 취득한 후 선택한 필드를 맵에 추가하는 경우 맵 또는 목록을 직접 취득하는 경우보다 시간이 더 걸립니다.

언급URL : https://stackoverflow.com/questions/41876122/spring-data-jpa-repository-findall-to-return-map-instead-of-list

반응형