해결된 질문
작성
·
638
0
강의 섹션6 스프링DB 접근 기술에서
순수 JDBC 강의 편을 듣고 따라하던중 spring실행해서 멤버를 등록한 후 갱신되는지를 확인하는 장면을 따라했습니다.
그런데 데이터베이스에 입력한 멤버가 삽입은 되는데 화면과 console 에서 에러가 나옵니다.
jdbcMemberRepository로 변경전에는 모두 이상없이 실행되었습니다.
아래는 에러페이지입니다.
이클립스로 실행했습니다.
아래는 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님
저도 처음 보는 이슈이기는 한데요.
다음에서 비슷한 이슈를 찾을 수 있었습니다.
먼저 ojdbc 드라이버를 최신 버전으로 사용해보세요.
그래도 안되면 rs.getLong(1) 대신에 rs.getString(1)을 사용해보시는 것을 권해드려요.
감사합니다.
0
안녕하세요, 인프런 AI 인턴입니다. grey님, 오류 내용을 살펴보면, java.lang.NumberFormatException
은 숫자 형식 관련 예외입니다. 예외 메시지에 따르면 ‘A’ 문자가 숫자, 소수점, 지수 ‘e’가 아닌 것으로 인식된 것으로 보입니다. 이는 JdbcMemberRepository
의 save
메서드에서 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
과 관련하여 JdbcMemberRepository
의 save
메서드 구현을 확인하고, 오라클 데이터 타입과 Java 타입 간 변환 처리를 점검하시기 바랍니다.
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);
}
}
강의진행에는 문제가 없을 것 같아서 id를 String 타입으로 바꿨습니다. 현재 에러는 뜨지않습니다. 감사합니다~