개발환경은 vscode, openjdk11, springboot, influxdb, mysql 이다.
influxdb의 데이터를 다운샘플링해서 mysql에 넣어야하는데
continuous query로 처리하기에는 너무나 수가 많고 복잡한 로직(다운 샘플링하는 조건)들이 있어서
batch로 개발하게 되었다.
그래서 pom.xml에 dependency 추가하고
<dependency>
<groupId>org.influxdb</groupId>
<artifactId>influxdb-java</artifactId>
<version>2.22</version>
</dependency>
influxdb에서 수신한 데이터를 받을 SeriesData 클래스를 만들었다.
@Measurement(name="SeriesData")
@Getter
@Setter
public class SeriesData {
@Column(name="time")
private Instant time;
//(이하 생략)
}
컴파일도 이상없고 배치도 잘돌아가는 듯하였으나 mysql에 데이터가 하나도 들어오지 않았다.
Measurement 에 name attribute 의 값과 일치하는 measurement에서만 데이터를 받아올수 있는 것이었다.
그럼 mesurement가 백개가 넘고 앞으로도 늘어날텐데 똑같은 클래스를 name만 바꿔서 계속 만들어야 하는건가?
>> 나는 그렇게 코딩안한다
>> 자료조사 시작
찾고 또 찾아서 이방법 저방법 다 해봤으나 결국에는 다 실패하던 와중
[나를 살려준 포스트] 를 영접한다.
https://rotadev.com/adding-java-annotations-at-runtime-dev/
Adding Java Annotations at Runtime – Dev – RotaDEV.com
The best answers to the question “Adding Java Annotations at Runtime” in the category Dev. QUESTION: Is it possible to add an annotation to an object (in my case in particular, a Method) at runtime? For a bit more explanation: I have two modules, modul
rotadev.com
방법은 간단하다.
위 포스트에서 RuntimeAnnotation 소스를 고대로 긁어다가 클래스를 하나 만들어서 사용만 하면 된다.
사용법은 아래와 같다. (미래의 나를위해 남기자..)
String mesurementListQuery = "SHOW MEASUREMENTS";
QueryResult measurementResult = influxDB.query(new Query(mesurementListQuery));
InfluxDBResultMapper resultMapper = new InfluxDBResultMapper();
if (measurementResult.getResults().size() > 0) {
for (Result measurement : measurementResult.getResults()) {
if(measurement.getSeries() == null) {
// measurement 없을시에 함수 종료
break;
}
List<List<Object>> measurementList = measurement.getSeries().get(0).getValues();
for(List<Object> measurements : measurementList) {
String measurementName = measurements.get(0).toString();
//(중략)
String ReadQuery = "select * from " + measurementName + " where parameter='" + PARAM_STR + "' and time >= " + from + " and time < " + to;
QueryResult Readtables = influxDB.query(new Query(ReadQuery));
if(Readtables.getResults().get(0).getSeries() == null)
continue; // 결과 없으면 pass
// Measurement annotation = SeriesData.class.getAnnotation(Measurement.class);
// log.debug("before @ = {} ", annotation);
Map<String, Object> valuesMap = new HashMap<>();
valuesMap.put("name", measurementName);
RuntimeAnnotations.putAnnotation(SeriesData.class, Measurement.class, valuesMap);
List<SeriesData> tmp = resultMapper.toPOJO(Readtables, SeriesData.class );
// Measurement annotation = SeriesData.class.getAnnotation(Measurement.class);
// log.debug("after @ = {} ", annotation);
//(이하 생략)
아주 잘 된다.
다만 배치가 동시에 도는게 생기면 문제가 될수있을것 같아 배치별로 SeriesData1,2,3 이런식으로 몇개 더 만들어줬다.
(배치당 한개씩!)
'개발 > java' 카테고리의 다른 글
| Logbook 으로 access log 남기기 (2) | 2024.01.04 |
|---|---|
| mybatis interceptor 암복호화 처리 (1) | 2023.12.13 |
| JPA EntityListener로 multi JpaRepository save (1) | 2022.09.07 |
| vscode debugger에서 java.lang.ExceptionInInitializerError 잡기 (0) | 2022.09.07 |
| CutomException 처리 (1) (0) | 2022.07.07 |