인프런 커뮤니티 질문&답변

grey님의 프로필 이미지
grey

작성한 질문수

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

Jdbc 적용후 member 등록을 누르면 에러페이지가 나옵니다.

해결된 질문

작성

·

618

0

 

강의 섹션6 스프링DB 접근 기술에서

순수 JDBC 강의 편을 듣고 따라하던중 spring실행해서 멤버를 등록한 후 갱신되는지를 확인하는 장면을 따라했습니다.

그런데 데이터베이스에 입력한 멤버가 삽입은 되는데 화면과 console 에서 에러가 나옵니다.

jdbcMemberRepository로 변경전에는 모두 이상없이 실행되었습니다.

 

 

 

아래는 에러페이지입니다.

에러페이지.png

 

 

 

이클립스로 실행했습니다.

아래는 console로그에서 에러부분 입니다.

java.lang.NumberFormatException: Character A is neither a decimal digit number, decimal point, nor "e" notation exponential mark.

threw exception [Request processing failed: java.lang.IllegalStateException: java.sql.SQLException: 부적합한 변환이 요청됨] with root cause

java.lang.NumberFormatException: Character A is neither a decimal digit number, decimal point, nor "e" notation exponential mark.
	at java.base/java.math.BigDecimal.<init>(BigDecimal.java:586) ~[na:na]
	at java.base/java.math.BigDecimal.<init>(BigDecimal.java:471) ~[na:na]
	at java.base/java.math.BigDecimal.<init>(BigDecimal.java:900) ~[na:na]
	at oracle.jdbc.driver.T4CVarcharAccessor.StringToNUMBER(T4CVarcharAccessor.java:782) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
	at oracle.jdbc.driver.T4CVarcharAccessor.getNUMBER(T4CVarcharAccessor.java:257) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
	at oracle.jdbc.driver.T4CVarcharAccessor.getLong(T4CVarcharAccessor.java:555) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
	at oracle.jdbc.driver.GeneratedStatement.getLong(GeneratedStatement.java:208) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
	at oracle.jdbc.driver.GeneratedScrollableResultSet.getLong(GeneratedScrollableResultSet.java:261) ~[ojdbc8-19.3.0.0.jar:19.3.0.0.0]
	at com.zaxxer.hikari.pool.HikariProxyResultSet.getLong(HikariProxyResultSet.java) ~[HikariCP-5.0.1.jar:na]
	at com.example.hello.repository.JdbcMemberRepository.save(JdbcMemberRepository.java:43) ~[main/:na]
	at com.example.hello.service.MemberService.join(MemberService.java:29) ~[main/:na]
	at com.example.hello.controller.MemberController.create(MemberController.java:34) ~[main/:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:259) ~[spring-web-6.1.4.jar:6.1.4]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:192) ~[spring-web-6.1.4.jar:6.1.4]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.4.jar:6.1.4]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:920) ~[spring-webmvc-6.1.4.jar:6.1.4]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:830) ~[spring-webmvc-6.1.4.jar:6.1.4]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.han~$ConnectionHandler.process(AbstractProtocol.java:896) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1744) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.19.jar:10.1.19]
	at java.base/java.lang.Thread.run(Thread.java:842) ~[na:na]

 

 

 

제가 데이터베이스를 오라클로 설치했는데 오라클에서 테이블 생성 sql 은 이렇습니다.

데이터는 보면 id에 모두 숫자만 들어가 있습니다.

create table member(
id number generated by default as identity, 
name varchar2(255),
primary key(id)
);

 

 

혹시나해서 설정파일도 올려봅니다

아래는 bundle.gradle입니다.

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.2.3'
	id 'io.spring.dependency-management' version '1.1.4'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'com.oracle.ojdbc:ojdbc8:19.3.0.0'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('bootBuildImage') {
	builder = 'paketobuildpacks/builder-jammy-base:latest'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

아래는 application.properies 입니다.

server.port = 8090

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true

spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe 
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.username=test_1
spring.datasource.password=admin123

 

 

답변 2

1

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. grey님

저도 처음 보는 이슈이기는 한데요.

다음에서 비슷한 이슈를 찾을 수 있었습니다.

https://stackoverflow.com/questions/48741210/issue-with-preparedstatement-while-using-with-statement-return-generated-keys

먼저 ojdbc 드라이버를 최신 버전으로 사용해보세요.

그래도 안되면 rs.getLong(1) 대신에 rs.getString(1)을 사용해보시는 것을 권해드려요.

감사합니다.

grey님의 프로필 이미지
grey
질문자

강의진행에는 문제가 없을 것 같아서 id를 String 타입으로 바꿨습니다. 현재 에러는 뜨지않습니다. 감사합니다~

0

안녕하세요, 인프런 AI 인턴입니다. grey님, 오류 내용을 살펴보면, java.lang.NumberFormatException은 숫자 형식 관련 예외입니다. 예외 메시지에 따르면 ‘A’ 문자가 숫자, 소수점, 지수 ‘e’가 아닌 것으로 인식된 것으로 보입니다. 이는 JdbcMemberRepositorysave 메서드에서 id를 처리하는 부분에서 문제가 발생했을 가능성이 높습니다.

해당 문제는 일반적으로 문자열을 숫자로 변환하려 할 때 발생하는 오류로, 숫자가 아닌 문자열을 변환하려고 시도했을 때 나타납니다. 여기서 중요한 것은 Oracle DB의 id 필드가 Number 타입인데, 이를 애플리케이션에서 처리할 때 적절한 숫자 타입으로 변환하지 못해서 발생하는 문제일 수 있습니다.

오류 메시지에서 JdbcMemberRepository.save나 해당 메서드를 호출하는 구문을 자세히 살펴보셔야 할 것 같습니다. 그 과정에서 id 값을 문자열로 인식하거나, id 값의 형식을 올바르게 변환하지 못하는 부분이 있는지 점검해 보세요.

또한, 현재 사용 중인 쿼리나 리포지토리 메서드에서 Oracle 데이터 타입을 Java의 타입(예: Long, Integer)으로 변환할 때 올바른 형식을 사용하고 있는지도 확인해야 합니다. JdbcMemberRepository의 구현 부분에서 ResultSet.getLong이나 ResultSet.getInt 등을 사용해 값을 추출할 때, Oracle DB의 NUMBER 데이터 타입과 Java의 숫자 타입 간에 올바르게 매핑되고 있는지 점검해 보셔야 할 것입니다.

오라클 테이블 생성 SQL을 올바르게 사용하고 계시며, create table member 구문이 올바른 구문으로 보입니다. id 필드에 숫자만 들어가 있는 것을 확인하셨다면, 애플리케이션 측에서 id를 처리하는 코드에 문제가 있는 것으로 추정됩니다.

spring datasource 설정은 문제가 없어 보입니다. ojdbc8 드라이버와 관련된 구성도 적절해 보이며, application.properties 설정도 적절해 보입니다.

여기서 다시 한 번 강조하지만, java.lang.NumberFormatException과 관련하여 JdbcMemberRepositorysave 메서드 구현을 확인하고, 오라클 데이터 타입과 Java 타입 간 변환 처리를 점검하시기 바랍니다.

grey님의 프로필 이미지
grey
질문자

id는 Long 타입이고 jdbc연결전까지는 문제가없어서 이전에 작성된파일에서는 문제가 없을것 같습니다. 아래는 jdbcMemberRepoistory.java 전문입니다.

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(Long.parseLong(String.valueOf(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);
	}
}
grey님의 프로필 이미지
grey

작성한 질문수

질문하기