본문 바로가기

개발 일기

[ 0510 ] 오류 일기 (MyBatis, SpringBoot)

첫번째 에러

Caused by: org.apache.ibatis.builder.BuilderException: Error resolving class. Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'long, long'. Cause: java.lang.ClassNotFoundException: Cannot find class: long, long

 

MyBatis xml 파일에서 매개변수를 두개 두고 싶어서 parameterType="long, long" 을 해봤다.

이 부분 때문에 에러가 발생해버렸다...

    <insert id="addPrefer" parameterType="long, long"> // long으로 바꾸니 돌아감
        insert into streamingLike(live_id, user_id)
        values(#{liveId}, #{userId})
    </insert>

 

 

두번째 에러

2024-05-10T13:26:07.029+09:00 WARN 16742 --- [Mytube] [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type long from Object value (token JsonToken.START_OBJECT)]

 

long json 을 long 타입으로 역직렬화를 하려고 했는데 실패했다는내용이다.

역직렬화가 이뤄지는 곳은 controller 이니 그 쪽 코드를 확인했다.

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/live")
public class LiveController {
    @PostMapping("/{liveId}/prefer") // before
    public void preferLive(@PathVariable("liveId") long liveId, @RequestBody long userId){
        liveService.prefer(liveId, userId);
    }
}


// After
	@PostMapping("/{liveId}/prefer") 
    public void preferLive(@PathVariable("liveId") long liveId, @RequestBody ThumbsUpRequest request){
        request.setLiveId(liveId);
//        ThumbsUpRequest request = new ThumbsUpRequest(liveId, userId);
        liveService.prefer(request);
    }
    
-----
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@Getter
@AllArgsConstructor
public class ThumbsUpRequest {
    private long userId;
    @Setter
    private long liveId;
}

 

controller 에서 service 로 넘어갈 때 객체를 만들어 역직렬화가 되도록 바꿨다.

 

세번째 오류

java.lang.NullPointerException: Cannot invoke "com.flab.Mytube.service.LiveService.prefer(com.flab.Mytube.dto.movie.request.ThumbsUpRequest)" because "com.flab.Mytube.controller.LiveController.liveService" is null

 

선언한 서비스에 null 이 들어갔다는 걸 보고 어이가 없어서 부랴부랴 확인했다.

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/live")
public class LiveController {
    private static LiveService liveService; // before
    
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/live")
public class LiveController {
    private final LiveService liveService; // after

static -> final

 

 

네번째 오류

org.apache.ibatis.binding.BindingException: Parameter 'liveId' not found. Available parameters are [request, param1]

발생 원인

MyBatis를 이용한 SQL Mapper의 메소드는 하나의 파라미터만을 읽음.

즉, 파라미터의 개수가 2개 이상일 때 발생

  • 하나의 파라미터만 읽기 때문에 2개 이상에 파라미터를 주는 경우 해당데이터가 어떤 것인지를 명시하지 않으면 에러 발생

아래 링크를 참고해서 해결했다.  

[MyBatis]org.apache.ibatis.binding.BindingException: Parameter '파라미터명' not found. 에러

 

[MyBatis]org.apache.ibatis.binding.BindingException: Parameter '파라미터명' not found. 에러

에러 내용 org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.bindi...

blog.naver.com

 

다섯번째 오류

org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'liveId' in 'class java.lang.Long'

 

MyBatis 동작 과정 중 liveId 라는 변수에서 getter 를 찾고 있었다.

이에 매퍼와 관련한 코드인 걸 직감하고 확인했다.

@Component
@Mapper
public interface LiveMapper {
    long getPreferCount(@Param("request") long liveId); // before

    long getPreferCount(@Param("request") ThumbsUpRequest request);// after

넘겨주는 매개변수가 하나일지라도 객체로 넘겨줘야 하나보다.

지금 와서 생각해보는데 long 이란 기본 자료형인 Long 참조 자료형으로 했으면 해결 되지 않았을까?

 

여섯번째 오류

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.mybatis.spring.MyBatisSystemException] with root cause

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 10 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:80) ~[mybatis-3.5.7.jar:3.5.7]

 

sql 문이 여러게의 레코드를 결과로 던져주고 있다고 한다.

그냥 throw Exception 으로 처리하는 블로그도 보긴 했지만 내가 의도한 건 1개의 결과만 가져오는 것이었기 때문에 확인을 해봤다.

관련된 sql 문을 실행해보던 중 여러개의 레코드를 반환하는 select 를 찾아서 sql 문을 수정했다.

 

 

일곱번째 오류

with path [] threw exception [Request processing failed: org.springframework.jdbc.BadSqlGrammarException:

Error querying database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'streaming_id' in 'where clause'

The error may exist in file [/Users/aristo/Desktop/2024/f-lab/project/Mytube-streaming/Mytube/build/resources/main/mybatis/mapper/StreamingMapper.xml]

The error may involve com.flab.Mytube.mapper.LiveMapper.getPreferCount-Inline

The error occurred while setting parameters

SQL: select thumbs_up from live_streaming where streaming_id = ?

Cause: java.sql.SQLSyntaxErrorException: Unknown column 'streaming_id' in 'where clause'

; bad SQL grammar []] with root cause

java.sql.SQLSyntaxErrorException: Unknown column 'streaming_id' in 'where clause'

 

얼마나 실수를 했는지 모르겠다.

테이블에 없는 필드에서 데이터를 가져오려고 해서 난 에러였다.

쿼리문을 다시 작성했다.

 

 

 

여덟번째 오류

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Long (java.lang.Integer and java.lang.Long are in module java.base of loader 'bootstrap')] with root cause

java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Long (java.lang.Integer and java.lang.Long are in module java.base of loader 'bootstrap')

 

Integer 를 Long 으로 캐스트할 수 없다는 오류였다.

자바 코드에서 해당 변수를 모두 long 으로 했는데 어디서 잘못되었는지 곰곰히 생각해봤다.

그리고 문득 이 부분이 생각났다.

    <select id="checkPrefer" parameterType="com.flab.Mytube.dto.movie.request.ThumbsUpRequest" resultType="long">
        select count(id) from streamingLike
        where streaming_id = #{request.liveId} and user_id = #{request.userId}
    </select>

// resultType="long" after (before: resultType:"int")

select 문의 resultType="int" 로 되어 있었던 것이다.

DB에 int 형으로 저장했기 때문에 별다른 의심 없이 작성했었는데 long 으로 바꾸니 잘 해결되었다.

 

 

 

교훈

오타 조심하자.