mysql 8버전부터 rank over 함수가 들어오면서 드디어! 편한 함수의 세상이 열리긴 한다만..
아직 5.7을 사용하고 있기에 그 이하 버전에 등수를 구하는 방법을 알아야 한다.
서버에 부하가 가지 않고 제일 좋은 방법은 집계할 때 등수를 같이 쌓아주어 그냥 select 해가면 되는 것이지만..
서버는 그닥 user-friendly 하지 않다. 그리고 기획자는 서버에 없는 것만 요청한다..
1. count 사용 서브쿼리
select * from (
select
(select count(*) +1 from table for_rank where for_rank.start_date ='2023-02-06' and for_rank.prize_total > this.prize_total) as r,
this.*
from table this
where this.start_date ='2023-02-06'
order by prize_total desc
) as with_rank
where id = 'tbot0275'
2. @사용자 정의 변수 사용
select * from (
select (@rank := @rank +1) as r,
this.*
from table this, (select @rank := 0) as ranking
where this.start_date ='2023-02-06'
order by prize_total desc
)as weekly_with_rank
where id = 'tbot0275'
허나 두 쿼리의 결과가 다를 수 있다. 왜냐면 동점자를 다루는 방식이 다르기 때문.
위 이미지에서처럼 1번의 경우 동점자를 같은 등수로 치게 되고 2번의 경우는 어쨌건 한 줄 서기라 조회에 따라 랜덤 하게 등수가 나올 수 있다.
연결된 서비스 중 아무데서나 위 api를 호출하면 204 성공이 떨어지고 spring cloud config 서버를 통해 받고 있던 데이터들이 전 서비스에 걸쳐 모두 한 번에 refresh 되는 것을 볼 수 있다. (이전에는 각각 /actuator/refresh를 호출했어야 했음)
파일을 바로 볼거라 file:// 로 시작하는데 깃으로 관리한다면 아래 처럼 해당 주소를 기입하면 될 것 같다.
git:
uri: https://github.com/haileyjhbang/inflearn-config.git
# username: bbb //private repository 일 경우 필요
# password: aaa //private repository 일 경우 필요
# uri: file:///Users/JIHYUN BANG/Documents/source/inflearn/git-local-repo
여기서 주의해야하는 것은 파일 경로를 알기 위해 아래와 같이 명령어를 입력할 경우 (윈도우의 경우) 아래와 같이 C드라이브 아래부터 나오는데, /c 를 제외하고 /Users 부터 입력해야 한다는 것.
3. 서버를 시작하고 아래 주소로 확인해 보면 ecommerce.yml의 내용이 화면에 찍힌다.
http://localhost:8888/ecommerce/default
4. 허나 로그를 보면 아래와 같은 에러가 지나가는데
org.springframework.cloud.config.server.environment.NoSuchLabelException: No such label: main
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.refresh(JGitEnvironmentRepository.java:307) ~[spring-cloud-config-server-3.1.8.jar:3.1.8]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.getLocations(JGitEnvironmentRepository.java:256) ~[spring-cloud-config-server-3.1.8.jar:3.1.8]
at org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository.getLocations(MultipleJGitEnvironmentRepository.java:139) ~[spring-cloud-config-server-3.1.8.jar:3.1.8]
...
Caused by: org.eclipse.jgit.api.errors.RefNotFoundException: Ref main cannot be resolved
at org.eclipse.jgit.api.CheckoutCommand.call(CheckoutCommand.java:223) ~[org.eclipse.jgit-5.13.1.202206130422-r.jar:5.13.1.202206130422-r]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.checkout(JGitEnvironmentRepository.java:461) ~[spring-cloud-config-server-3.1.8.jar:3.1.8]
at org.springframework.cloud.config.server.environment.JGitEnvironmentRepository.refresh(JGitEnvironmentRepository.java:300) ~[spring-cloud-config-server-3.1.8.jar:3.1.8]
... 69 common frames omitted
2024-01-29 14:01:10.993 INFO 20748 --- [nio-8888-exec-1] .c.s.e.MultipleJGitEnvironmentRepository : Will try to refresh master label instead.
2024-01-29 14:01:11.218 WARN 20748 --- [nio-8888-exec-1] .c.s.e.MultipleJGitEnvironmentRepository : Could not merge remote for master remote: null
내용을 살펴보면 git-local-repo\ecommerce.yml 가 깃으로 관리되는데 main 브랜치가 없다는 것이다.
5. 신기한 점은 git uri에 file://로 설정할 경우 해당 파일 경로가 remote 깃과 연결되지 않았을 때는 파일 저장만으로도 바로 반영이 되었는데,
remote 깃과 연결한 후에는 파일을 수정하여 저장하더라도 자동으로 git에서 파일을 가져와서 override 하기 때문에 파일이 수정되지 않는다. 그 후에는 깃에 커밋하고 푸시해야만 반영됨.
즉, 파일시스템으로 프로퍼티를 관리하기위한 제대로된 방법은 native를 사용하는 것이다.
file://인 경우 ecommerce.yml이 반영되려면 깃에 커밋을 하지 않고도 저장만 하면 바로 반영이 된다. 즉, 저장을 하고 http://localhost:8888/ecommerce/default 를 호출하면 서버 재시작 없이도 변경된 내용을 확인할 수 있음. 물론 이는 지금 깃이 아닌 파일을 바라보도록 했기 때문.. 깃으로 수정했다면 remote push까지 해야한다. <<-깃에 연결 전
즉, bootstrap.yml로 로딩된 ecommerce.yml 은 위 순서에서 application-ecommerce.yml으로 인식되어 두번째 우선순위를 갖는다.
# application.yml에서 일부를 띠어서 공용으로 관리하기로 했기 때문에
# application.yml 이전에 불러올 정보를 가져올 프로퍼티임
spring:
cloud:
config:
uri: http://127.0.0.1:8888
name: ecommerce #파일명.yml 일 때 파일명 작성
3. 설정 후 서버 시작 시 아래 로그 지나감 확인
INFO 24156 --- [ restartedMain] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://127.0.0.1:8888
INFO 24156 --- [ restartedMain] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=ecommerce, profiles=[default], label=null, version=4c8198ea3c95ce84f573a78f41b637a4da81ad49, state=null
INFO 24156 --- [ restartedMain] b.c.PropertySourceBootstrapConfiguration : Located property source: [BootstrapPropertySource {name='bootstrapProperties-configClient'}, BootstrapPropertySource {name='bootstrapProperties-file:///Users/JIHYUN BANG/Documents/source/inflearn/git-local-repo/file:/C:/Users/JIHYUN BANG/Documents/source/inflearn/git-local-repo/ecommerce.yml'}]
4. 혹시 실행 시 아래 에러를 만나면, (그래도 실행은 잘 되지만) 프로퍼티 수정이 필요하다.
2024-01-29 15:29:08.527 ERROR 20628 --- [ restartedMain] o.a.catalina.session.StandardManager : Exception loading sessions from persistent storage
java.io.EOFException: null
at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2926) ~[na:na]
...
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.6.jar:2.7.6]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.6.jar:2.7.6]
at com.example.userservice.UserServiceApplication.main(UserServiceApplication.java:18) ~[classes/: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.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.7.6.jar:2.7.6]
해당 에러는 Tomcat의 SESSIONS.ser 파일이 없을 때 나는 에러로 추정되며, 해당 파일은 Tomcat이 애플리케이션 세션 상태를 저장하는 데 사용된다. (참고로 현 프로젝트는 spring-boot-starter-web 안의 tomcat을 사용 중)
세션 지속성(persistent session)은 웹 서버가 다운되거나 재시작될 때 사용자 세션 정보를 유지하는 기능인데 이를 통해 서버가 재시작된 후에도 사용자가 이전의 세션을 계속 사용할 수 있음.
세션 지속성을 '끈다'는 것은 이러한 세션 정보의 유지를 비활성화하는 것을 의미한다. 즉, 서버가 다운되거나 재시작되면 모든 사용자 세션 정보가 손실되는 것이다. 이 기능은 개발 과정에서 테스트나 디버깅을 쉽게 하기 위해 사용되곤 하는데, 서비스의 안정성이나 사용자 경험을 위해서는 일반적으로 세션 지속성이 활성화되어 있는 것이 좋다.
spring boot의 경우 내장 tomcat을 사용하기 때문에 직접적인 tomcat 설정 파일을 수정할 수 없음
따라서 에러를 없애기 위해서 application.yml에 아래 설정을 추가(기본적으로 true로 세팅됨)
server:
servlet:
session:
persistent: false
5. 공용 설정파일인 ecommerce.yml 파일을 동적으로 가져오려면
위의 config service에서는 파일 커밋 시 바로 반영된 것을 확인할 수 있었으나, 사용처에서는 바로 확인이 안 된다는 것을 알 수 있다. 동적으로 가져오려면 아래와 같은 방법이 있다.
java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
at io.jsonwebtoken.impl.Base64Codec.decode(Base64Codec.java:26) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.setSigningKey(DefaultJwtParser.java:151) ~[jjwt-0.9.1.jar:0.9.1]
at com.example.gatewayservice.filter.AuthorizationFilter.isValidJwt(AuthorizationFilter.java:54) ~[classes/:na]
: set할 때는 paidUser를 찾아 세팅하고 내릴 때는 자동 생성되는 getter사용
: 해결
정리
When using Jackson for JSON serialization and deserialization, it recognizes this convention and automatically maps it to the property name without the "is" prefix.
If you annotate a getter method with @JsonProperty, Jackson will use the annotated method as the getter for that property.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>runtime</scope> # <-- 기본이 test 로 되어 있고, 이러면 프로젝트에서 사용할 수 없음
</dependency>
spring:
h2:
console:
enabled: true
settings:
web-allow-others: true
path: /h2-console // H2 콘솔 사용한다는 뜻
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test //db 연결 후 테이블 자동 생성
하지만 서버가 뜨고 db 연결 시 아래와 같은 에러 발생
testdb 데이터베이스를 springboot실행 시 자동 생성해주어야 하는데 그렇지 못함.
H2 1.4.198 이후 버전부터는 보안 문제로 자동으로 디비를 생성하지 않음.
h2 버전의 문제로 1.4 -> 1.3.176으로 낮추면 해결됨
((최신 버전으로 해도 그러는지 확인 필요))
h2를 메인으로 쓰면서, 서비스 시작 시 entity 테이블을 자동으로 생성하고자 하는 경우