inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

재고시스템으로 알아보는 동시성이슈 해결방법

스프링 부트 2.7.9 native query 에러

1224

김지현

작성한 질문수 3

0

- 학습 관련 질문을 남겨주세요. 상세히 작성하면 더 좋아요!
- 먼저 유사한 질문이 있었는지 검색해보세요.
- 서로 예의를 지키며 존중하는 문화를 만들어가요.
- 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.

혹시 저와 같이 에러가 발생하는 분들이 있을 수도 있을 것 같아서 여기다 글을 적습니다!

스프링 부트 2.7.9 버전으로 진행하다 named lock 부분에서 native query를 사용하니

org.springframework.beans.factory.UnsatisfiedDependencyException

이러 에러가 발생하더라구요! 그래서 이런저런 방법을 찾아보다가 혹시나 해서 스프링 부트 2.7.9 를 강의 버전에 맞춰 2.7.0 으로 바꿨더니 해결이 되었습니다.

혹시나 저와 같이 오류가 나시는 분들은 참고해주세요!!

(근데 오류가 나는 이유까지는 모르겠네요 ㅠㅠ)

java spring 동시성

답변 2

2

임재승

spring boot 2.7.9로 올리는거 검토하면서 native query 사용한 repository 주입한 빈 생성 실패해서
추적해보니 이게 내부적으로 counting query인지 판별하는 부분에서 버그가 있네요.

아래는 QueryUtils라는 class의 메소드입니다.
코드 세그먼트를 보면 countProjection이 null인 경우 variable이 null이 되는 케이스가 분명히 존재하는데 그에 대한 방어가 없이 nativeQuery가 true인 경우 variable.contains를 수행해서 NPE가 발생하면서 빈 생성이 실패하는 경우더라고요.

static String createCountQueryFor(String originalQuery, @Nullable String countProjection, boolean nativeQuery) {

		Assert.hasText(originalQuery, "OriginalQuery must not be null or empty!");

		Matcher matcher = COUNT_MATCH.matcher(originalQuery);
		String countQuery;

		if (countProjection == null) {

			String variable = matcher.matches() ? matcher.group(VARIABLE_NAME_GROUP_INDEX) : null;
			boolean useVariable = StringUtils.hasText(variable) //
					&& !variable.startsWith("new") // select [new com.example.User...
					&& !variable.startsWith(" new") // select distinct[ new com.example.User...
					&& !variable.startsWith("count(") // select [count(...
					&& !variable.contains(",");

			String complexCountValue = matcher.matches() && StringUtils.hasText(matcher.group(COMPLEX_COUNT_FIRST_INDEX))
					? COMPLEX_COUNT_VALUE
					: COMPLEX_COUNT_LAST_VALUE;

			String replacement = useVariable ? SIMPLE_COUNT_VALUE : complexCountValue;

			if (nativeQuery && (variable.contains(",") || "*".equals(variable))) {
				replacement = "1";
			} else {

				String alias = QueryUtils.detectAlias(originalQuery);
				if (("*".equals(variable) && alias != null)) {
					replacement = alias;
				}
			}

			countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, replacement));
		} else {
			countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, countProjection));
		}

		return countQuery.replaceFirst(ORDER_BY_PART, "");
	}

 

1

김지현

와... 감사합니다!! 아직 많이 부족해서 완전히 이해하진 못한 것 같지만 무슨 원리인지는 알 것 같습니다!! 자세한 답변 너무 감사합니다!

1

최상용

김지현님 공유 감사드립니다!

레디선 테스트코드에서 채널이름은 없어도 되는건가요?

0

45

2

낙관적 락을 사용할 떄 차이점

0

125

2

동시성 검증 코드에 관한 문의

0

96

2

단일연산

0

70

2

낙관적락vs. 레디스락

0

108

2

안녕하세요. 레디슨 질문있습니다..!!

0

67

2

@Lock(OPTIMISTIC)이 필요한 이유

0

90

2

get_lock 의 timeout이 3000초 이던데 너무 긴거 아닌가요?

0

132

2

DataSource Hikari 사용 이유

0

148

2

saveAndFlush 사용 이유 문의

0

113

3

비관적 락 VS 네임드 락

0

161

3

application.yaml 에 redis 정보

0

101

2

왜 클래스 이름에 Facade 가 붙나요?

0

185

2

@Transactional 으로 인한 동시성 문제 발생 원인이 궁금합니다.

0

220

2

@modifying 이용한 동시성 제어

0

168

2

DB락과 분산락

0

262

2

NamedLock 테스트 실패

0

186

2

테스트에서 트랜잭션 어노테이션 질문 있습니다.

0

174

2

optimistic Lock 재시도 질문입니다.

0

233

2

낙관적 락 테스트 실패

0

242

2

오류?

0

1630

4

LettureLockStockFacadeTest에서 오류가 발생합니다.

1

268

2

Pessimistic Lock 전체 테스트 오류 문의

0

362

3

비관적 락 vs 레디스(Lettuce)락 비교 관련 질문

0

462

2