묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
repository관련 질문
repository 코드입니다. private static long sequence = 0L; private DataSource dataSource; public DbMemberRepository(DataSource dataSource) { this.dataSource = dataSource; } public void save(String memberId, String password) throws SQLException { String sql = "insert into member(id, member_id, password) values(?,?,?)"; try { Connection con = null; PreparedStatement pstmt; con = getConnection(); pstmt = con.prepareStatement(sql); pstmt.setLong(1, ++sequence); pstmt.setString(2, memberId); pstmt.setString(3, password); log.info(String.valueOf(sequence)); pstmt.execute(); } catch (SQLException e) { throw new SQLException("sql exception"); } }@Test void save() throws SQLException { memberRepository.save("test1", "test1!"); //memberRepository.save("test2", "test2!"); } 위 코드에서 save테스트를 돌릴 때 save test를 두번 누르면 sequence(id)가 1, 2로 저장된다고 생각했는데 에러가 나고 test코드내에서 memberRepository.save를 두번적으면 되더라고요. 왜 전자처럼 두번누르는 것은 예외가 나나요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
DB 변경
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]DB를 H2에서 MySql로 변경하고 싶으면섹션 1의 예제에서는 ConnectionConst 클래스의 URL을 MySql 관련 URL로 바꾸기만 하면 되나요?
-
해결됨토비의 스프링 부트 - 이해와 원리
자동구성 관련해서 질문드립니다.
안녕하세요 토비님.자동구성하는 방법에서 궁금한점이 있어 글드립니다.@MyAutoConfiguration 과 같이 imports 를 통해 자동구성을 설정해줄때 Configuration 외에 Service 혹은 Repository(JPA) 등 여러 다른 Component 들이 있을때는 어떤방식으로 자동구성을 해줄수 있을까요?단순히 생각했을때는 import 에 모두 기입하거나 @Import 의 방법이 생각이 들긴한데 너무 많은 정의가 있을경우에는 좋은방법이 있을까해서 질문드립니다.@ComponentScan 을 사용하는 방법은 권장하지 않는다고 들었습니다. (아마 스캔에 따른 불명확함 때문이 아닌가 생각합니다)
-
해결됨토비의 스프링 부트 - 이해와 원리
신규강의와 스프링 3.1 책관련 질문드립니다
다른 질문글에서 스프링 신규강의 오픈 예정인 답변을 보았습니다.기존에 출판하신 스프링 3.1 책과 새로 오픈할 강의 같이 봐도 될까요? 강의만 보는걸 추천하시나요?
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
delete 오류
안녕하세요 트랜잭션 적용1 강의 10분 40초 정도에서 쿼리로 delete from member를 적었는데 Timeout trying to lock table "MEMBER"; SQL statement:delete from member [50200-224] HYT00/50200 (도움말) 이러한 오류가 떠서요 어떻게 하면 될까요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
javax.transaction.Transactional 질문
안녕하세요.javax.transaction.Transactional annotation에 대해 추가 질문드립니다. @Transactional annotation은 총 2가지가 있습니다.Spring에서 제공: org.springframework.transaction.annotation.TransactionalJava에서 제공: javax.transaction.Transactional 강의에서는 spring에서 제공하는 annotation을 사용으로 추천해주셨고, 대부분 org.springframework.transaction.annotation.Transactional으로 사용을 하더라구요. 직접 찾아본 바로는 두가지 모두 트랙잭션 자체에 대한 동작은 동일하지만, spring에서 제공하는 Transactional이 더 많은 부가 기능을 가지고 있어 사용을 권장한다고 하네요. 이렇게 이해하고 넘어가면 될까요?!의견이 궁금해서 질문드립니다.
-
해결됨토비의 스프링 부트 - 이해와 원리
안녕하세요. 토비님
안녕하세요. 혹시 다음 강의 계획에 대해 여쭤봐도 될까요? 스프링 학습을 좀 더 깊게하고 싶어 토비의 스프링3.1을 구매하려고 했는데 혹시라도 조만간 토비님의 강의가 나온다면 강의부터 보고 싶은 마음에 질문 드립니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
xml파일과 properties에 로그레벨 질문
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n</pattern> </encoder> </appender> <root level="DEBUG"> <appender-ref ref="STDOUT" /> </root> </configuration>이 코드를 쓰면 DataSource 커넥션풀에서 별도의 Thread가 동작하는 코드를 볼수가 있는데 application.properties에서 logging.level.root=debug 로 설정을하니까 안보이더라구요... 왜 안되는지 이유를 알수잇을까요?
-
미해결토비의 스프링 부트 - 이해와 원리
GenericWebApplicationContext : boot 2.* 와 3.* 차이
안녕하세요 토비님 토비님에 강의 어노테이션 매핑 정보 사용강의 내용 중 GenericWebApplicationContext를 사용해서 @RequestMapping이 스프링 부트 2.7에서는 정상적으로 동작을 하는데요 스프링 3.* 에서는 404가 뜨는 상황입니다. GenericWebApplicationContext가 뭔가 변한걸까요? 로그를 보면 3.*는 아예 리플래쉬가 안되는것 같은 느낌이 듭니다. 감사합니다.
-
해결됨토비의 스프링 부트 - 이해와 원리
섹션 9 세번째 강의 문의
안녕하세요. 강의 정말 잘 보고 있습니다. 다름이 아니라 섹션9 세번째 강의 jdbc transaction manager 설정 및 테스트 하는 과정에서 마지막 부분에 첫번째 테스트는 통과 하지만 두번째 테스트는 실패합니다라고 설명 해주셨는데요, 아래 실제 콘솔을 보면 두번째 테스트가 성공 하고 첫번째 테스트가 실패 하고 있습니다. 그래서 궁금한 점은 junit에서 각 테스트는 코드상에서 위아래와 무관 하게 각 테스트 메서드가 병렬적으로 동작 하고, 그 과정에서 먼저 디비를 터치하고 트랜잭션을 완료 한 테스트가 먼저 성공 하는 것 인지 궁금 합니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
예외처리
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]강의에서 예외를 직접 잡을 일이 별로 없다고 말씀해주셨는데, 예를 들어 회원가입을 할 때 중복된 아이디를 입력해서 오류가 발생해서 오류 메시지를 보여줘야 하는 경우는 개발자가 잡아야 하는 예외라고 봐도 될까요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
왜 계속 커넥션 풀 내 새로운 커넥션을 사용하는 건가요?
트랜잭션 매니져 사용하는 service 테스트 하는 MemberServiceV3_1Test 실행시키면 나오는 로그입니다. 제가 이해가 안가는 것은find by id , save, delete 같은 repository 함수들은 항상 close를 마지막으로 끝내잖아요?그럼 항상 커넥션 하나 사용한 다음에 다시 pool에 반환되니, 매번 conn0만 사용해야하는거 아닌가요? 그리고 지금 여러명이 DB에 들락거리는 것도 아니고 저 혼자만 테스트해보는건데왜 한개의 커넥션이 아닌 여러개의 커넥션을 사용하게 되는 건가요? 커넥션 풀에 있는 다른 커넥션을 사용해야한다는 것은 특정 커넥션들이 트랜잭션 상태에 있기 때문에어쩔 수 없이 풀에 남아있는 커넥션을 사용해야하는거잖아요?근데 저 혼자만 테스트하면 매번 DB작업한 다음에 커넥션을 다시 커넥션풀에 갖다 놓을텐데(모든 repository 함수들이 close로 끝나기 때문에) 왜 conn0이 아닌 5 6 7번까지 사용하게 되는걸까요??
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
DriverManagerDataSource 질문
이 DriverManagerDataSource가 커넥션 풀은 아닌거죠? 매번 getConnection할때마다 새 커넥션을 생성하긴 하지만URL USERNAME PASSWORD 를 매번 전달하지는 않아도 되는그냥 좀 더 편리한 DriverManager 라고 생각하면 되는 걸까요
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
빈 등록
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]기본적인건데 애매해서 질문드립니다. test코드에서 RepositoryV3와 ServiceV3_3를 @Bean으로 등록하지 말고 실제 RepositoryV3클래스와 ServiceV3_3클래스에 @RequiredArgsConstructor와 각각 @Repository, @Service를 추가해서 빈으로 등록을 해도 똑같이 내부에서 작동하는 것으로 봐도 괜찮을까요? test를 실행했을 때 오류가 발생하지 않아서 질문드립니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
테스트코드에서 transactionManager() 사용이유
안녕하세요@Bean PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dataSource()); }테스트코드에서 이 로직을 제거해도 작동이 잘 되는데요MemberServiceV3_3 클래스 에서@Transactional 을 사용해서트랜잭션 설정하는 로직이 필요없을것 같았는데위 코드를 사용하신 이유가있으실까요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
h2 데이터베이스 관련
안녕하세요 h2 데이터베이스에 대한 질문이 있습니다. h2 데이터베이스는 "연결" 누르고 sql 실행할 수 있는 창에 들어왔다면 이게 데이터베이스 서버를 띄운건가요?그럼 이 데이터베이스 창을 닫으면 자동으로 데이터베이스 서버를 다운시킨건가요? 그러니까 종료시킨건가요?그럼 spring 실행을 시킬때 항상 이 h2 데이터베이스에 연결해서 접속한다음에 실행해야하는건가요?그리고 현재는 저 한명만이 h2로 테스트하는거니까 그냥 계속 Embedded mode로 접속해도 되는거죠?감사합니다.
-
해결됨토비의 스프링 부트 - 이해와 원리
@Conditional 학습테스트 << 강의중 질문있습니다!
안녕하세요 토비님. 수업 잘 듣고있습니다다름이 아니라,학습테스트 강의 중에, @Conditional() 괄호 안에 있는 클래스의 리턴값에 따라 true/false를 반환하는 void conditional() 테스트 메서드에 대해 질문이 있습니다. true를 리턴하는 경우 코드가AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();ac.register(Config1.class);ac.refresh();MyBean bean = ac.getBean(MyBean.class);이고, false를 리턴하는 경우는AnnotationConfigApplicationContext ac2 = new AnnotationConfigApplicationContext();ac2.register(Config2.class);ac2.refresh();MyBean bean2 = ac2.getBean(MyBean.class);인데요..여기서 true 테스트는 성공하고 false테스트는 실패를 합니다.여기서 생긴 의문점은, ac와 ac2 둘다 스프링 컨테이너를 가리키는 것인데, ac.getBean의 결과와 ac2.getBean의 결과가 다르다는것은 앞서 ac.register()해서 등록한 MyBean이 ac2 스프링 컨테이너에는 없다는 것으로 해석이 되는데요.. 스프링에서는 스프링 컨테이너라는것이 하나 존재하고 그 안에 여러 빈들이 들어있다고 지금까지 생각하고 있었습니다.그래서 ac에서 bean을 등록했기때문에 ac2.getBean을 해도 똑같이 MyBean이 존재해야 하는것이 아닌가?? 라는 의문점이 듭니다. Q1. ac와 ac2 는 다른 스프링 컨테이너인가요 ??Q2.다른것이라면 , 스프링에서는 스프링컨테이너가 여러개 존재하는 것인가요??읽어주셔서 감사합니다. 새해 복 많이 받으세요
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
강의자료 관련
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]안녕하세요 강의 잘 듣고 있습니다. pdf 강의자료 6.스프링과 문제 해결 pg.11의 MemberServiceV4Test 코드에서 @AfterEach의 after 메소드에 붙은 throws SQLException를 제거해도 될 것 같아서 글을 남깁니다. 좋은 하루 되세요.
-
해결됨토비의 스프링 부트 - 이해와 원리
안녕하세요 토비님. 강의중 질문있습니다.
안녕하세요 강의 잘 듣고있는 학생입니다.다름이 아니라 applicationContext의 생성과정이 아직 스스로 정리가 되어있지 않아 이렇게 질문을 드립니다..우선 제 생각은 이렇습니다.applicationContext를 생성하면서 내부적으로 onRefresh() 를 오버라이딩을 합니다.여기서 ServletWebServerFactory serverFactory = this.getBean(ServletWebServerFactory.class); DispatcherServlet dispatcherServlet = this.getBean(DispatcherServlet.class); 을 통해서 등록된 Bean을 들고오게 됩니다.여기서 드는 의문점1은, this.getBean(DispatcherServlet.class)을 한다는 것은 이미 DispatcherServlet이 Bean등록이 되어있다는 것이고 그렇다면 applicationContext라는 변수를 만들기 전에 이미 Bean이 등록이 되어있었다고 생각됩니다. 그러면 applicationContext라는 변수를 방금 막 선언하고 아직 객체를 할당하는 과정인데 this.getBean이 작동한다?this는 분명 applicationContext인데 어떻게 applicationContext안의 getBean을 통해 dispatcherServlet등이 불러와지는지 모르겠습니다.. (요약하면, 아직 인스턴스를 만들지 않았는데 어떻게 applicationContext안의 getBean이 동작할 수 있는가? 입니다) 두번째는, 어떻게든 위의 과정을 거쳐서 applicationContext(스프링 컨테이너)가 서블릿 컨테이너와 연결이 되었습니다. 이후 applicationContext.register(HellobootApplication.class)를 하게되는데, 이미 위에서 빈 등록도 다 하고 모든걸 가지고 있는것 같은데 왜 register가 필요한것인지 모르겠습니다 ㅠㅠ register하는 코드는HellobootApplication.class라는 클래스 구성정보를 읽어서 그 내용을 토대로 빈(이때 이 빈은 HellobootApplication 빈 일까요??)을 등록한다 라고 생각되는데, HellobootApplication 클래스의 정보에는 팩토리 메서드 2개(ServletWebServerFactory,DispatcherServlet) 와 applicationContext를 구성하는 코드밖에 없다고 생각됩니다. applicationContext를 구성하는 과정에서 이미 팩토리 메서드 정보를 사용한 것 같은데, 그렇다면 이미 빈을 만드는데 필요한 정보는 다 가지고 있는것이 아닌가? 라고 생각이 듭니다. 이런 부분들이 자꾸 맘에 걸려서 다음강의로 못넘어가겠습니다 ㅠㅠ 명확하게 정리해주시면 감사하겠습니다..
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
Controller 안에서 @Transaction 설정이 다른 2개의 method 호출
@Slf4j @RestController public class AController { @Autowired AService aService; @Autowired BService bService; @PostMapping("/api/v2/aaaa") public ResponseEntity<ResponseDto> postA( @RequestBody @Valid PostADto postADto, HttpServletRequest request) throws Exception { A a = aService.getA(request); HashMap<String, Object> result = bService.createB(postADto, a); .... }위 와 같이 컨트롤러에서 aService.getA(request); 와 bService.createB(postADto, user); 메서드를 호출합니다.각 메서드는 아래와 같이 선언돼있습니다.@Transactional(readOnly = true) public A getA(HttpServletRequest request) { .... return aRepository.findById(id).orElse(null); }@Transactional public HashMap<String, Object> createB(PostADto postADto, A a) { ...... bRepository.save(postADto.toB()); ...... return ...; }getA 메서드안에서 TransactionSynchronizationManager.isCurrentTransactionReadOnly(); log 출력했을때 readonly = true로 나오고 readDB로 잘 연결됩니다. 하지만 createB 메서드안에서 TransactionSynchronizationManager.isCurrentTransactionReadOnly(); log 출력했을때 readonly = false로 나오는데 실제로는 readDB로 연결되고 query를 발생시켜 아래와 같은 오류가 발생합니다.Caused by: java.sql.SQLException: The MySQL server is running with the --read-only option so it cannot execute this statement at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) Caused by: java.sql.SQLException: The MySQL server is running with the --read-only option so it cannot execute this statement 컨트롤러에 @transactional 을 선언하지 않았기 때문에 각 메서드에서 트랜잭션이 수행되어 getA 메서드에서는 readDB로 createB 메서드에서는 writeDB로 요청이 된다고 알고 있었는데 그런 방식으로 동작이 안되 혼란스럽습니다. 어떤 이유로 이런 문제가 발생하는지 궁금합니다. 그리고 왜 이렇게 동작하는지 어느 부분을 학습하면 좋은지 궁금합니다.