이전 내용은 내부 트랜잭션이 외부 트랜잭션에 종속된다는 내용이였는데, 지금까지 테스트를 트랜잭션 매니저로 직접 생성해서 해주셨습니다. 그런데 실무에서는 트랜잭션 어노테이션을 많이 쓰는데 디폴트 트랜잭션은 기존 트랜잭션이 존재하면 그대로 이어 쓰는 걸로 알고 있습니다. 이 경우가 이어 쓰는 것임에도 논리적으로 외부 내부로 구분하는 건지, 아니면 다른 옵션의 예가 따로 있는 건지 궁금합니다. 정리하자면 기존 트랜잭션을 이어 쓰는 REQUIRED 옵션이 이제까지 설명해주신 내부가 외부에 종속되는 트랜잭션인지 아니면 다른 옵션이 있는 건지 궁금합니다.
안녕하세요 강사님. 현재 섹션5를 보고 있는데 프로젝트가 어떤 프로젝트인지 헷갈려서 질문 드립니다. 섹션 1,2,3 을 보면 투두리스트 인것 같은데 갑자기 섹션4부터는 product나 상품들도 나오고, 그 뒤 섹션들을 보면 장바구니도 나오고 하던데 최종적으로는 어떤게 만들어지는 건가요?
안녕하세요. 앞서 전파기본 강의와 전파예제 강의를 듣고나서 이해가 되지않는 부분이 몇가지 있어서 질문드립니다. 1. 강의 자료중에, 트랜잭션매니저에 커밋하는것이 논리적인 커밋이라면, 실제커넥션에 커밋하는것을 물리 커밋이라고 할수있다 = 내부트랜잭션인 txManager.commit(inner)을 하는것이 논리적인 커밋이고, 외부트랜잭션인 txManager.commit(outer)을 하는것이 물리커밋이다. = 트랜잭션 매니저를 통해 txManager.commit(inner)를 하는것이 논리적인 커밋이고, 트랜잭션 매니저를 통해 txManager.commit(outer)를 하는것이 물리커밋이다. 이렇게 생각하는게 맞을까요?? 2. 1번 질문에 더해서, 트랜잭션 매니저를 통해서 txManager.commit()을 하는것이 논리적인 커밋이라면, 물리적인 커밋은 코드상 어떤것인가요? 외부트랜잭션도 txManager.commit()을 통해 커밋하는거같은데, 이렇게 외부트랜잭션을 커밋하는것이 논리적인 커밋임과 동시에 물리커밋인것인가요?? 3. 외부트랜잭션도 논리트랜잭션이고 내부트랜잭션도 논리트랜잭션인가요? 그래서 이 두가지를 묶어서 물리트랜잭션이라고 하는것인가요?? + 위 질문에 대해서 계속 찾아보면서 생각해봤는데, 이렇게 이해하면 될까요? 1. 내부트랜잭션이 트랜잭션 매니저를 통해서 커밋하는것이 논리적인 커밋이고, 외부트랜잭션이 트랜잭션매니저를 통해서 커밋하는것은 실제 DB커넥션에 커밋하는것이다. 외부트랜잭션의 커밋은 논리적커밋임과 동시에 물리커밋이다. 2. 외부트랜잭션을 커밋하는것은 논리적 커밋임과 동시에 물리커밋이다. 3. 외부트랜잭션과 내부트랜잭션 모두 논리트랜잭션이고, 논리트랜잭션을 묶어서 물리트랜잭션이라고한다.
1. 강의 내용과 관련된 질문인가요? 예 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예 3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예 [질문 내용] 5분 지점에 member와 team을 분리해서 호출하기 위해 프록시를 사용한다라고 이해했는데 9분 53초대에서 보면 getUsername()을 호출했을 때 쿼리가 team까지 조인해서 가져옵니다. getTeam() 을 호출하지 않아도 조인으로 가져오는 거라면 굳이 프록시를 사용해야되는 것인지 의문점이 들었습니다. 제가 이해한 것이 맞는지 궁금합니다.
두 개의 테이블을 OneToOne으로 연관관계를 설정하여 JPA 로 account와 authority테이블을 한 번에 save하는 로직을 강의 내용을 응용하여 개발하고 있습니다. save를 통해 저장하려고 하면 insert 구문에 LOGIN_ID가 두 번 지정되어 쿼리가 날아가는 현상이 있는데 어느 부분이 잘못된 것인지 도움 부탁드립니다.. (쿼리문 예시 insert into LOGIN_ACCOUNT (LOGIN_ID, ~~~, login_id) select SCOPE_IDENTITY() AS GENERATED_KEYS', ~~~, form에서 입력받은 실제 id값) 아래는 소스 내용의 일부입니다.
목록처리(2) 에서 refresh 까지 다 하고 하단에 페이지 넘버를 클릭하면 어떨때는 두번 눌러야 화면이 넘어가는 경우가 있습니다. 브라우저 개발자 도구의 콘솔탭에서 확인해보니 아래 이미지처럼 current가 각기 다르게 두번 불러오는데요(현재 2페이지에서 1페이지를 눌렀을때의 결과 입니다.) 리액트에서 두번 불러오는거에 대해서 언급하신게 있었는데 제가 놓친부분이 있는건지... 이렇게 되는 이유를 모르겠습니다. 혹시 몰라 압축파일로 제 구글 드라이브에 올려놓았습니다. ( https://drive.google.com/drive/folders/1TQxdqkRD8xvXIHzVoI5fp2hm_HZaE0aT ) 감사합니다.
안녕하세요. 앞서 전파기본 강의와 전파예제 강의를 듣고나서 이해가 되지않는 부분이 몇가지 있어서 질문드립니다. 1. 강의 자료중에, 트랜잭션매니저에 커밋하는것이 논리적인 커밋이라면, 실제커넥션에 커밋하는것을 물리 커밋이라고 할수있다 = 내부트랜잭션인 txManager.commit(inner)을 하는것이 논리적인 커밋이고, 외부트랜잭션인 txManager.commit(outer)을 하는것이 물리커밋이다. = 트랜잭션 매니저를 통해 txManager.commit(inner)를 하는것이 논리적인 커밋이고, 트랜잭션 매니저를 통해 txManager.commit(outer)를 하는것이 물리커밋이다. 이렇게 생각하는게 맞을까요?? 2. 1번 질문에 더해서, 트랜잭션 매니저를 통해서 txManager.commit()을 하는것이 논리적인 커밋이라면, 물리적인 커밋은 코드상 어떤것인가요? 외부트랜잭션도 txManager.commit()을 통해 커밋하는거같은데, 이렇게 외부트랜잭션을 커밋하는것이 논리적인 커밋임과 동시에 물리커밋인것인가요?? 3. 외부트랜잭션도 논리트랜잭션이고 내부트랜잭션도 논리트랜잭션인가요? 그래서 이 두가지를 묶어서 물리트랜잭션이라고 하는것인가요??
[질문 내용] 스프링 부트와 JPA 활용 1편에서 제가 작성한 코드에서는 POST: http://localhost:8080/api/v1/members 해당 API가 잘 작동하는데 스프링 부트와 JPA 활용 2편에서 제공하신 강의 소스에서는 작동이 안되어서 문의드립니다. 해당 사진처럼 오류가 발생(상태코드 500) 아래 링크에 있는 내용대로 패키지 이름 변경은 다 했습니다. (javax -> jakarta) https://docs.google.com/document/d/1j0jcJ9EoXMGzwAA2H0b9TOvRtpwlxI5Dtn3sRtuXQas/edit?tab=t.0#heading=h.vfy9wirpglmx
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요. 강사님의 강의를 들으며 코드를 작성하던 도중 해결되지 않는 의문이 생겨 질문게시판에 글을 남깁니다. 강의를 보며 샘플데이터 추가를 위한 코드를 작성하고 나서 QuerydslApplication을 실행하면 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'initMember': Invocation of init method failed 이라는 오류코드가 뜨면서 QuerydslApplication실행이 종료 됩니다. 그런데 김영한 강사님이 올려주신 자료의 코드를 넣어서 실행해 보면 QuerydslApplication 실행이 잘 됩니다. 분명 똑같이 만들었는데 왜 이런 차이가 나는걸까요? 코드도 다른점이 없어보이는데 이러한 차이가 생기는 이유가 궁금합니다. 아래는 제가 작성한 코드(수정 전 샘플데이터)와 김영한 강사님의 코드(수정후 샘플데이터)입니다. package study.querydsl; import jakarta.annotation.PostConstruct; import jakarta.persistence.EntityManager; import jakarta.persistence.PersistenceContext; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import study.querydsl.entity.Member; import study.querydsl.entity.Team; //샘플데이터 추가 /*수정 전 샘플데이터*/ /*@Profile("local") @Component @RequiredArgsConstructor public class InitMember { private final InitMemberService initMemberService; @PostConstruct public void init() { initMemberService.init(); } @Component static class InitMemberService { @PersistenceContext private EntityManager em; @Transactional private void init() { Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); em.persist(teamA); em.persist(teamB); for (int i = 0; i < 100; i++) { Team selectedTeam = i % 2 == 0 ? teamA :teamB; em.persist(new Member("member" + i, i, selectedTeam)); } } } }*/ /*수정후 샘플데이터*/ @Profile("local") @Component @RequiredArgsConstructor public class InitMember { private final InitMemberService initMemberService; @PostConstruct public void init() { initMemberService.init(); } @Component static class InitMemberService { @PersistenceContext EntityManager em; @Transactional public void init() { Team teamA = new Team("teamA"); Team teamB = new Team("teamB"); em.persist(teamA); em.persist(teamB); for (int i = 0; i < 100; i++) { Team selectedTeam = i % 2 == 0 ? teamA : teamB; em.persist(new Member("member" + i, i, selectedTeam)); } } } }
[질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예) [질문 내용] 안녕하세요 강사님. 강의 수강 중에 질문 드려봅니다. 섹션9. 프록시 1편 11분경에, 코드를 그대로 따라 치고 실행해보았는데, 실제로 강의와 다르게 동작하는 거 같습니다. try { Member member = new Member(); member.setUsername("hello"); em.persist(member); em.flush(); em.clear(); Member findMember = em.getReference(Member.class, member.getId()); System.out.println("findMember.id = " + findMember.getId()); System.out.println("findMember.username = " + findMember.getUsername()); tx.commit(); } catch (Exception e) { tx.rollback(); } finally { em.close(); } 위와 같이 코드를 실행했는데요, Hibernate: select next value for Member_SEQ Hibernate: /* insert for hellojpa.Member */insert into Member (USERNAME, MEMBER_ID) values (?, ?) Hibernate: select m1_0.MEMBER_ID, t1_0.TEAM_ID, t1_0.name, m1_0.USERNAME from Member m1_0 left join Team t1_0 on t1_0.TEAM_ID=m1_0.TEAM_ID where m1_0.MEMBER_ID=? findMember.id = 1 findMember.username = hello 콘솔에서는 이렇게 나옵니다. findMember.id는 쿼리 실행 필요 없이 바로 출력 가능해야 할 거 같은데 쿼리가 먼저 실행되는 이유가 뭘까요? (username을 꺼내쓰는 부분을 제거하고 실행해봐도 쿼리가 실행되고 id를 출력합니다.)
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 강의에서 order 테이블을 조회하면 id값이 4, 11로 나오는데 저는 1, 2로 나옵니다. 아무리 생각해봐도 4, 11로 나올 이유가 없어보이는데 왜 4,11로 나오는지 궁금합니다
안녕하세요. 그런데 섹션3 의 'Querydsl 검색처리' 영상을 다 보고 TDD 테스트를 돌리는데 계속 아래와 같은 에러가 납니다.. 몇일동안 찾아봤는데도 아예 해결이 되지 않아서 여기에 질문드리게 됐네요.. ㅠㅠ 혹시 몰라 콘솔탭에 있는거 전부 다 복사해 왔습니다. 강의를 파트별로 정리하면서 공부하고 있어서 앞에 Ex01 이런식으로 이름이 붙어 있습니다. 왜 안되는지 도저히 모르겠어요.. (게시글이 10000자 이상 안써진다고 해서 댓글에 다음 메세지들 쓰겠습니다.) (혹시 몰라서 대댓글로 코드들도 남깁니다.) . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.3.6) 2024-12-02T05:13:22.977+09:00 INFO 7780 --- [ restartedMain] c.zerock.apiserver.ApiserverApplication : Starting ApiserverApplication using Java 17.0.13 with PID 7780 (C:\Users\hykim\Desktop\apiserver\build\classes\java\main started by hykim in C:\Users\hykim\Desktop\apiserver) 2024-12-02T05:13:22.993+09:00 INFO 7780 --- [ restartedMain] c.zerock.apiserver.ApiserverApplication : No active profile set, falling back to 1 default profile: "default" 2024-12-02T05:13:23.010+09:00 INFO 7780 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2024-12-02T05:13:23.010+09:00 INFO 7780 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2024-12-02T05:13:23.322+09:00 INFO 7780 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2024-12-02T05:13:23.353+09:00 INFO 7780 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 28 ms. Found 1 JPA repository interface. 2024-12-02T05:13:23.632+09:00 INFO 7780 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8080 (http) 2024-12-02T05:13:23.638+09:00 INFO 7780 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2024-12-02T05:13:23.638+09:00 INFO 7780 --- [ restartedMain] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.33] 2024-12-02T05:13:23.665+09:00 INFO 7780 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2024-12-02T05:13:23.665+09:00 INFO 7780 --- [ restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 655 ms 2024-12-02T05:13:23.733+09:00 INFO 7780 --- [ restartedMain] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2024-12-02T05:13:23.761+09:00 INFO 7780 --- [ restartedMain] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.5.3.Final 2024-12-02T05:13:23.777+09:00 INFO 7780 --- [ restartedMain] o.h.c.internal.RegionFactoryInitiator : HHH000026: Second-level cache disabled 2024-12-02T05:13:23.936+09:00 INFO 7780 --- [ restartedMain] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer 2024-12-02T05:13:23.951+09:00 INFO 7780 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2024-12-02T05:13:23.989+09:00 INFO 7780 --- [ restartedMain] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection org.mariadb.jdbc.Connection@6303bda2 2024-12-02T05:13:23.990+09:00 INFO 7780 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2024-12-02T05:13:24.411+09:00 INFO 7780 --- [ restartedMain] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) 2024-12-02T05:13:24.438+09:00 INFO 7780 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2024-12-02T05:13:24.535+09:00 WARN 7780 --- [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ex04_10_TodoServiceImpl' defined in file [C:\Users\hykim\Desktop\apiserver\build\classes\java\main\com\zerock\apiserver\service\Ex04_10_TodoServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'ex04_13_TodoRepository' defined in com.zerock.apiserver.repository.Ex04_13_TodoRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract org.springframework.data.domain.Page com.zerock.apiserver.repository.search.Ex04_11_TodoSearch.search1(com.zerock.apiserver.dto.Ex04_7_PageRequestDto); Reason: Paging query needs to have a Pageable parameter; Offending method: public abstract org.springframework.data.domain.Page com.zerock.apiserver.repository.search.Ex04_11_TodoSearch.search1(com.zerock.apiserver.dto.Ex04_7_PageRequestDto) 2024-12-02T05:13:24.535+09:00 INFO 7780 --- [ restartedMain] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default' 2024-12-02T05:13:24.537+09:00 INFO 7780 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2024-12-02T05:13:24.538+09:00 INFO 7780 --- [ restartedMain] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. 2024-12-02T05:13:24.539+09:00 INFO 7780 --- [ restartedMain] o.apache.catalina.core.StandardService : Stopping service [Tomcat] 2024-12-02T05:13:24.545+09:00 INFO 7780 --- [ restartedMain] .s.b.a.l.ConditionEvaluationReportLogger : Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. 2024-12-02T05:13:24.556+09:00 ERROR 7780 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'ex04_10_TodoServiceImpl' defined in file [C:\Users\hykim\Desktop\apiserver\build\classes\java\main\com\zerock\apiserver\service\Ex04_10_TodoServiceImpl.class]: Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'ex04_13_TodoRepository' defined in com.zerock.apiserver.repository.Ex04_13_TodoRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Could not create query for public abstract org.springframework.data.domain.Page com.zerock.apiserver.repository.search.Ex04_11_TodoSearch.search1(com.zerock.apiserver.dto.Ex04_7_PageRequestDto); Reason: Paging query needs to have a Pageable parameter; Offending method: public abstract org.springframework.data.domain.Page com.zerock.apiserver.repository.search.Ex04_11_TodoSearch.search1(com.zerock.apiserver.dto.Ex04_7_PageRequestDto) at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:795) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:237) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1375) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1212) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) ~[spring-beans-6.1.15.jar:6.1.15] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:971) ~[spring-context-6.1.15.jar:6.1.15] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.15.jar:6.1.15] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.6.jar:3.3.6] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.6.jar:3.3.6] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.6.jar:3.3.6] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.6.jar:3.3.6] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.6.jar:3.3.6]
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. 안녕하세요 김영한님 ! REQUIRES_NEW는 완전히 물리적으로 트랜잭션이 분리되어 REQUIRED(A 메서드)에서 REQUIRES_NEW(B 메서드)를 호출 했을 때 B 메서드에 발생한 예외가 A 메서드에 전파되지 않는다고 이해했습니다. 실제 확인을 위해 아래 코드를 구성해 @Service @RequiredArgsConstructor public class MeetingService { private final MeetingRepository meetingRepository; private final MemberService memberService; @Transactional public void save() { meetingRepository.save(new Meeting("스터디 모임", LocalDate.now(), LocalTime.now(), "AB3AS2EG")); memberService.save(); } @Transactional(readOnly = true) public List<Meeting> findAll() { return meetingRepository.findAll(); } } @Service @RequiredArgsConstructor public class MemberService { private final MemberRepository memberRepository; @Transactional(propagation = Propagation.REQUIRES_NEW) public void save() { memberRepository.save(new Member("김철수")); throw new IllegalArgumentException(); } @Transactional(readOnly = true) public List<Member> findAll() { return memberRepository.findAll(); } } 아래 테스트 코드로 테스트를 진행했습니다. @Test void test() { assertThatThrownBy(() -> meetingService.save()) .isInstanceOf(IllegalArgumentException.class); // 롤백 여부 확인 List<Meeting> meetings = meetingService.findAll(); List<Member> members = memberService2.findAll(); assertThat(meetings).isEmpty(); assertThat(members).isEmpty(); } 결과를 로그로 분석해보니 MemberService의 트랜잭션은 독립적으로 롤백 발생한 예외가 MeetingService로 전파 전파된 예외로 인해 MeetingService의 트랜잭션도 롤백 이런식으로 흐름이 진행됐습니다. 제가 추측하기로는 물리적으로 분리는 되어 있지만 하나의 스레드에서 생긴 커넥션이고 자바의 예외 전파 메커니즘에 따라 A 메서드에서 호출한 B 메서드의 예외가 A 메서드에 전파된 것이 아닌가 생각을 했는데요 REQUIRES_NEW 사용 시 예외가 전파 되지 않는다. 라고 이해를 했어서 제가 실험한 결과가 맞는지 간과한 부분이 있었던 것인지 궁금합니다 !
연관관계가 없는 조인에 대해 설명하신 부분에 대해 문의 드립니다. 보통 연관관계가 없다고 한다면 외래키로 연결되지 않는 두개의 테이블 이라고 생각할텐데 강의에서는 두 테이블 간 연관관계는 존재하고 연관관계의 컬럼으로 조인하는것이 아닌 , 다른 컬럼으로 조인하는것을 연관관계가 없는 조인이라고 설명하시는것 같아 혼동이 옵니다. 연관관계가 없는 조인 의 경우 두 테이블 간에 외래키가 없는경우에도 연관관계 없는 조인이 가능한건지 아니면 외래키는 있지만 외래키 조인이 아닌 다른 컬럼으로 조인할수 있는것을 연관관계가 없는 조인이라고 하시는건지 알려 주시면 감사하겠습니다.
안녕하세요 지식공유자님. 강의에서 JwtProvider 에 @Component 어노테이션을 선언하셔서 스프링이 관리하도록 의도하신 것 같습니다. 그런데, 함수에 static 을 모두 붙이시고, 사용하는 쪽에서는 bean 으로 등록 하지 않고 static util 처럼 사용하시는 것을 확인했습니다. 질문은 두가지 입니다. @Component 를 선언하셨음에도 static 메서드를 authService 에서 사용하신 이유가 있으신지. 빈으로 만들고서도 static 함수로 사용하는 것에 이점이 있는 것인지. 답변 부탁드리겠습니다. 감사합니다.