묻고 답해요
131만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
의존관계 주입
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]헷갈려서 질문 남깁니다.JpaConfig 를 통해 @Bean 등록 한다JpaConfig Class 에 있는 EntityManager 는 스트링부트가 자동적으로 Bean 등록을 해주기 때문에의존관계 주입을 통해 사용이 가능하다.new JpaRepository(em) 을 통해 의존관계 주입 JpaRepository에서의 EntityManager em 은 JpaConfig에서 ItemRepository 를 @Bean 등록할 때매개변수로 받은 것을 사용제가 이해하고 있는 흐름이 맞나요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
스프링 부트 3.1.3버전 CGLIB
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.스프링 부트 3.1.3버전 CGLIB스프링 부트 3.1.3버전으로 해당 강의를 따라가던 중 proxyCheck() 테스트의 로그가 CGLIB$$0이 출력됩니다. 테스트는 성공하였지만 영한님처럼 프록시 객체의 해시코드가 16진수로 이루어진 값이 아니라 0이 나옵니다. 혹시 몰라서 부트를 2.7.14로 다운그레이드 했더니 영한님과 비슷하게 16진수의 해시코드가 나오더라구요. 혹시 스프링부트3 버전 이상부터 프록시 객체의 해시코드 값이 변경된 걸까요?
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
DB2 - 9.스프링 트랜잭션 이해 - 트랜잭션 적용 확인 강의 관련 질문
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]트랜잭션이 실제 적용되고 있는지 확인하는 방법에서 TxApplyBasicTest 코드 짤때요 BasicService 프록시 객체가 스프링빈으로 자동등록되는데 왜 굳이 @TestConfiguration 에서 BasicService를 수동으로 빈 등록을 하는건가요?? 안해도 되는거 아닌가요?어차피 프록시 객체가 등록되어있어서 @Autowired로 의존관계 주입받을 수 있지 않나요??
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
@Slf4j
@Slf4j 롬복을 이용하여 log값을 출력할때,맨 위 클래스에 작성하고 사용하지 않고 클래스 위에 각각 @Slf4j를 작성하는 이유는 무엇인지 궁금합니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
TxBasicTest
TxBasicTest에서proxyCheck에서 테스트를 돌리면 에러가 나옵니다기대값은 true인데 false가 나온다고합니다. package hello.springtx.apply; import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.transaction.support.TransactionSynchronizationManager; import static org.assertj.core.api.Assertions.assertThat; @Slf4j @SpringBootTest public class TxBasicTest { @Autowired BasicService basicService; @Test void proxyCheck(){ log.info("aop class={}", basicService.getClass()); assertThat(AopUtils.isAopProxy(basicService)).isTrue(); } @TestConfiguration static class TxApplyBasicConfig{ @Bean BasicService basicService(){ return new BasicService(); } } @Slf4j static class BasicService{ public void tx(){ log.info("call tx"); boolean txActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("tx active={}", txActive); } public void nonTx(){ log.info("call nonTx"); boolean txActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("nonTx active={}", txActive); } } }
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
Invalid bound statement
mybatis 작성을 다하고 test를 돌리는데 에러가 발생합니다. org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): hello.itemservice.repository.mybatis.ItemMapper.save 제가 작성한 코드에 문제가 있는지하고 pdf를 복사해서 돌려보아도 계속 에러가 발생합니다..
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
finditems() 에러
'테스트 - 스프링 부트와 임베디드 모드' 수강 중에 ItemRepositoryTest를 h2를 모두 끄고 동작시켰는데강사님처럼 모두 성공을 뜨지 않고 finditems()에서 에러가 납니다.강의자료 초반에 데이터베이스에서 데이터가 보관되어 있어서 그렇다고 들었는데어떻게 해결해야하나요?? h2는 접속 종료한 상태입니다.
-
미해결스프링 DB 2편 - 데이터 접근 활용 기술
IncorrectResultSizeDataAccessException
'JdbcTemplate 적용1- 기본' 강의에서 findById()를 설명하실때,'결과가 없을경우'는 catch로 예외처리를 해주시는데'둘 이상일 경우' IncorrectResultSizeDataAccessException에 대해서는 왜 catch문으로 예외처리를 하지 않는것인지 궁금합니다.
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
어그리거트 설계
jpa를 활용해서 어그리거트를 만들고 있습니다. 게시글 (post 어그리거트)게시자 (member 어그리거트)로 어그리거트를 나눴습니다. 그리고 프로젝트 패키지 구조는 이런 식 입니다.controller- post- memberservice- post- memberdomain (entity와 repository 인터페이스)- post- memberinfra (repository 구현체)- post- member 만약 같은 데이터베이스임에도 post엔티티가 member엔티티를 간접참조(Long memberId를 통한 참조)를 하고 있다면, post 상세페이지에서 member의 이름을 띄워주는 것을 어떻게 구현해야 좋을까요? 현재 고려하고 있는 방법은 두 가지 입니다.service/post 패키지에 PostDetailService 객체를 만든다. 그리고 이 객체가 postRepository와 memberRepository를 di 받은 다음에 두 엔티티를 가져오고 responseDto로 합쳐서 PostDetailController에게 리턴한다.이유는 member 어그리거트가 다른 서버로 분리될 경우, memberRepository의 구현체만 변경하면 될 것 같아서 입니다. (member의 서버가 다른 서버가 되면 member 정보를 api로 받아와야 할 것 같아서 그렇게 하였습니다.) 또 다른 방법으로는 현재는 같은 rdb에 저장되어 있으니 Dao객체를 만들어서 조인으로 responseDto를 직접 만드는 방법이 있을 것 같습니다. jpa 연관관계는 없으니 조인으로 쿼리를 날려야 할 것 같습니다. 어느 방법이 더 좋은 방법인가요? 혹은 더 좋은 방법이 있을까요?
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
DTO를 Result<T> 클래스에 담아서 반환할 때의 예외처리
안녕하세요!영한님 강의를 들으면서 추가적으로 RestTemplate에 대해 알게되어 지금까지 배운 것을 복습할 겸 api와 DTO 통신에 대해 연습하고 있었습니다.DTO를 반환할 때, 그냥 주기보다는 Result<T>의 data같은 속성에 담아서 주는 것이 바람직하다고 하여 그 응용을 연습해 볼겸 Result<T>에 status 속성을 추가해보았습니다.status 속성은 외부 api에서 조건을 충족하는 api를 찾아 와서 반환할 DTO가 있을 경우 "success"를, 조건을 충족하는 api를 찾지 못하여 HttpClientErrorException 예외가 발생할 경우 "fail"을 담아서 반환하고자 하였습니다.아래의 코드를 통해 구현은 성공하였으나, Service 클래스에서 try-catch문을 사용하는게 좀 찜찜하여 혹시 try-catch문 없이 구현하는게 더 좋을지 아니면 그냥 사용해도 좋은지가 궁금하여 질문을 하게 되었습니다.(status가 "fail"이면 data는 null을 반환하게끔 설계해보았습니다) @RestController @RequiredArgsConstructor @RequestMapping("/summoners") public class SummonerController { private final SummonerService summonerService; @GetMapping public ResponseEntity<Result<SummonerDTO>> findSummonerApi(@RequestParam String name) { SummonerDTO summonerDTO = summonerService.findSummonerApi(name); if (summonerDTO == null) { return ResponseEntity.ok().body(new Result<>("fail", null)); } return ResponseEntity.ok().body(new Result<>("success", summonerDTO)); } }@Slf4j @Service @RequiredArgsConstructor public class SummonerService { @Value("${apiKey}") private String apiKey; private final SummonerRepository summonerRepository; private final RestTemplate restTemplate; // riot에서 소환사 정보 api를 받아오는 메서드 public SummonerDTO findSummonerApi(String name) { String url = "https://kr.api.riotgames.com/lol/summoner/v4/summoners/by-name/{summonerName}"; HttpHeaders headers = new HttpHeaders(); headers.set("X-Riot-Token", apiKey); try { return restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), SummonerDTO.class, name).getBody(); } catch (HttpClientErrorException e) { return null; } } }Controller와 Service의 코드는 위와 같습니다. (restTemplate은 별도의 설정파일에 빈으로 구현하였습니다)
-
미해결실전! Querydsl
현시점 QueryDSL에 대한 의견이 궁금합니다.
안녕하세요 김영한님!저는 2년차 백엔드 개발자 주니어입니다. 다름 아니라, QueryDSL이 2021년 5.0.0 버전 이후 새로 릴리즈되고 있지 않습니다.그래서 만약 새로운 서버에 대한 기술 스택을 정할 때, QueryDSL에 대한 영한님의 의견이 어떨지 궁금하여 글을 작성하게 되었습니다.("영한님 의견대로 도입한다 vs 안 한다" 같은 상황이 아니라 단순히 의견이 궁금한 겁니다!) 현재 거론되고 있는 대체 라이브러리는 대략 다음과 같은 것 같습니다.jooqkotlin-jdsl (코틀린 한정)MyBatis 만약 영한님이라면 현시점에서 QueryDSL을 선택하실 것 같나요? 다른 기준이 필요하다면 무엇일까요?혹은 요새 관심있는 라이브러리가 있으실까요?의견이 궁금합니다!감사합니다.
-
해결됨스프링 DB 2편 - 데이터 접근 활용 기술
jpa_pdf 객체 조회 부분에서..
memberId를 파라미터로 받고 해당하는 단일 Member 객체를 반환하는 find 메소드와 연관지었을 때JOIN 뒤에 있어야 할 WHERE M.MEMBER_ID = ? 와 같은 where 절이 없는데.. 생략된 것인가요?
-
미해결
spring boot 3.x 업그레이드 후 querydsl transform 함수 작동이 안됩니다.
안녕하세요. spring boot 3.1.0 으로 업그레이드하여 hibernate 6.2.2 버전을 사용하고 있습니다.Querydsl 로 개발 도중 간단한 select 문은 정상적으로 작동이 되었는데,transform(groupBy().list()) 함수를 사용하니 에러가 발생하였습니다.java.lang.NoSuchMethodError: 'java.lang.Object org.hibernate.ScrollableResults.get(int)' at com.querydsl.jpa.ScrollableResultsIterator.next(ScrollableResultsIterator.java:70) at com.querydsl.core.group.GroupByMap.transform(GroupByMap.java:57) at com.querydsl.core.group.GroupByMap.transform(GroupByMap.java:35) at com.querydsl.core.support.FetchableQueryBase.transform(FetchableQueryBase.java:55) 버전 문제인 것 같아 spring boot 2.x 버전으로 내리고 hibernate도 5.x 버전으로 내리니 정상 작동하더라구요...spring boot 3.x 로 업그레이드하면서 transform() 함수가 제대로 동작을 안 하는 걸까요?
-
미해결자바 ORM 표준 JPA 프로그래밍 - 기본편
단건조회시 fetch를 이용했을때 쿼리개수와 성능이 궁금합니다.
long startTime = System.currentTimeMillis(); BoardResponse.Detail response = boardService.findBoard(board.getId()); long endTime = System.currentTimeMillis(); // then System.out.println(endTime - startTime);해당 코드에서 findBoard Service는 게시글의 힌트, 태그, 정답, 공감을 가져와 DTO의 변환을 거쳐 하나의 게시글을 단건조회하는 서비스입니다.다만 여러 케이스로 테스트했는데단순히 findById로 로직을 테스트를 하게되면 해당 findBoard는 60~90ms의 실행속도와 쿼리가 지연로딩으로 인해 5개가 나가지만JPQL을 통해 DTO를 직접 접근하는 식으로 바꿨을땐, 쿼리를 1개로 나가지만 실행속도가 250~290ms가 나오게 되는데 단건조회의 경우 fetchJoin이나 join+DTO 방식을 쓰는것보다 지연로딩이 있더라도 일반적인 findById를 사용하는것이 좋은지 여쭤봅니다.
-
해결됨실전! Querydsl
로그에 native Query가 출력되게 하려면 어떻게 해야하나요?
요약QuerydslRepositorySupport 적용p6spy 적용쿼리 로그는 출력이 되고 있지만 native query로 출력되지 않음. 로그 예시-- 현재 출력되는 로그 포맷 select daOrder.id, daOrder.createDate from DaOrder daOrder -- 원하는 로그 포맷 select d.id, d.create_date from da_order d 로컬에서 네이티브 쿼리가 바로 로그에 보이도록 설정하고 싶은데테이블명이 아닌 클래스명으로 쿼리가 출력이 되고 있는데요 혹시 어떤 설정을 바꿔야하는지 알 수 있을까요??
-
미해결더 자바, 코드를 조작하는 다양한 방법
어노테이션 프로세서 활용 예와 관련해 질문 있습니다.
'마무리' 한 강 남았네요.덕분에 많이 배우고 많이 성장한 것 같습니다.그런데, 어노테이션 프로세서 활용과 관련해서,, QueryDSL 사용 시 생성되는 엔티티의 Q파일도 어노테이션 프로세서를 활용한 기술인지 궁금합니다.짐작으로는 맡긴 한데, 관련 언급이 없었어서요.
-
미해결실전! Querydsl
첫번째 querydsl테스트 코드 에서 nullpointexception이 터졌습니다
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.q타입을 생성하고 import를 해주었습니다. package study.querydsl; import com.querydsl.jpa.impl.JPAQueryFactory; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; import study.querydsl.entity.Member; import study.querydsl.entity.Team; import javax.persistence.EntityManager; import static study.querydsl.entity.QMember.*; @SpringBootTest @Transactional public class QuerydslBasicTest { @Autowired EntityManager em; JPAQueryFactory queryFactory; @BeforeEach public void before() { Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); em.persist(teamA); em.persist(teamB); Member member1 = new Member("member1", 10, teamA); Member member2 = new Member("member2", 20, teamA); Member member3 = new Member("member3", 30, teamA); Member member4 = new Member("member4", 40, teamA); em.persist(member1); em.persist(member2); em.persist(member3); em.persist(member4); } @Test public void startJPQL() { String qlString = "select m from Member m" + " where m.username = :username"; Member findMember = em.createQuery(qlString, Member.class) .setParameter("username", "member1") .getSingleResult(); Assertions.assertThat(findMember.getUsername()).isEqualTo("member1"); } @Test public void startQuerydsl() { Member findMember = queryFactory .select(member) .from(member) .where(member.username.eq("member1")) .fetchOne(); Assertions.assertThat(findMember.getUsername()).isEqualTo("member1"); } }
-
해결됨실전! Querydsl
jakarta 환경에서 javax 클래스패스로 entityManager를 찾고있습니다.
실행환경gradle 7.6.1java 17, jdk19spring boot 3.0.2제일 처음 환경을 설정한 후 테스트하는 코드에서 아래와 같은 로그가 발생합니다.java: cannot access javax.persistence.EntityManager class file for javax.persistence.EntityManager not found import static org.assertj.core.api.Assertions.*; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; import study.querydsl.entity.Hello; import study.querydsl.entity.QHello; @SpringBootTest @Transactional class QuerydslApplicationTests { @Autowired EntityManager em; @Test void contextLoads() { Hello hello = new Hello(); em.persist(hello); //현재 컴파일 에러가 나고 있는 부분 JPAQueryFactory query = new JPAQueryFactory(em); //em에서 javax.persistence.EntityManager 클래스를 찾을 수 없다는 에러가 나고 있음. QHello qHello = new QHello("h"); Hello result = query .selectFrom(qHello) .fetchOne(); assertThat(result).isEqualTo(hello); } }import문까지 모두 jakarta로 해주고 있습니다. 정상적으로 Q타입클래스가 되어있는데 JPAQueryFactory 생성자 부분의 에러가 전혀 사라지지 않습니다.버전문제인가 싶어서 여러번 버전을 확인했는데도, 제가 확인한 바로는 버전 호환에서는 문제 될 것이 없어보입니다.dataJPA가 3.0.X버전이상에서는 hibernate를 6+버전으로 맞춰줘야한다고 해서 확인해본 결과 hibernate는 다음과 같습니다.org.hibernate.orm:hibernate-core:6.1.7.Final추가적으로 build.gradle 코드를 올려놓겠습니다.plugins { id 'java' id 'org.springframework.boot' version '3.0.2' id 'io.spring.dependency-management' version '1.1.0' id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'study' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.6' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' // == 스프링 부트 3.0 이상일 때, querydsl 의존성 == implementation "com.querydsl:querydsl-core:5.0.0" implementation "com.querydsl:querydsl-collections" implementation("com.querydsl:querydsl-jpa:5.0.0:jakarta") annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" annotationProcessor "jakarta.persistence:jakarta.persistence-api:3.1.0" testImplementation ('org.springframework.boot:spring-boot-starter-test') testImplementation 'jakarta.persistence:jakarta.persistence-api' testImplementation 'com.querydsl:querydsl-jpa:5.0.0' } tasks.named('test') { useJUnitPlatform() } //querydsl 세팅 시 def querydslDir = "$buildDir/generated/querydsl" querydsl { jpa = true querydslSourcesDir = querydslDir } sourceSets { main.java.srcDir querydslDir } configurations { querydsl.extendsFrom compileClasspath } compileQuerydsl { options.annotationProcessorPath = configurations.querydsl }
-
미해결실전! Querydsl
querydsl에서 oneToMany 관계인데 Many쪽 검색이 필요할 때 어떻게 해야하나요?
예를 들어 Order와 OrderItem이 있는데 Order의 검색을 동적쿼리로 검색해야해서 querydsl을 사용하고 있는 상황입니다. 그 중 검색조건이 OrderItem의 이름으로 검색해서 Order의 목록을 가져와야하는데 Order와 OrderItem을 조인하고 where절에 OrderItem의 이름으로 조회하는 방법 말고는 없을까요? 그럴 경우 distinct를 쓰거나 따로 중복 제거 로직을 넣어야해서ㅜ 혹시 다른 방법이 있나 문의드립니다.이런 경우에는 양방향 연관관계를 맺어주고 해결해도 될까요?
-
미해결실전! Querydsl
UPDATE 동적쿼리 사용 질문
안녕하세요. 강의 듣고 미니 프로젝트 하며 궁금한 점이 생겨 질문드려봅니다. UPDATE문에서도 동적쿼리를 사용하고 싶어 정적쿼리를 아래와 같이 구현해보았는데 혹시 WHERE절의 BooleanExpression처럼 조금 더 깔끔하게 처리할 수 있는 방법이 있을지 문의드려봅니다. 감사합니다.