작성
·
911
·
수정됨
0
안녕하세요. 코드로 8080에 접속해서 회원가입하고 등록하는건 잘 되었습니다. 또한 h2-database에서
http://localhost:8082/login.do?jsessionid=573840fda7971b85bee554c496227dcd
로 들어가서도 문제없이 하였습니다.
@Bean
public MemberRepository memberRepository() {
// return new MemoryMemberRepository();
return new JdbcMemberRepository(dataSource);
}
하지만 return new JdbcMemberRepository(dataSource); 이렇게 하고 이름을 입력하고 등록을 누르거나 조회를 누르면 화이트라벨 에러가 발생합니다.
spring.application.name=hello-spring
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
properties는 문제없이 입력하였습니다.
2024-06-16T14:47:06.989+09:00 ERROR 15340 --- [hello-spring] [nio-8080-exec-3] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization.
org.h2.jdbc.JdbcSQLNonTransientConnectionException: Connection is broken: "java.net.ConnectException: Connection refused: getsockopt: localhost" [90067-224]
2024-06-16T14:47:07.004+09:00 ERROR 15340 --- [hello-spring] [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.IllegalStateException: org.springframework.jdbc.CannotGetJdbcConnectionException: Failed to obtain JDBC Connection] with root cause
java.net.ConnectException: Connection refused: getsockopt
에러가 길어서 핵심적인 에러들만 가져왔습니다. 스프링도 3. 이상이여서 h2를 2.1.214 버전 이상 사용하였습니다. 밑에 코드들은 저의 인텔리제이에 있는 코드들입니다. 대부분 복붙해서 문제는 없는거 같아요.
package hello.hello_spring.repository;
import hello.hello_spring.domain.Member;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class JdbcMemberRepository implements MemberRepository {
private final DataSource dataSource;
public JdbcMemberRepository(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Member save(Member member) {
String sql = "insert into member(name) values(?)";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
pstmt.setString(1, member.getName());
pstmt.executeUpdate();
rs = pstmt.getGeneratedKeys();
if (rs.next()) {
member.setId(rs.getLong(1));
} else {
throw new SQLException("id 조회 실패");
}
return member;
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
@Override
public Optional<Member> findById(Long id) {
String sql = "select * from member where id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setLong(1, id);
rs = pstmt.executeQuery();
if(rs.next()) {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return Optional.of(member);
} else {
return Optional.empty();
}
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
@Override
public List<Member> findAll() {
String sql = "select * from member";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
List<Member> members = new ArrayList<>();
while(rs.next()) {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
members.add(member);
}
return members;
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
@Override
public Optional<Member> findByName(String name) {
String sql = "select * from member where name = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
rs = pstmt.executeQuery();
if(rs.next()) {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return Optional.of(member);
}
return Optional.empty();
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
private Connection getConnection() {
return DataSourceUtils.getConnection(dataSource);
}
private void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn != null) {
close(conn);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private void close(Connection conn) throws SQLException {
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
package hello.hello_spring.repository;
import hello.hello_spring.domain.Member;
import org.springframework.stereotype.Repository;
import java.util.*;
public class MemoryMemberRepository implements MemberRepository {
private static Map<Long, Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
public void clearStore() {
store.clear();
}
}
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
이현준님, 스프링 부트 애플리케이션에서 H2 데이터베이스 접속 시 발생하는 ‘화이트라벨 에러’와 관련된 문제에 대해 답변 드리겠습니다. 에러 로그를 살펴보면, HikariCP를 통한 데이터베이스 연결 초기화 과정에서 ‘Connection refused: getsockopt’ 오류가 발생하고 있습니다. 이는 스프링 부트 애플리케이션에서 설정한 데이터베이스 접속 정보와 실제 데이터베이스의 상태 또는 설정이 일치하지 않음을 나타냅니다.
properties 설정 내용을 보면, 스프링 데이터 소스 URL이 ‘jdbc:h2:tcp://localhost/~/test’로 설정되어 있는데, 이 주소로의 연결이 거부되고 있습니다. H2 데이터베이스가 TCP 서버 모드로 실행 중이고 해당 주소와 포트(localhost:9092
가 기본값)에서 대기하고 있는지 확인해야 합니다.
문제 해결을 위한 몇 가지 확인 사항을 안내해 드리겠습니다:
H2 데이터베이스가 실제로 실행 중인지, 그리고 TCP 서버 모드로 구동되고 있는지 확인하십시오. H2 데이터베이스를 스프링 부트 애플리케이션과 동일한 호스트에서 실행 중이라면, 해당 TCP 서버 모드에 대한 설정(예: 포트 번호)이 올바른지 확인해야 합니다.
스프링 데이터 소스 URL 주소에 명시된 경로와 포트 번호가 정확한지 검증하십시오. ~/test
경로는 사용자 홈 디렉토리에 위치한 test
데이터베이스를 가리키며, 이 경로가 올바른지 확인하십시오.
포트 번호가 명시되지 않았다면, H2 데이터베이스의 기본 포트인 9092
를 사용하고 있는지, 아니면 커스텀 포트 번호를 사용하고 있다면 해당 포트가 올바르게 설정되었는지 확인하십시오.
에러 메시지의 ‘Connection refused’ 부분은 대개 네트워크 연결 문제, 즉 클라이언트(여기서는 스프링 부트 애플리케이션)가 데이터베이스 서버에 접속하려 할 때 해당 서버가 요청을 받을 준비가 되어 있지 않을 때 발생합니다. 이는 데이터베이스 서버가 아직 시작되지 않았거나, 서버의 방화벽이나 보안 설정으로 인해 접속이 차단되었거나, 주소나 포트 정보가 잘못되었을 수 있습니다.
따라서, 위의 점검 사항을 바탕으로 설정을 다시 한 번 확인하시고, 필요하다면 H2 데이터베이스 서버의 실행 상태나 설정을 재검토하십시오.