먼저 이 글을 보기 전에 알고 있으면 더 좋은 글입니다.
1번. MySQL JSON DATA TYPE
2018/11/30 - [Develop/MySQL] - [MySQL] MySQL JSON - MySQL 5.7 JSON Functions
2번. MySQL에서의 '일반' 값을 JSON형식으로 가져오기
2018/10/28 - [Develop/Spring Boot] - Spring boot JPA EntityManager를 이용한 Map형식으로 mapping하기
2018/10/24 - [Develop/Spring Boot] - Spring boot jpa map, hashmap, JSON형식
3번. JSON PARSING
2018/11/13 - [Develop/Spring Boot] - Spring Boot Json, hashmap to json , JsonObject 만들기- JSON 마지막
2018/11/12 - [Develop/Spring Boot] - Spring Boot Deserialization Json, Deserialization JsonString to JsonObject - Json 4편
2018/11/09 - [Develop/Spring Boot] - Spring Boot Json, Jackson을 이용한 JsonParsing - Json 3편
2018/11/07 - [Develop/Spring Boot] - Spring Boot Json, Gson을 이용한 JsonObject to String, String to JsonObject- JSON 2편
2018/11/06 - [Develop/Spring Boot] - Spring Boot Json, JsonObject로 만들기 - JSON 1편
나도 SPRING BOOT 에서 어떻게 가져오는지 많이 검색해봤으나. 자료가 거의 없어서 열심히 삽질했던 것 같다.
수 많은 삽질 끝에 알아내서 필요한 곳에 사용중이다.
이번 글은 MySQL에서 SELECT시 일반 DATA 형식이 아닌 JSON DATA TYPE을 SPRING BOOT 에 SELECT하는 내용이다.
우선 일반 DATA형식은 그냥 말그대로 SELECT id, name FROM test 해서 가져오는 내용들이고
JSON DATA TYPE 형식은 위의 1번 링크에서 확인할 수 있다.
1. 우선 이번에 사용할 예제 테이블 및 데이터이다. 1번링크에서 확인 가능하다.
2. 먼저 JSON DATA TYPE을 불러올 코드를 작성한다.
아래의 코드를 보면 CONCAT_WS('\\\\', 부분이 있다.
사실 JSON DATA TYPE을 가져올 때 JSON_OBJECT를 사용하면 가져올 수 있으나. 사용하는 이유는
SPRING BOOT에서 CONCAT_WS('\\\\', 를 사용하지 않으면 MySQL에서 값을 불러올때 쌍따옴표를 지워버린다.
그래서 만약 CONCAT_WS를 사용하지않고 JSON_OBJECT만을 이용하여 SELECT하면
ex) {"ID": 1, "NAME": "TEST", "PASSWORD": "1234", "PHONE_NUM": "010-1111-1111"} 이렇게 불러와야할 값이
{" 이렇게 나오고 뒤의 내용은 다 짤려버린다.
그래서 CONCAT_WS 함수를 이용하여 쌍따옴표가 안짤리고 SELECT하기 위해 앞에 역슬래쉬를 붙인다.
4개 붙이는 이유는 두개 붙이니까 SPRING BOOT단에서 짤려버리더라...... 그래서 4개 붙인다.
그리고 CONCAT_WS를 사용하면 값을 Byte로 불러온다. 그래서 String 형식이나 기타 외의 데이터로는 불러오지 못하므로
항상 Object 데이터 형식을 사용해서 불러와야 한다. 그 후 Object를 Byte로 변환 그리고 Byte를 String으로 변환하는 방법 등을 사용 해야 한다.
아래의 코드에서도 우선 List로 결과를 불러오고 Object를 통해 Byte로 변환 그리고 Byte를 다시 String으로 변환한다.
|
@GetMapping("/test")
public void test() {
Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
+ "as TEST " + "FROM " + "test t");
List r = query.getResultList();
for (Object obj : r) {
byte[] b = (byte[]) obj;
String value = new String(b, StandardCharsets.UTF_8);
System.out.println(value);
}
}
위 코드를 실행하면 아래와 같은 JSON 타입의 내용을 Spring Boot에서 불러올 수 있다.
3. 이 Json String을 JsonObject로 만들어보자
3번 링크의 Gson이나 Jackson, JsonObject 등등 을 이용하여 만들 수 있다.
Jackson을 이용하여 한번 만들어 보겠다.
먼저 TestDTO 클래스를 하나 만든다
3번링크의 Json 1편의 DTO에서 password와 phone_num 변수를 추가한다.
만든 후 현재 데이터를 2개가 불러오기 때문에 객체 배열로 생성하였다.
그 후 각 클래스 배열마다 Jackson의 objectmapper를 사용하여 Json String을 Json Object로 변환시켜주었다.
Query query = entityManager.createNativeQuery("SELECT " + "concat_ws('\\\\', "
+ "json_object('id', t.id, 'password', t.password, 'name', t.name, 'phone_num', t.phone_num)) "
+ "as TEST " + "FROM " + "test t");
List r = query.getResultList();
ObjectMapper objectMapper = new ObjectMapper();
TestDTO t[] = new TestDTO[r.size()];
int i=0;
for (Object obj : r) {
byte[] b = (byte[]) obj;
String value = new String(b, StandardCharsets.UTF_8);
try {
t[i]= objectMapper.readValue(value, TestDTO.class);
i++;
}
catch (IOException e) {
e.printStackTrace();
}
}
for(TestDTO test : t) {
System.out.println(test.getId());
System.out.println(test.getPassword());
System.out.println(test.getName());
System.out.println(test.getPhone_num());
System.out.println();
}
아래와 같이 결과가 나온다
이것을 많은 형식을 이용하여 불러 올 수있다 2번링크를 사용하여 애초에 Map으로 불러와서 mapping시키거나 할 수 있다.
Map으로 불러와서 mapping할 경우 문제점은 정규식을 통해 파싱해줘야 하는 단점이있다.
왜냐하면 Json값이 { "id" : 1 } 이렇다면 Map으로 불러올경우 "{ "id" : 1 }" 이렇게 중괄호에 쌍따옴표가 붙어버린다.
그래서 정규식을 통해 중괄호의 쌍따옴표만 지워야 하는 단점이 있다. 하지만 나는 이러한 단점에도 불구하고도
JSON_TYPE과 함께 일반 데이터까지 가지의 값을 가져 와야하기 때문에 자주 사용한다.