스프링 myBatis JSON 형식 입력하고 출력하기 : Spring myBatis JSONType input output  

스프링 myBatis JSON 형식 입력하고 출력하기 : Spring myBatis JSONType input output

개발환경

Java 7.x
Spring 4.x
myBatis 3.2.8
jackson 2.0.1
H2 1.4.180

myBatis 를 이용한 JSON 형식의 데이터를 저장하고 조회하는 로직을 간단하게 구현하는 방법을 설명하려고 한다.

데이터의 흐름

저장: [클라이언트] --JSON--> [Spring] --String JSON--> [DB]
조회: [DB] --String JSON--> [Spring] --Object JSON--> [클라이언트]

데이터의 흐름은 클라이언트에서 전송된 json 형식의 데이터를 서버 DB에 저장하고 다시 클라이언트로 json 데이터를 넘겨주는 작업인데... 흔히 json 데이터를 문자열로 변경하고 db에 저장한 후 출력할때는 다시 문자열을 객체로 변경하고 프론트엔드로 넘겨주는 식이다. 이렇게하면 domain의 데이터 형식이 문자열이여야하나 객체여야하나 혼동이 생길수도 있고 바인딩 과정이 복잡해지는 문제가 발생한다.

저장: [클라이언트] --JSON--> [Spring] --Object JSON--> [DB: JSON Parsing]
조회: [DB: JSON Parsing] --Object JSON--> [Spring] --JSON--> [클라이언트]

그래서 위의 데이터 흐름과 같이 JSON 파싱작업은 myBatis에서 하고 json 데이터 형식은 항상 객체로 유지하도록하여 심플한 로직을 구현할 수 있게 하였다.

로직 구현

테이블

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

CREATE TABLE ex (
  name VARCHAR(10),
  json  VARCHAR(4000)
);

도메인 클래스

package org.syaku.ex.domain;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import org.apache.commons.lang.builder.ToStringBuilder;

import java.util.Map;

/**
 * @author Seok Kyun. Choi. 최석균 (Syaku)
 * @site http://syaku.tistory.com
 * @since 16. 3. 7.
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class Ex {
    private String name;
    private Map<String, Object> json;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, Object> getJson() {
        return json;
    }

    public void setJson(Map<String, Object> json) {
        this.json = json;
    }

    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }
}

myBatis에서 지원하는 타입헨들러를 이용하면 쉽게 구현이 가능하다. JacksonParsing 클래스는 jackson 라이브러리를 이용하여 json 형식을 간편하게 파싱하기 위해 따로 만든 클래스이다.

package org.syaku.ex.mapper.type;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.syaku.common.object.JacksonParsing;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @author Seok Kyun. Choi. 최석균 (Syaku)
 * @site http://syaku.tistory.com
 * @since 16. 3. 8.
 */
public class JSONTypeHandler extends BaseTypeHandler<Object> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)
            throws SQLException {

        String p = JacksonParsing.toString(parameter);
        ps.setObject(i, p);
    }

    @Override
    public Object getNullableResult(ResultSet rs, String columnName)
            throws SQLException {
        Object d = rs.getObject(columnName);
        if(d == null) return d;
        return JacksonParsing.toMap(d.toString());
    }

    @Override
    public Object getNullableResult(ResultSet rs, int columnIndex)
            throws SQLException {
        Object d = rs.getObject(columnIndex);
        if(d == null) return d;
        return JacksonParsing.toMap(d.toString());
    }

    @Override
    public Object getNullableResult(CallableStatement cs, int columnIndex)
            throws SQLException {
        Object d = cs.getObject(columnIndex);
        if(d == null) return d;
        return JacksonParsing.toMap(d.toString());
    }
}
  • setNonNullParameter: 저장할때 데이터 파싱
  • getNullableResult, getNullableResult, getNullableResult : 조회할때 데이터 파싱

만들어지 타입헨들러를 맵퍼에 적용해보자.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.syaku.ex.mapper.ExMapper">

    <resultMap id="ex" type="org.syaku.ex.domain.Ex">
        <result property="name" column="name" />
        <result property="json" column="json" typeHandler="org.syaku.ex.mapper.type.JSONTypeHandler" />
    </resultMap>

    <select id="select" resultMap="ex">
        SELECT * FROM ex
    </select>

    <insert id="insert">
        INSERT INTO ex (
            name,
            json
        ) VALUES (
            #{name},
            #{json, typeHandler=org.syaku.ex.mapper.type.JSONTypeHandler}
        )
    </insert>

</mapper>

typeHandler 속성에 org.syaku.ex.mapper.type.JSONTypeHandler 패키지를 포함한 클래스명을 입력하면 된다.

테스트

package org.syaku.ex.service;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.syaku.ex.domain.Ex;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Seok Kyun. Choi. 최석균 (Syaku)
 * @site http://syaku.tistory.com
 * @since 16. 3. 8.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath*:config/*-context.xml" })
public class ExServiceTest {

    @Resource(name = "exService") ExService exService;

    @Test
    public void select() {
        Ex ex = new Ex();
        ex.setName("syaku");

        Map<String, Object> json = new HashMap<>();
        json.put("name","syaku");
        json.put("value","spring");
        ex.setJson(json);

        exService.insert(ex);
        exService.insert(ex);
        exService.insert(ex);
        exService.insert(ex);
        exService.insert(ex);

        for(Ex data : exService.getExList()) {
            System.out.println(data.toString());
        }

    }
}

결과

org.syaku.ex.domain.Ex@2f7f2ae[name=syaku,json={name=syaku, value=spring}]
org.syaku.ex.domain.Ex@645d7f07[name=syaku,json={name=syaku, value=spring}]
org.syaku.ex.domain.Ex@363ed80b[name=syaku,json={name=syaku, value=spring}]
org.syaku.ex.domain.Ex@57d9d5ff[name=syaku,json={name=syaku, value=spring}]
org.syaku.ex.domain.Ex@1e708568[name=syaku,json={name=syaku, value=spring}]

Github

https://github.com/syakuis/spring-syaku/tree/mybatis-ex1



출처: https://syaku.tistory.com/311 [개발자 샤쿠 (Syaku)]

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
350 Jackson 라이브러리를 활용한 Map to Json Serialization 처리 졸리운_곰 2020.09.24 249
349 Mybatis selectMap 예제 file 졸리운_곰 2020.09.24 2362
» 스프링 myBatis JSON 형식 입력하고 출력하기 : Spring myBatis JSONType input output 졸리운_곰 2020.09.24 274
347 Java code example to export from database to CSV file file 졸리운_곰 2020.09.24 205
346 Export Oracle table to CSV file in Java 오라클 테이블을 CSV 파일로 변환 졸리운_곰 2020.09.24 760
345 Spring Batch and MongoDB 졸리운_곰 2020.09.21 307
344 Spring Batch to Read From MongoDB and Generate XML Files 졸리운_곰 2020.09.21 160
343 Spring Batch Goodies With MongoDB 졸리운_곰 2020.09.21 143
342 MongoBatis Ver 1.04 in SpringFrameWork (mongoDB + MyBatis) file 졸리운_곰 2020.09.21 207
341 Spring 몽고DB 연동 졸리운_곰 2020.09.21 182
340 MongoDB CRUD with Java Driver 몽고디비 java 연결 및 CRUD 테스트 졸리운_곰 2020.09.21 777
339 LinkedList - Java 구현 file 졸리운_곰 2020.03.25 181
338 How to use Weka in your Java code 졸리운_곰 2020.02.01 307
337 weka and java eclipse example : A Simple Machine Learning Example in Java file 졸리운_곰 2020.01.31 362
336 머신러닝? weka file 졸리운_곰 2020.01.31 357
335 [Weka] Weka를 이용한 Iris 데이터 머신러닝 file 졸리운_곰 2020.01.30 363
334 [강좌] WEKA 사용법 (간단한 분류, 의사결정트리 분석 설명) file 졸리운_곰 2020.01.30 343
333 MyBatis 에서 procedure 처리 졸리운_곰 2020.01.27 1142
332 neo4j 시작하기 졸리운_곰 2019.12.25 256
331 Neo4J Cypher 가이드 file 졸리운_곰 2019.12.25 273
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED