월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결실전! 스프링 데이터 JPA
안녕하세요
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요 성능 테스트를 해보고 QueryHint 를 적용할지 고민하라고 하셨는데 성능 테스트란 정확하게 어떤 걸 의미하나요? 부하 테스트 인지 맞다면 예시가 뭐인지 궁금합니다.그리고 성능 테스트를 하면 QueryHint 를 쓰는게 더 성능이 좋게 나올텐데 그럼 쓰는 게 낫지 않나 하는 궁금증이 듭니다.
- 미해결실전! 스프링 데이터 JPA
long 반환타입
MemberJpaRepository의 count 함수에서 Long이 아닌 long 으로 반환타입을 작성 하는 이유가 뭔가요?Long으로 해도 상관 없는걸까요?
- 미해결실전! 스프링 데이터 JPA
@CreatedDate에 관하여
@CreatedDate가 persist 전에 호출된다는 말씀이 -> persist 전에 호출되기 때문에 createdDate의 값을 가져오기 위해 별도의 쿼리를 날리지 않는다는 말인가요??또 CreateDate를 사용하는 이유가 persist 전에 호출되고 persist 이후에 JPA가 createdDate에 값을 넣어주기 때문에 사용한다고 생각하는게 맞을까요??
- 미해결실전! 스프링 데이터 JPA
DTO 조회하기 n+1오류
강의 내용은 간단하게 설명해주셧는데1.OneToMany의 경우나 n+1문제가 발생할 경우는 어떻게 해결하나요?2.강의에서는 join만 썻는데 fetch join은 불가능한가요?
- 해결됨실전! 스프링 데이터 JPA
기초적인 질문입니다...
public void changeTeam(Team team) { this.team = team; team.getMembers().add(this);}강의를 들었을 때 양방향 연관관계에서는 한쪽에만 작업을 해주면 안되고 양쪽을 작업해줘야 하기 때문에 위와 같은 코드를 작성한다고 알고 있습니다.위 코드에서 팀 변경으로 인해 새로운 팀에 member를 추가해주고 기존의 팀의 list에서 제거해주는 작업은 별도로 진행하지 않아도 되는지 궁금하여 질문 남깁니다...한쪽에 설정해주면 JPA가 알아서 양방향 연관관계에 대해서 정리해주는건가 싶기도 하고 잘모르겠어서 질문 드립니다
- 미해결실전! 스프링 데이터 JPA
JOIN 관련해서 질문드릴게 있어요!
안녕하세요. 수업 듣다가 갑자기헷갈려서 여쭤볼게 생겼어요.@Query("select new study.datajpa.dto.MemberDto(m.id, m.username, t.name) " + "from Member m join m.team t")위 같은 쿼리에서 Member entity에 t.name이란게 없으니 저는 fetch join을 써야 한다고 처음에 생각했거든요.일반 join은 조회시 join 대상이 되는 entity는 조회 대상이 되는 칼럼에서 불러지지 않고, 불러진다면, 따로 쿼리가 동작하기 떄문에 N+1 이 발생하는 걸로 알고있었는데, 수업에서 log보니깐 select 쿼리에서 t.name 도 같이 한 쿼리에 조회되는게 보여서 갑자기.. 멍해지더라구요 ㅋㅋ;;;저는 member 따로 1번, team따로 1번 돌거라고 예상했었는데... 제가 놓친 부분이 있을까요?? 답변 미리 감사드리겠습니다.
- 해결됨실전! 스프링 데이터 JPA
isNew() 메서드의 구현체 문의
안녕하세요! isNew() 메서드의 구현체가 정확히 무엇인지 확인하고 싶어 질문드립니다!SimpleJpaRepository의 save() 메서드 내부에서 isNew() 메서드가 호출될 때,if (entityInformation.isNew(entity)) {처럼 호출되는데요, 이 때 isNew 가 org.springframework.data.repository.core.EntityInformation 인터페이스의 추상 메서드인 것을 확인했습니다.그런데 이 isNew 의 구현체가 여러개라서 하나씩 확인해보니 강의에서 설명해주신 내용이 추상 클래스 org.springframework.data.repository.core.support.AbstractEntityInformation 에 구현된 내용과 같더라고요.// AbstractEntityInformation.isNew() public boolean isNew(T entity) { ID id = getId(entity); Class<ID> idType = getIdType(); if (!idType.isPrimitive()) { return id == null; } if (id instanceof Number) { return ((Number) id).longValue() == 0L; } throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType)); }그런데 AbstractEntityInformation 역시 추상 클래스이다 보니 정확한 구현체를 찾기가 힘든 상태입니다. 질문) SimpleJpaRepository의 save() 내부에서 사용되는 isNew() 의 구현체는 정확히 어떤 클래스인가요? 또, 이러한 구현체가 정확히 무엇인지 알 수 있는 방법이 있을까요?확인해주셔서 감사합니다. :D
- 미해결실전! 스프링 데이터 JPA
loginfailureHandler에서 db에 로그 저장 시 에러
안녕하세요질문이 있어서 글을 남깁니다. 로그인 실패 시 handler에서 DB에 로그를 남기고 싶은데,마지막 loginLogService.saveLoginLog(loginLogDto); 에서 null 됩니다.어떤 것이 문제일까요???답변 부탁드립니다.감사합니다.
- 미해결실전! 스프링 데이터 JPA
빌더와 생성자의 보안 차이가 궁금합니다!
setter를 지양하는 이유 중에 하나가 보안성이라고 생각했습니다.그런데 builder를 사용하면 똑같이 보안에 문제가 생기지 않나 의문이 들었습니다.값을 변경하거나 삽입할 때 함수를 따로 만드는 것이 가장 보안성이 좋지만 파라미터가 많을 때 가독성과 편리성을 위해 builder를 사용하는 건가요??
- 미해결실전! 스프링 데이터 JPA
모든 쿼리에 같은 where조건이 필요 할 때
예시 상황은 여러 학생이 테이블을 공유해서 사용하여 모든 테이블에 student_id 컬럼이 있고 이를 이용해 데이터 사용자를 구별한다고 했을 때입니다.이럴 때 모든 find, update, delete 절에 where student_id = '1000' 와 같은 조건이 필요하다고 하면 단순히 모든 find문에 findByStudentId 하고 아이디를 넣어주는 수밖에 없을까요?어플리케이션 사용자 학생 아이디는 properties에 적어놓고 가져와 사용할 것이라 프로세스 실행중에 파라미터로 받아오는 경우는 없습니다.
- 미해결실전! 스프링 데이터 JPA
단방향 연관관계 적용시 질문 있습니다.
일반적으로 양방향 연관관계는 지양하는 것이 좋다고 해서, 단방향 연관관계로 생각을 해보고 있는데요. Member (N) 쪽에만 Team 쪽으로 단방향 연관관계를 설정한 상태인데요. 특정 팀의 멤버들을 알고 싶은 경우가 있을거 같아요. Member 중, team id 가 X 인 것을 찾고 싶은 경우에는 어떻게 해야하나요? fetch join 시에는 별칭을 줄 수 없기 때문에 안될거 같습니다. 이럴때는 그냥 일반 조인문으로 풀어내고, team 정보가 필요하다면 다시 조회하는 것이 맞나요?
- 미해결실전! 스프링 데이터 JPA
data jpa 사용 시 쿼리도 aop 같은 방식이 적용 가능한가요?
안녕하세요. 강의 듣고, jpa이용해서 팀 프로젝트 만들어 보고 있습니다.다름이 아니라, 게시글 삭제 시, 정말 게시글이 삭제되는 것이 아니라, 게시글 안의 Enum 에 deleted로 변경 해 두고, 일정 시간이 삭제되게 하려고 했습니다.변경 까지는 문제가 없었는데, 이렇게 기능이 추가가 되니, 기존에 게시 글을 반환하던 쿼리 들에 전부where status = 'ACTIVE' 와 같은 조건을 넣어주어야 하게 되었습니다. 전부 수작업으로.... 조건을 넣어주는 방법 밖에는 없을까요? 간단한 프로젝트라고 생각해서 QueryDsl은 사용하지 않았습니다.또 저 조건을 개발자가 전부 쿼리 개발 할 때 필수로 넣어야 된다면, 어쩌다 까먹고 안 넣게되면 삭제 처리 되었던 게시글이 사용자 눈에 보이는..참사가 발생할 것 같습니다.기존 Repository 쿼리가 실행되기 전에 먼저 article.status = 'ACTIVE' 인 것들만 필터를 하고, 거기에 제가 지금까지 만들어 놓은 쿼리들이 적용이 되면 될 것 같은데, 아무리 찾아봐도 좋은 대안이 보이지가 않아 보여서 혹시나 하는 마음에 질문 드립니다.감사합니다.
- 미해결실전! 스프링 데이터 JPA
벌크연산이 영속성 컨텍스트를 무시하는 이유
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]안녕하세요 선생님 좋은 강의 감사합니다.벌크연산이 영속성 컨텍스트를 무시하고 곧바로 db에 반영되는 이유가 메모리 크기의 한계 때문일까요? 이렇게 설계된 이유가 궁금합니다!
- 미해결실전! 스프링 데이터 JPA
pathVariable관련 질문 드립니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)네 조금은 다를수있습니다.2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)네3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)네[질문 내용]강의와는 조금 다를수있지만/mebers/{id} 이렇게 조회를 하면 누군가도 똑같은 url을 입력하여 해당 정보를 볼수 있다고 생각하는데 이런거에 대한 위험성같은거는 따로 처리하는 방법?같은게 있는지 궁금합니다.
- 미해결실전! 스프링 데이터 JPA
Percictence Context에 대해 질문있습니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요. 현재 JPA에 대해 공부하고 있는 학생입니다. 현재 N+1에 대한 이슈를 테스트하는 중에 Entity의 생명주기에 대한 궁금점이 있어 질문을 남겼습니다.EntityManager 초기화 시 1차 캐시에 있는 Entity는 자동으로 Flush가 되나요?N+1 확인을 하기위해 모든 Entity를 저장한 후EntityManager를 초기화 시켜 1차 캐시를 초기화시켰습니다. 이유는 1차 캐시에 원하는 Entity가 존재한다면 해당 Entity를 DB를 거치지 않는다고 알고 있어서입니다.코드는 다음과 같습니다.@ExtendWith(SpringExtension.class) @DataJpaTest public class StudyRoomRepositoryTest { @Autowired private StudyRoomRepository studyRoomRepository; @Autowired private UserRepository userRepository; @PersistenceContext EntityManager em; private List<StudyRoom> studyRooms = new ArrayList<>(); private List<User> users = new ArrayList<>(); @BeforeEach public void setUp() { users.add(userRepository.save(User.builder().userUuid(UUID.randomUUID()).email("tester@gmail.com").password("password").nickName("tester").build())); users.add(userRepository.save(User.builder().userUuid(UUID.randomUUID()).email("tester2@gmail.com").password("password").nickName("tester2").build())); studyRooms.add( studyRoomRepository.save(StudyRoom.builder().roomName("TestStudyRoom1").constructor(users.get(0)).build())); studyRooms.add( studyRoomRepository.save(StudyRoom.builder().roomName("TestStudyRoom2").constructor(users.get(1)).build())); } @Test @DisplayName("users N+1 문제 Test") public void UsersNPlusOneTest(){ em.clear(); //EntityManager 초기화 List<StudyRoom> findStudyRooms = studyRoomRepository.findAll(); for(StudyRoom findStudyRoom: findStudyRooms){ System.out.println(findStudyRoom.getConstructor()); } } }예상대로 N+1 이슈에 대해 확인할 수 있었습니다. 하지만 궁금한점이 생겼습니다. 제가 알기로는 Save 메소드가 호출된다 해도 Transaction이 진행중이면 실제 DB에는 안 넘어가는것으로 알고있습니다. 또한 만약 DB로 넘기고 싶다면 Flush를 통해 넘길 수 있는 것으로 알고있습니다. 근데 저는 SaveAndFlush() 메소드가 아닌 Save() 메소드를 호출했음에도 불구하고 Select Query로그가 찍힙니다.Hibernate: select studyroom0_.study_room_id as study_ro1_1_, studyroom0_.create_at as create_a2_1_, studyroom0_.is_deleted as is_delet3_1_, studyroom0_.update_at as update_a4_1_, studyroom0_.user_id as user_id7_1_, studyroom0_.room_name as room_nam5_1_, studyroom0_.room_uuid as room_uui6_1_ from study_rooms studyroom0_ Hibernate: select user0_.user_id as user_id1_2_0_, user0_.create_at as create_a2_2_0_, user0_.is_deleted as is_delet3_2_0_, user0_.update_at as update_a4_2_0_, user0_.email as email5_2_0_, user0_.nick_name as nick_nam6_2_0_, user0_.password as password7_2_0_, user0_.role as role8_2_0_, user0_.user_uuid as user_uui9_2_0_ from users user0_ where user0_.user_id=? com.twoleader.backend.domain.user.entity.User@522fb69이유를 잘 모르겠습니다. 제 예상으로는 EntityManager의 clear()메소드 호출 시 1차 캐시 안에 Entity들이 존재한다면 자동으로 Flush()메소드가 호출되는 것으로 추측이 되는데 맞는지 여쭙고 싶습니다. 만약 아니라면 해당 데이터는 어디서 불러온것인지 궁금합니다.
- 미해결실전! 스프링 데이터 JPA
쿼리 힌트 Page 추가 예제 관련 질문입니다/
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? [질문 내용]안녕하세요. 강의와 자료를 병행해서 보다가 질문이 있어 문의드립니다. 우선적으로https://www.inflearn.com/course/lecture?courseSlug=%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84&unitId=28020&tab=community&category=questionDetail&q=723744해당 내용을 읽어보았는데도 이해가 되질 않아 문의드리게 된 점 양해부탁드립니다 ㅜ해당 내용처럼 저도 application.yml 내 use_sql_comments: true 를 추가쿼리문을 확인하였을 때forCounting=false /* select count(m) from Member m where m.username = :username */ select count(member0_.id) as col_0_0_ from member member0_ where member0_.username='member1'; forCounting=true /* memberRepository.findByUsername */ select count(member0_.id) as col_0_0_ from member member0_ where member0_.username='member1';위와 같은 결과를 반환받았는데 어떤 차이가 있는지 잘모르겠습니다 ㅜ 어떤 의도를 말씀하시는지 잘모르겠습니다 ㅜ
- 미해결실전! 스프링 데이터 JPA
부모 엔티티의 Respository 로 저장시 자식 엔티티의 영속성 전이 문제
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]김영한님 안녕하세요. JPA 사용중에 부모 엔티티의 Respository 로 저장시 자식 엔티티의 영속성 전이 문제가 있어 질문 남깁니다. 상황은 다음과 같습니다.게시판과 게시판의 댓글을 하나의 애그리거트로 보고 게시판(루트 애그리더트)을 통해 댓글을 작성하려고 합니다. 댓글의 게시판 칼럼을 세팅하고 게시판의 repository로 save 하게 되면 댓글이 영속성 상태가 되지 않습니다. 근데 게시판 내부에 있는 댓글 리스트에 추가된 신규 댓글을 영속성 상태입니다. (영속성 상태 여부는 id 값 존재 여부로 판단했습니다.) 위 캡쳐에서 board 의 commentList의 인덱스가 4인 BoardComment 를 보시면 id가 7로 세팅 되어 있지만, boardComment 의 id는 null 로 되어 있습니다. 그래서 물어보고 싶은건 다음과 같습니다.위 상황에서 boardComment 의 id 가 7(null 이 아닌)이 될 수 있는 방법댓글 조회/수정/삭제에서 DDD 를 적용했을때의 로직 DDD 에 맞게 루트 애그리거트를 통한 CRUD 를 만들려고 하다보니 이런 질문을 하게 되었습니다. 이 문제의 전체코드는 https://github.com/SongHae8640/community 이고, 위 테스트 코드는 https://github.com/SongHae8640/community/blob/master/src/test/java/com/example/community/domain/board/comment/BoardCommentTest.java 입니다. 확인 부탁드립니다.감사합니다.
- 미해결실전! 스프링 데이터 JPA
JpaRepository 오버라이드 메소드에 QueryHints 적용시 에러발생
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true")) @Override Optional<Member> findById(Long aLong);위와 같이 SimpleJpaRepository의 findById를 오버라이딩 할 경우 오류가 발생합니다.JpaRepository의 메소드를 오버라이드 하여서 적용할 수 없는건지 궁금합니다.다음은 오류의 내용입니다.org.springframework.dao.InvalidDataAccessApiUsageException: class java.lang.String cannot be cast to class java.lang.Boolean (java.lang.String and java.lang.Boolean are in module java.base of loader 'bootstrap'); nested exception is java.lang.IllegalArgumentException: class java.lang.String cannot be cast to class java.lang.Boolean (java.lang.String and java.lang.Boolean are in module java.base of loader 'bootstrap') at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:374) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:235) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551) at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61) at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:152) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241) at com.sun.proxy.$Proxy132.findById(Unknown Source) at study.datajpa.MemberRepositoryTest.queryHint(MemberRepositoryTest.java:318) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725) at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140) at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84) at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115) at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105) at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67) at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86) at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86) at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:57) at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54) Suppressed: org.springframework.transaction.UnexpectedRollbackException: Transaction silently rolled back because it has been marked as rollback-only at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:752) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) at org.springframework.test.context.transaction.TransactionContext.endTransaction(TransactionContext.java:131) at org.springframework.test.context.transaction.TransactionalTestExecutionListener.afterTestMethod(TransactionalTestExecutionListener.java:255) at org.springframework.test.context.TestContextManager.afterTestMethod(TestContextManager.java:445) at org.springframework.test.context.junit.jupiter.SpringExtension.afterEach(SpringExtension.java:206) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$12(TestMethodTestDescriptor.java:257) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:273) at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:273) at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:272) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:256) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:141) ... 47 moreCaused by: java.lang.IllegalArgumentException: class java.lang.String cannot be cast to class java.lang.Boolean (java.lang.String and java.lang.Boolean are in module java.base of loader 'bootstrap') at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3434) at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3380) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:315) at com.sun.proxy.$Proxy112.find(Unknown Source) at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById(SimpleJpaRepository.java:335) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137) at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121) at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:530) at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:286) at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:640) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164) at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:76) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ... 77 moreCaused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Boolean (java.lang.String and java.lang.Boolean are in module java.base of loader 'bootstrap') at org.hibernate.internal.SessionImpl.find(SessionImpl.java:3396) ... 106 more
- 미해결실전! 스프링 데이터 JPA
fetch하지 않은 left join은 member만 조회하는데 어떻게 객체탐색이 가능한지 이유
우선 저의 코드부터 올려보겠습니다.@Query("select m from Member m left join m.team t") List<Member> findmemberByLeftJoin();저의 코드는 JPQL에서 left join fetch를 하지 않고 left join만 걸었습니다.강의 내용에 의하면 단순 joinAll()을 하였을 때 영속성 컨텍스트로부터 proxy객체를 일단은 주입한다고 하셨습니다.저의 경우는 @Query를 활용하여 다음과 같은 JPQL을 선언하였을 때, Console에 출력되는 내용은 아래와 같습니다.left join은 걸리지만 Select절에는 Member에 대한 데이터만 불러올 뿐, Team에 대한 데이터는 불러오지 않고 있습니다.그렇다면 이때 Team을 getClass로 출력할때 proxy객체일거라 생각했습니다.하지만 직접 출력해보니 class study.datajpa.entity.Team 이렇게 출력이 됩니다.이것은 조회는 하지 않았으나, 프록시객체를 반환하지는 않고 진짜 객체로 반환한다는 뜻인데...여기서부터 햇갈리기 시작합니다.어떻게 이해하고 받아들여야 할까요?1. 쿼리상에서는 Team을 불러오지 않는데, 어떻게 객체탐색을 통해 Team 객체가 조회가 되나요?2. 쿼리상에서는 Team을 불러오지 않는데, 어째서 Proxy객체가 아닌 진짜 엔티티인가요?3. 결국 이런 현상은 패치조인과 다른 것 이라고 이해해야 할까요? (이 현상은 inner Join에서도 발생합니다) * left조인은 걸리고, select절에 team은 없지만 * n+1이 발생하지 않고도 team이 조회되는 이유 * 프록시 객체가 아닌 진짜 team객체를 반환해주는 이유
- 해결됨실전! 스프링 데이터 JPA
교안과 강의내용의 차이점 및 Member(String name) 생성자 초기화 세팅
우선 강의 에서는 생성자를 아래와 같이 구성하여 진행하였습니다public Member(String username) { this.username = username; // 2번 생성자 호출 } public Member(String username, int age, Team team) { this.username = username; this.age = age; if (team != null) { changeTeam(team); } }순차적으로 각각 1번과 2번 생성자로 구분한다고 가정하였을 경우 강의 교안에서는 아래와 같은 코드로 구성되어 있습니다. public Member(String username) { this(username, 0); // 2번 생성자 호출 } public Member(String username, int age) { this(username, age, null); // 3번 생성자 호출 } public Member(String username, int age, Team team) { this.username = username; this.age = age; if (team != null) { changeTeam(team); } }논리적으로 해석해보자면 2번째 생성자는 username과 age만 값이 세팅되므로 team에 대한 값은 null로 세팅하는게 맞다 라고 판단이 되었으나,1번째 생성자는 username만 초기화되고 age에 대한 값만 0으로 초기화 해주지만 team에 대한 값은 들어오지 않았으니 null로 처리해줘야 하는게 아닌가? 하는 의문이 들었습니다. public Member(String username) { this(username, 0, null); // 2번 생성자 호출 } 위와 같이 1번 생성자의 this() 초기화에서는 username만 들어온다면 2번째 생성자와 같이 team에대한 값을 null로 함께 초기화 해야 맞는것이 아닌가 의문이 듭니다.