월 19,800원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨스프링 DB 2편 - 데이터 접근 활용 기술
Test 코드에서 @Transactional 의 자동 롤백 유무 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요! 강의듣다 궁금한점이 생겨 질문 드립니다.섹션 9 트랜잭션 적용 확인 강의 약 10분쯤에서, Test 코드에서 @Transactional 을 남긴 메서드를 실행했는데, 커밋된 로그는 남지 않고, 컴플리트 된 로그만 남아있다고 설명하시는 부분에서 질문이 있습니다.지난번 강의에서 Test 코드에서 @Transactional 을 남기면 이건 Test이기 때문에 자동으로 롤백 된다는 설명을 하셨던 거로 기억하는데,이게 @Test 어노테이션이 붙은 메서드만 해당해서, 강의중 나온 메서드에선 적용이 안된는걸까요? 강의에선 Test코드에서 BasicService 를 static 클래스로 만들고, 해당 메서드에서 @Transactional 을 사용하는 메서드를 선언했습니다.아님 단순 로그가 커밋이나 롤백을 표시해주지 않기 때문에 그 내용을 설명해주신 걸까요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
spring.profiles.active=test 의 필요성
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]test 패키지의 application.properties에서 spring.profiles.active=test를 주석처리하고 실행해보았을때 아래와 같은 로그가 나옵니다. h.i.ItemServiceApplicationTests : No active profile set, falling back to 1 default profile: "default"test 패키지의 application.properties에 profile을 지정해주는 이유는 local 프로필로 인식되지않게하기 위함인데 위와 같은 결과가 나온다면 test 패키지의 application.properties에 profile을 따로 지정해줄 필요가 없지않을까요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
spring data jpa동적 업데이터에 관한 질문입니다.
안녕하세요 진짜 잘 보고 있습니다.저 spring data jpa공부하던 중 질문이 있어 글 남깁니다.예를 들어update memberset pass=?, addr=?, memo=?where id=?이런 식으로 sql이 만들어지고 pass,addr,memo는 사용자가 뭘 입력하냐에 따라서 변경하기 위한 입력값이 들어오는 경우도 있고 없을 수도 있습니다.한 사용자는 pass만 변경할 수도 있고 한 사용자는 memo만 변경할 수 있다고 가정할때 mybatis같은 경우 값이 설정된 값만 업데이트가 됐던 거 같은데jpa는 어떻게 해야 할까요?@DynamicUpdate를 추가해도......member.setId(id);member.setAddr(addr);member.setMemo(memo);repository.save(member);로 업데이트를 하면 id,addr,memo에 대한 업데이트 코드가 만들어집니다. 이거 동적 처리하는게 querydsl말고는 방법이 없는지 여쭤봅니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
프록시 호출 관련 질문
안녕하세요 강사님좋은 강의 감사드립니다.참여했던 실무 프로젝트에서 @Transactional 을 잘 이해하지 못한 채 사용했던 적이 있습니다.특정 서비스의 한 메소드에서 @Transactional을 선언하고 해당 메소드가 여러 작업을 하기 때문에 다른 메소드를 호출하는 방식이었습니다.이때 저는 트랜잭션의 특징을 잘 몰라서 두 메소드에 다 @Transactional을 선언했었습니다.예시)@Transactionalpublic void ex1() {...// 로직 수행 후 다른 메소드 호출ex2();}@Transactionalpublic void ex2() {// 로직 수행}테스트를 하는데 로직 수행중 ex1에서 에러가 나든 ex2에서 에러가 나든 트랜잭션 롤백이 안됐었는데 이런 케이스는 무엇이 원인인지 알려주실 수 있나요?강의에서처럼 ex1이 아예 @Transactional이 선언되어 있지 않았다면 롤백이 안되는게 맞다고 생각이 드는데 저는 두 메소드 다 선언했었거든요,,확인해주시고 답변 주시면 정말 감사드리겠습니다ㅠ(혹시나 해서 강의 코드의 externalCall 메소드에 트랜잭션 선언해보고 테스트 돌려봤는데 트랜잭션 적용 되더라고요)+추가 질문으로 이런 경우에는 ex1 메소드에만 @Transactional을 선언하면 될까요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
소스코드안에 itemservice-db-start, itemservice-db
itemservice-db-start를 itemservice-db로 바꾸라 하셨는데 이미 itemservice-db가 있었습니다.그래서 itemservice-db로 intellij를 켰는데 안되고 itemservice-db-start로 하니까 되었습니다.두개 다 필요한것인지 궁금합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
3번째 tx가 1번째 tx에 참여하게 할 수 있나요?
안녕하세요. 현재 스프링 트랜잭션 전파7을 듣는 예제에서 제가 3번째 트랜잭션을 만들어봤습니다. 2번째 트랜잭션은 REQUIRES_NEW이므로 새로운 커넥션이 생성되고 1번째 커넥션은 지연됩니다. 그 결과 3번째 트랜잭션을 만들면 2번째 트랜잭션에 참여하는 것처럼 보입니다. 그러면 2번째 트랜잭션을 사용하다가 잠시 2번째를 지연시키고, 다시 1번째를 사용하면서 3번째가 이에 참여하게 만들었다가 다시 2번째를 사용하도록 만들 수도 있나요? [예시][tx 1] 생성[tx 1] 지연, [tx 2] 생성[tx 2] 지연, [tx 1] 사용[tx 3] 생성, [tx 1]에 참여[tx 3]과 [tx 1] 커밋[tx 2] 커밋 이런 상황을 만날 일은 없어보이고, 이런 문제상황은 다른 해결방법이 있겠지만 트랜잭션 매니저로 위와 같은 상황을 해결할 수 있는지가 궁금합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
로그에 대해 실무에서 저장방법
[질문 내용]실무에서는 로그를 파일로 저장하나요? 아니면 데이터베이스에 저장하나요? 궁금하네요
- 해결됨스프링 DB 2편 - 데이터 접근 활용 기술
애너테이션 대신 AOP로 트랜잭션 설정하면 어떤가요?
@Transactional 애너테이션을 사용하는 대신 예를 들어 비즈니스 로직이 담겨있는 service 계층의 모든 메서드에 AOP를 통해 일괄적으로 트랜잭션을 적용한다면 어떤 문제가 있을까요?생각으로는 성능 상 부하가 생길 것 같지만 그 영향이 어느 정도인지는 또는 다른 어떤 단점들이 있을지 가늠이 잘 되지 않습니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
jdbc 탬플릿으로 findById로 조회 시 정상적으로 반환은 되지만 AUTO_INCREMENT 한 컬럼이 null인 상황입니다.
안녕하세요. 질문 제목에 관해 말씀드리겠습니다.상황은 이러합니다.member table에 jdbc 탬플릿으로 잘 저장하고 잘 조회하나 테스트하는 중으로 테이블은 아래와 같습니다.CREATE TABLE member ( member_id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(45), login_id VARCHAR(45), password VARCHAR(45), email VARCHAR(45) UNIQUE ); 레포지토리는 아래와 같습니다.package com.boaz.sketch2fashion.repository.member; import com.boaz.sketch2fashion.domain.Member; import com.boaz.sketch2fashion.repository.member.MemberRepository; import com.boaz.sketch2fashion.repository.member.dto.MemberSaveDTO; import com.boaz.sketch2fashion.repository.member.dto.MemberUpdateDTO; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.BeanPropertyRowMapper; import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Repository; import javax.sql.DataSource; import java.security.Signature; import java.util.List; import java.util.Map; @Slf4j @Repository public class JdbcMemberRepository implements MemberRepository { private final NamedParameterJdbcTemplate template; public JdbcMemberRepository(DataSource dataSource) { this.template = new NamedParameterJdbcTemplate(dataSource); } @Override public Member save(Member member) { String sql = "insert into member(name, login_id, password, email) values(:name, :loginId, :password, :email)"; KeyHolder keyHolder = new GeneratedKeyHolder(); SqlParameterSource param = new BeanPropertySqlParameterSource(member); template.update(sql, param, keyHolder); long key = keyHolder.getKey().longValue(); member.setId(key); return member; } @Override public Member findById(Long id) { String sql = "select * from member where member_id = :id"; Map<String, Object> param = Map.of("id", id); Member member = template.queryForObject(sql, param, memberRowMapper()); return member; } @Override public Member findByLoginId(String loginId) { String sql = "select * from member where login_id = :loginId"; Map<String, Object> param = Map.of("loginId", loginId); Member member = template.queryForObject(sql, param, memberRowMapper()); return member; } @Override public void update(Long id, MemberUpdateDTO memberUpdateDTO) { String sql = "update member set name = :name, login_id = :loginId, password = :password, email = :email where id = :id"; SqlParameterSource param = new MapSqlParameterSource() .addValue("name", memberUpdateDTO.getName()) .addValue("loginId", memberUpdateDTO.getLoginId()) .addValue("password", memberUpdateDTO.getPassword()) .addValue("email", memberUpdateDTO.getEmail()); template.update(sql, param); } @Override public void delete(Long id) { String sql = "delete from member where id = :id"; Map<String, Object> param = Map.of("id", id); template.update(sql, param); } private RowMapper<Member> memberRowMapper() { return BeanPropertyRowMapper.newInstance(Member.class); } } 테스트 코드는 아래와 같습니다. @Test void findById() { // given Member memberA = new Member("a", "a", "a", "a"); // when Member saveMember = memberRepository.save(memberA); log.info("{}", saveMember.getId()); Member findMember = memberRepository.findById(saveMember.getId()); log.info("{}", saveMember.getId()); log.info("{}", findMember.getId()); // then assertThat(saveMember).isEqualTo(findMember); } memberA를 저장하고 findById로 찾아서 saveMember와 findMember의 내용물이 같은지 확인하는 코드입니다. memberA를 저장하면 pk는 1이 될 것이라고 생각하여 findById(saveMember.getId());로 H2 DB에서 pk가 1인 행을 찾아 findMember로 반환하여 isEqualTo를 하려고 했습니다. 결과 이미지saveMember의 getId 1로 findMember를 찾았는데 findMember의 getId는 null입니다.따라서 테스트가 실패합니다. 테스트 환경H2 스프링 내장 DB, jdk 17 항상 질문 답변 해주셔서 정말 감사합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
데이타소스없이 JpaRepository 작동하는 이유
안녕하세요.문득 스프링 데이타 JPA로 테스트 진행 중 없는 테이블을 만들어주는 기능을 보니 db에 커넥션이 없이 이 모든 게 진행된다는 게 갑자기 낯선 느낌이 들었습니다.쿼리를 만들고 날리는 과정이 커넥션 여부와 관계없이 실행되는 것인가요? 어떻게 데이타소스 없이 작동하는건지 조금 이상하다는 생각이 듭니다.트랜잭션과 관련있는 내용은 아니지만 강의에서 설명을 들으니 문득 궁금해져 질문 드립니다.감사합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
테스트에서 @Slf4j 를 따로 선언하는 이유가 궁금합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 테스트 클래스에 @Slf4j를 붙이고 그 아래 static 클래스에도 붙이셔서 그 이유가 궁금합니다.테스트 클래스에만 선언하면 되지않나? 라는 생각이 들어서 static 클래스에 있는 @Slf4j를 지워 보고 했는데 로그는 잘 나오더라구요.혼자 찾아보려 했는데 잘 안돼서 질문남깁니다 ㅠ
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
스프링 데이터 jpa
스프링 데이터 jpa 사용 시에 삭제하는 기능을 구현하면findById로 삭제할 엔티티를 찾은 다음에 delete하는 것그냥 바로 삭제할 id를 가지고 native쿼리 1번은 두번 db를 들락거리고2번은 한번 db를 들락거리는데2번이 좋은것 아닌가요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
ItemMapper Bean
[질문 내용]MyBatisConfig 에서 private final ItemMapper itemMapper; 이 부분이 bean을 찾을 수 없다고 하는데 테스트는 정상적으로 동작하는 이유가 궁금합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
ItemMapper Bean을 찾을 수 없습니다.
1. MyBatisConfig 클래스에서 ItemMapper 빈을 찾을수 없습니다. IDE 에러일줄 알았는데 Application을 실행해보면 에러가 뜨네요.2.현재 ItemServiceApplication의 빈 탐색범위가 hello.itemservice.web으로 되어있는데 그렇다면은 Controller 빈만 주입받고, Service, Repository등의 클래스는 전부 Configuration 어노테이션 이용해서 주입받는건가요? 만약에 맞다면 실제로 ItemMapper는 어디서 주입받는거에요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
트랜잭션 AOP주의사항 - 해결방법 문의
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]영한님께서 이번 강의에서 트랜잭션 프록시 객체에서 외부메서드를 호출하고, 진짜 객체의 외부 메서드에서 자기 자신의 내부 메서드를 호출할 때 내부 메서드에는 @Transactional을 설정해도 트랜잭션이 적용되지 않는 점 이해 했습니다. 강의에서 이 부분을 해결하기 위해 별도의 클래스를 만들고, Bean으로 주입(이 경우 프록시객체가 Bean으로 등록)해서 프록시 객체가 @Transactional 메서드를 호출하는 방식으로 해결하는 점도 이해했습니다. 스프링 MVC강의에서 빈 스코프 문제(프로토타입과 싱글톤 Bean을 같이 사용할 때 문제점)을 해결하기 위해 Dependency Lookup을 사용하신 방법이 떠올라 V3테스트코드를 작성해보았습니다. @Slf4j @SpringBootTest public class InternalCallV3Test { @Autowired CallServie callServie; @Test void printProxy() { log.info("callService class={}", callServie.getClass()); } @Test void internalCall() { callServie.internal(); } @Test void externalCall() { callServie.external(); } @TestConfiguration static class InternalCallV1TestConfig { @Bean CallServie callServie() { return new CallServie(); } } @Slf4j static class CallServie { @Autowired private ObjectProvider<CallServie> selfProvider; public void external() { log.info("call external"); printTxInfo(); CallServie self = selfProvider.getObject(); log.info("self class={}", self.getClass()); self.internal(); } @Transactional public void internal() { log.info("call internal"); printTxInfo(); } private void printTxInfo() { boolean txActive = TransactionSynchronizationManager.isActualTransactionActive(); log.info("tx active={}", txActive); boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly(); log.info("tx readOnly={}", readOnly); } } } 실행 결과는 다음과 같습니다.DL을 이용해서 스프링 컨테이너에서 프록시를 가져와서, 프록시의 메서드를 호출하면 트랜잭션이 적용되는 것 처럼 보입니다. 질문1) 이 방법으로 트랜잭션이 적용되는게 맞을까요?2) 이 방법을 혹시 스프링-고급편에서 다루나요?3) 1번 질문이 맞다면 클래스를 새로 만들고, 메서드를 옮기는 비용보다 DL로 프록시객체를 찾아오는 비용이 더 쌀 것 같은데, 둘 중 어느 방법이 선호되는 편인가요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
도메인 모델을 나눌 때 중간테이블
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 네니오2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 네3. 질문 잘하기 메뉴얼을 읽어보셨나요? 아니오[질문 내용]현재 다니고 있는 회사에서는 Pojo 모델과 Entity 모델을 나누어서 관리하고 있습니다. 이 때, M:N 테이블을 나누어 주는 중간 테이블은 POJO 모델을 만들지 않고 infrastructure 레이어에 위치시키고 도메인 레이어에는 노출시키지 않으려고 하고 있는데요, 이 때 해당 중간 테이블을 구분되는 두 도메인중 어느쪽에 위치시켜야할지 고민이 되어 질문을 남깁니다.보통 이러한 중간 테이블에 대응하는 Entity는 어느 패키지에 두는지 기준이 궁금합니다.추후 데이터베이스를 나누었을 때 이러한 중간 테이블을 어디에 위치 시켜야할지 아니면 서로 다른 데이터베이스에 중간테이블을 중복 저장 시켜야할지 궁금합니다.양 쪽 모두에서 간간히 조회에 활용 됩니다. 위 방법 자체에 문제가 있다고 느끼신다면 어떤 대안이 있을지 남겨주시면 감사하겠습니다. 감사합니다.
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
JPA를 이용해서 springboot 시작 이후 Datasource설정
안녕하세요 강의 너무 잘 듣고 있습니다.개인 프로젝트를 하고 싶어서 궁금한게 생겼는데요위에 사진처럼 Datasource를 application.properties에 설정한 값 말고 트랜잭션 시작하기 전에 새로 데이터베이스 커넥션을 만들어서 처리해주고 싶습니다.jpa를 이용하고 싶은데 .properties말고 트랜잭션 시작전에 커넥션을 만들어서 JPA를 이용하려면 어떻게 해야될지 잘 모르겠습니다.autoconfiguration에서 "spring.datasource"로 들어오는 properties 설정값이나JpaBaseConfiguration으로 설정된 값을 트랜잭션 시작전에 connection을 새로 설정해서 처리할 수 있는지도 궁금합니다.
- 해결됨스프링 DB 2편 - 데이터 접근 활용 기술
실무에서의 test DB 구성 방식이 궁금합니다.
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]기존 질문 답변을 모두 읽어 보았지만, 실무에서의 테스트 db 세팅 방법의 정확한 방향이 잡히지 않아 질문드립니다.테스트 db 환경을 로컬로도 구축하신다는 의미가 예를 들어 mysql을 사용하는 경우 로컬 mysql db에 실운영 mysql db 스키마를 등록하고 이를 test db로 사용하신다는 의미로 이해해도 될까요??h2 임베디드 db 만을 신뢰하여 통합테스트와 같은 테스트를 실행하기에는 test의 신뢰도가 떨어진다는 내용들을 봐서 실제 사용하는 db를 쓰는 것이 맞을 것 같기는 한데 위와 같은 방식으로 하면 배보다 배꼽이 더 커질 것 같아 걱정입니다.배민과 같은 좋은 기준을 가진 회사의 방식이 궁금하고 이를 적용하고 싶은데 답변만으로 어려우시다면 추후 테스트 코드 강의에 이를 반영하여 주시길 바라는 마음에서도 질문 남겨봅니다.(테스트 코드 강의 나오면 바로 구매할께요!)
- 해결됨스프링 DB 2편 - 데이터 접근 활용 기술
jpa 연관관계 질문
안녕하세요. 현재 저는 jpa를 공부하면서 회원 -> 게시글 -> 댓글을 구현하고 있습니다. 강의를 보고 대략적으로 게시글@many to one (lazy)Member member@one to manyList<Comment> comments = new array 로 구현하였는데 em.find(게시글, id)을 하면member는 다 모든 필드가 다 null인 객체가 들어오고comments는 PersistentBag 객체로 되어 있고 내부에 comment들이 다 들어옵니다. (디버거로 확인하였습니다.) 쿼리를 보니select * from 게시글 where id = idselect * from 댓글 where 게시글id = 게시글id이렇게 두개가 나가더라구요.... 왜 하나는 자동쿼리가 나가고 하나는 안나갈까요?
- 미해결스프링 DB 2편 - 데이터 접근 활용 기술
트랜잭션 내부호출
강의에서는 트랜잭션 내부호출을 해결하기 위해 클래스를 분리하여 외부에서 호출하는 방식으로 하셨는데 내부 호출을 하는 메소드에 @Transactional말고 호출을 하는 쪽에서 @Transactional을 설정하는 것은 어떻게 생각하시나요?정밀하게 트랜잭션이 적용되는 곳만 설정하는게 더 나은 방법일까요?