묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
프로젝트 생성 시 jdbc:failed 하면서 빌드가 실패했다고 나옵니다.
> Task :prepareKotlinBuildScriptModel UP-TO-DATEFAILURE: Build failed with an exception.* What went wrong:Could not resolve all dependencies for configuration ':compileClasspath'.Failed to calculate the value of task ':compileJava' property 'javaCompiler'.Cannot find a Java installation on your machine matching this tasks requirements: {languageVersion=17, vendor=any, implementation=vendor-specific} for MAC_OS on aarch64.No locally installed toolchains match and toolchain download repositories have not been configured.* Try:> Run with --stacktrace option to get the stack trace.> Run with --info or --debug option to get more log output.> Run with --scan to get full insights.> Get more help at https://help.gradle.org.BUILD FAILED in 504ms 이런 오류가 발생합니다.ㅜㅜ
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
예외처리
예외처리에 관련해 질문이 있습니다.try 구문안에서 예외가 발생하면 밑에있는 try의 남은 구문 건너뛰고 바로 catch문으로가서 잡아주는것으로 알고있습니다.그런데 공부하다보니까 헷갈리는게 MemberRepository에 있는 save메서드로 예를 들면,con.prepareStatement(sql)부터 SQLException을 발생시키는데 어떻게 try안에 있는 것들이 정상적으로 수행되는지 궁금합니다.예외가 나오는 순간 catch문으로가서 catch구문을 수행하는 것이 아닌가요 ?? @Override public Member save(Member member) { String sql = "insert into member(member_id,money) values(?,?)"; Connection con = null; PreparedStatement pstmt = null; try { con = getConnection(); pstmt = con.prepareStatement(sql); pstmt.setString(1, member.getMemberId()); pstmt.setInt(2, member.getMoney()); pstmt.executeUpdate(); //수정 return member; } catch (SQLException e) { log.error("db error", e); throw new MyDbException(e); }finally { close(con, pstmt, null); } }
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
test.mv.db 파일이 생성된걸 어디에서 확인 가능한가요?
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요.test.mv.db 파일이 생성된걸 어디에서 확인 가능한가요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
예외처리
안녕하세요 예외처리에 대한 질문이생겨 글 적습니다 !MemberServiceV3_2에서 bizLogic()을 호출해서 메서드에서 던져진 SQLException을 잡습니다 그런데 MemberServiceV3_1에서 트랜잭션 매니저로 처리하는 try catch문에서는 Exception으로 예외를 잡는데 Exception이 모든 예외의 조상이라서 모든 예외를 잡는건 알고있습니다 !그런데 헷갈리는 부분이 SQLException이 commit을 하면 사라지나요 ?아니면이때 SQLException이 잡히나요 ? 잡히지만 이미 커밋을 해버려서 롤백할 데이터가 없기 때문에 SQLException을 IllegalStateException으로 바꿔주기만 하고 try catch문을 빠져나오는 걸까요 ??
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
별도의 쓰레드를 만드는 원리
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요!!최근 병행해서 공부하고 있는 멀티 쓰레딩 개념을 도입해서 정리한 게 맞나 확인하고 싶어서 이렇게 남겨봅니다.별도의 쓰레드를 만드는 이유: 커넥션 풀에 채우는 작업 자체가 CPU 점유 시간(cpu time)이 커서별도의 쓰레드가 생긴 이유: HikariCP 라이브러리를 만든 개발자가 코드를 그렇게 작성 쓰레드 관리: 자바의 쓰레드 풀에 있는 쓰레드는 유저 레벨 쓰레드이고 os레벨의 쓰레드와 매핑되어서 사용하는데 이 멀티 쓰레딩 자체는 결국 cpu가 cpu 스케줄링을 통해서관리(= 컨텍스트 스위칭)항상 감사합니다
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
개인프로젝트에서 Datasource dataSource 오류
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]리포지토리인 Dto 클래스에 private final DataSource dataSource시 Could not autowire. No beans of 'DataSource' type found.라는 오류가 뜨면서 빌드가 안 됩니다! 서비스에서 트랜잭션을 쓰지는 않지만 DataSource를 적용해보고 싶었는데 안 되네요 ㅠㅠ package com.spring.dto; import com.spring.dao.member.Member; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Repository; import javax.sql.DataSource; import java.sql.*; import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; @Repository @RequiredArgsConstructor public class JDBCMemberDto implements MemberDto{ private final DataSource dataSource; // 테이블 열 private static final String TABLE_NAME = "USERS"; private static final String ID_COLUMN = "ID"; private static final String USERID_COLUMN = "USERID"; private static final String PASSWORD_COLUMN = "PASSWORD"; private static final String NAME_COLUMN = "NAME"; @Override public Member save(Member member) { String query = "INSERT INTO " + TABLE_NAME + " (" + ID_COLUMN + ", " + USERID_COLUMN + ", " + PASSWORD_COLUMN + ", " + NAME_COLUMN + ") VALUES (SEQ_USER.NEXTVAL, ?, ?, ?)"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(query)){ pstmt.setString(1, member.getUserId()); pstmt.setString(2, member.getPassword()); pstmt.setString(3, member.getName()); pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } return findByUserId(member.getUserId()).get(); } @Override public Member findById(Long id) { Member member = new Member(); String query = "SELECT * FROM USERS WHERE id = ?"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(query)){ pstmt.setLong(1, id); ResultSet rs = pstmt.executeQuery(); if(rs.next()) { member.setId(rs.getLong(ID_COLUMN)); member.setUserId(rs.getString(USERID_COLUMN)); member.setPassword(rs.getString(PASSWORD_COLUMN)); member.setName(rs.getString(NAME_COLUMN)); } else { throw new NoSuchElementException("유저를 찾을 수 없습니다. memberId=" + id); } } catch (SQLException e) { e.printStackTrace(); } return member; } @Override public Optional<Member> findByUserId(String userid) { return findAll().stream() .filter(member -> member.getUserId().equals(userid)) .findFirst(); } @Override public List<Member> findAll() { List<Member> list = new ArrayList<>(); String query = "SELECT * FROM USERS"; try (Connection conn = getConnection(); PreparedStatement pstmt = conn.prepareStatement(query)){ pstmt.executeUpdate(); ResultSet rs = pstmt.executeQuery(); while(rs.next()) { Member member = new Member(); member.setId(rs.getLong(ID_COLUMN)); member.setUserId(rs.getString(USERID_COLUMN)); member.setPassword(rs.getString(PASSWORD_COLUMN)); member.setName(rs.getString(NAME_COLUMN)); list.add(member); } } catch (SQLException e) { e.printStackTrace(); } return list; } private Connection getConnection() throws SQLException { Connection connection = dataSource.getConnection(); return connection; } }
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
단순 용어 질문드립니다.
DBConnectionUtil을 통해 커넥션을 획득하는 과정에서의 용어 질문입니다. 커넥션을 획득한다커넥션을 연결한다 이 둘의 의미가 여기서는 획득한다(얻다)가 더 알맞는 표현인건가요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
JdbcTemplate update 사용시 반환값 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오) 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) 예[질문 내용]여기에 질문 내용을 남겨주세요.안녕하세요. 수업에 배운 내용을 바탕으로 작은 메모 어플을 만들면서 질문이 있어 질문 남깁니다.@Repository public class JdbcMemoRepository implements MemoRepository{ private final JdbcTemplate template; public JdbcMemoRepository(DataSource dataSource) { this.template = new JdbcTemplate(dataSource); } @Override public Memo memoSave(Memo memo) { String sql = "insert into memo (memo, created, dTime) values (?, ?, ?)"; template.update(sql, memo.getMemo(), LocalDateTime.now(), memo.getDTime()); return memo; }이런식으로 코드를 짜서 memoSave의 반환값을 확인해 보면 반환값이 memo와 dTime 필드에만 있고, created와 id는 null값으로 반환이 됩니다. 이유는 클라이언트쪽에서 requestBody로 건내주는 필드가 memo와 dTime뿐이고, created는 서버에서 LocalDateTime.now()로, id는 mysql에서 auto increment로 생성하고 있어서 parameter로 받는 memo를 그대로 반환하면 id와 created가 null이 되는 것 같습니다. 이 문제를 해결 하기 위해서는 memoSave로 데이터베이스에 넣어준 후 바로 그 레코드 값을 데이터베이스에서 꺼내서 반환을 해야 할 것 같은데 방법을 모르겠어서 질문드립니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
커넥션풀 궁금한게 있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용]여기에 질문 내용을 남겨주세요.강의 이미지중에 애플리케이션 서버 내에 애플리케이션 로직, db드라이버, 커넥션 풀이 모두 포함되어 있는 이미지가 있습니다. 근데 스프링과같은 프로젝트 내에 db 드라이버, 커넥션 풀이 포함되어있는게 아닌가요? was 내에 db 드라이버, 커넥션풀이 포함되어 있는게 아니라.. 결론으로 1개의 jar, war 파일 내에 db 드라이버, 커넥션풀이 포함되어 있다고 이해하면 될까요? .. 감사합니다.
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
h2 db 테이블 관련 스크립트 질문
강의에서 h2 db 테이블 관련 스크립트를 h2 콘솔에 복사해서 붙여넣으셔서 테이블을 생성하셨는데요.강의자료를 보면, sql/schema.sql 파일을 생성해서 스크립트를 넣으라고 되어있습니다.둘 중 전자를 이용하면 되는 건가요?
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
try catch
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]다름이 아니라 try-with-resources 사용하면 자원이 끊길 때 알아서 close() 호출해주니까 JdbcUtils로 닫을 필요없이 try-with-resources 사용하면되지 않나요?!try ( Connection con = getConnection(); PreparedStatement pstmt = con.prepareStatement(sql)) { pstmt.setString(1,memberId); int resultSize = pstmt.executeUpdate(); log.info("resultSize={}", resultSize); } catch (SQLException e) { log.error("db error",e); throw e; }
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
SQL MAPPER Mybatis
최근에 우연히 spring.start.io에서 프로젝트를 만들다가 스프링 부트 3.3버전에서는 mybatis 의존성 추가를 막아 놓은것을 발견했습니다. mybatis라는 기술이 최신 버전의 스프링에서는 별로 좋지않은 방법이어서 의존성 추가를 못하게 막아놓는 건가요?
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
@Transactional 의존 관계 주입
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]@Transactional에서는 스프링 컨테이너를 참조하기 사용되는 리소스들이 빈으로 등록되어야 하기 때문에 properties에 url, username, password를 입력해놓으면 스프링부트가 알아서 데이터소스를 빈으로 등록해줌을 알았습니다. 트랜잭션 매니저도 라이브러리에 등록된 정보를 바탕으로 JDBC트랜잭션 매니저 또는 JPA트랜잭션 매니저를 빈으로 등록해주는데 그렇다면 Test가 아니라 실제 코드에서 트랜잭션에 사용되는 리포지토리랑 서비스클래스에 @Repository랑 @Service를 사용해야 @Transactional을 사용할 수 있는지 궁금합니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
지금까지 배운 내용들의 구조를 이해하려고 합니다
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]제가 지금까지 이해한 내용으로는 DataSource를 상속받은 구현체인 DataSourceDriverManager또는 커넥션 풀 등으로 커넥션을 생성하려고 하면 JDBC표준 인터페이스를 상속받은 ORACLE 드라이버 또는 MySQL 드라이버 등을 통하여 사용하는 DB에 접근한다로 이해하고 있습니다.여기서 PlatformTranscationManager를 상속받은 JPA트랜잭션, JDBC트랜잭션 등 이 구현체들과의 연관 관계가 어떻게 이어지는지 구조가 잘 그려지지 않습니다.제가 지금까지 이해한 내용이 잘못된건지 트랜잭션 매니저, 데이터소스, JDBC 이 셋 인터페이스를 구현한 구현체들의 작동 순서를 정확하게 이해하고 넘어가고 싶습니다.
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
전체 구조
안녕하세요! 먼저 항상 친절한 답변 감사드립니다 ㅎㅎ구조가 어떻게 되어있는 건지 헷갈려서 나름 그려봤는데...JPA를 사용할 때 전체 db 연결 구조가 이렇게 되어있는게 맞을까요??
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
트랜잭션 매니저가 커넥션을 얻어오는 방법 질문
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]여기에 질문 내용을 남겨주세요. 안녕하세요 영한님.항상 좋은 강의 잘 듣고있습니다.강의 자료의, 트랜잭션 매니저가 트랜잭션을 시작하기 위해커넥션을 얻어오는 부분에서"트랜잭션 매니저는 데이터 소스를 통해 커넥션을 만들고 트랜잭션을 시작한다" 라고 명시되어 있습니다.이부분을 저는 (1) 어차피 데이터 소스는 커넥션 획득 방법의 추상화 이고(2) 현업에서는 커넥션 풀을 사용하여 미리 만들어진 커넥션을 얻어오기 때문에이를 조합하여,i) 트랜잭션 매니저는 결국 커넥션 풀에서 커넥션을 얻어와서,본인의 트랜잭션 동기화 매니저에 보관해 놓고ii) 트랜잭션을 시작한 후,iii) 트랜잭션을 종료하면트랜잭션 동기화 매니저에 넣어두었던 커넥션을다시 커넥션 풀로 반환한다.로 이해했습니다.혹시 제가 맞게 이해한 것인지 질문 드리고 싶습니다.감사합니다.
-
미해결스프링 DB 1편 - 데이터 접근 핵심 원리
레포지토리에서 동기화를 사용하지 않은 이유가 따로 있으실까요?
[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]동기화가 필요하지 않은 서비스 로직이라 동기화를 일부러 적용 안하신건지 아니면 그냥 단순하게 예제를 만들기 위해 생략한 것인지 궁금합니다!
-
미해결토비의 스프링 부트 - 이해와 원리
다음 강의 오픈 일정 알 수 있을까요?
늦으면 4월이라고 하신 답변을 본 것 같은데 기다리고 있습니다!!
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
Jdbc템플릿을 사용하면 지금까지 내용은 직접 사용하는 일은 없나요?
지금까지의 설명은 기술의 발전 과정을 설명해주신것이니 실무에서나 개인 프로젝트 할때는 JDBC템플릿을 이용하면 지금까지 설명해주신 부분이 모두 해결이 자동으로 되니 에러 변환이나 커넥션 가져오고 반환하는 등 모든 과정을 고민하지 않아도 되는것인거죠 ?그리고 멤버서비스v3_4테스트부터 오류가 발생하여 Jdbc템플릿을 이용하는 방법 테스트에까지 오류가 해결이 안됩니다. 기존에 질문글에 구글드라이브 링크를 올렸는데 해결 부탁드립니다 ㅠ
-
해결됨스프링 DB 1편 - 데이터 접근 핵심 원리
체크예외를 런타임예외로 변환하는 코드
[질문 내용]해당 영상에서 unCheckedAppTest 클래스 내에서 SQLException을 RuntimeException으로 변환하는 부분을 static class로 생성해서 사용하고 있습니다.<첫 번째 질문>이렇게 체크 예외를 런타임 예외로 바꿀 때 항상 static class로 생성해야 되는지 아니면 try { ~~ } catch(SQLException e) { throw RuntimeException(e); } 이렇게 사용해도 되는지 궁금합니다.<두 번째 질문>체크 예외를 런타임 예외로 바꾸는 부분을 static class로 생성할 때 무조건 해당 체크 예외가 발생하는 클래스에다 생성해야 하는지도 궁금합니다.