Notice
Recent Posts
Recent Comments
Link
반응형
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- mysql json type
- 트랜잭션 전파속성
- spring boot 멀티모듈
- jpa json type
- JSON type
- server mode
- aws cli s3 exclude directory
- IAM이란
- 멀티모듈
- in memory
- json type index
- Transactiona
- Jenkins
- oracle cloud
- json type 활용
- aws cli s3
- 무료 인스턴스
- jpa 환경에서 json type 활용하기
- aws cli s3 cp
- json type column 생성
- IAM MFA
- multi module
- 선언적 트랜잭션
- jenkins 배포
- 프리티어 인스턴스
- AWS IAM MFA
- h2 연동
- Oracle Linux 8
- h2 intellij
- aws cli s3 exclude folder
Archives
- Today
- Total
Chris Devlog
Mysql에서 Json type 활용하기(2) 본문
반응형
들어가며
이번 글에서는 Mysql에서 Json type 활용하기(1)에서 설정한 데이터를 기반으로 JPA와 연계하여 활용하는방법에 대해 이야기 해보겠습니다.
# 현재 테이블 구조
Enity 설정 Type
1. Map
필드 추가
@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "json_data", columnDefinition = "json")
private Map<String, Object> dataJson;
사용
@Autowired
JsonTest1Repository jsonTest1Repository;
@Test
void test2() throws JsonProcessingException {
String json = "{\"key1\": \"value1\", \"key2\": 30000, \"key3\": \"2024-12-30 02:27:00\"}";
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> map = objectMapper.readValue(json, Map.class);
JsonTest1 jsonTest1 = jsonTest1Repository.save(JsonTest1.builder()
.dataJson(map)
.build());
Assertions.assertEquals("value1", jsonTest1.getDataJson().get("key1"));
Assertions.assertEquals(30000, jsonTest1.getDataJson().get("key2"));
Assertions.assertEquals("2024-12-30 02:27:00", jsonTest1.getDataJson().get("key3"));
}
장점
- 맵으로 지정하면 json 데이터를 바로 맵에서 꺼내쓰기 좋음
- 설정 및 사용이 간단함
단점
- 저장시 Mapper을 이용해 Map으로 변환후 저장가능
- 조회된 데이터를 활용하기 위해서는 추가적인 작업이 필요(형변환, DTO 맵핑 등)
- Object Mapper, Gson등 Mapper사용시 LocalDateTime과 관련된 추가적인 설정이 필요(설정하지않으면 에러발생)
- Map을 사용하기 때문에 디버깅이 어려움
2. String
필드추가
@JdbcTypeCode(SqlTypes.JSON) // JSON 타입 매핑
@Column(name = "json_data", columnDefinition = "json")
private String dataJson;
장점
- 데이터 저장이 쉬움. 특히 벌크 인설트/업설트(유니크 데이터 존재시 업데이트, 없으면 인설트)인경우 코드가 현저히 줄어듬
단점
- 필드 자체를 활용하기엔 어려움이 있음
Entity에 Map으로 선언하나 String으로 선언하나 사실 큰 차이는 없지만 굳이 String으로 선언하는 이유는 json 필드는 저장할 때만 사용하고 json 필드에서 값을 꺼내쓰지 않도록 하기 위해서 입니다
Jpa 환경에서 활용하기
Entity
@Getter
@Entity
@Table(name = "json_to_str")
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor
@DynamicInsert
public class JsonToStr {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Comment("json test id")
@Column(name = "json_test_id", columnDefinition = "bigint")
private Long id;
@JdbcTypeCode(SqlTypes.JSON) // JSON 타입 매핑
@Column(name = "json_data", columnDefinition = "json")
private String jsonData;
@Column(name = "key1", insertable = false, updatable = false)
private String key1;
@Column(name = "key2", insertable = false, updatable = false)
private Long key2;
@Column(name = "key3", insertable = false, updatable = false)
private LocalDateTime key3;
@CreationTimestamp
@Column(name = "create_at", nullable = false, updatable = false, columnDefinition = "timestamp default current_timestamp")
private LocalDateTime createAt;
@Builder
public JsonToStr(String dataJson) {
this.dataJson = dataJson;
}
}
이전글에서 json_test 테이블에 기본필드몇개를 추가하여 엔티티를 생성했습니다
기존 필드와의 차이점으로 json_data를 컬럼으로 등록한 경우 해당 컬럼은 "읽기전용"이기 때문에 필드에 insertable & updatable을 false 처리하여 save 메소드 호출시 json_data가 저장될 때 insert 쿼리에서 json_data만 저장 될 수 있도록 해줘야합니다
1. 아무 설정 없이 데이터 저장 후 데이터 확인
@Autowired
JsonToStrRepository jsonToStrRepository;
@Test
void test2() {
String json = "{\"key1\": \"value1\", \"key2\": 30000, \"key3\": \"2024-12-30 02:27:00\"}";
JsonToStr jsonToStr = jsonToStrRepository.save(JsonToStr.builder()
.dataJson(json)
.build());
Assertions.assertEquals("value1", jsonToStr.getKey1());
Assertions.assertEquals(30000, jsonToStr.getKey2());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Assertions.assertEquals(LocalDateTime.parse("2024-12-30 02:27:00", formatter), jsonToStr.getKey3());
}
Execute DML :
insert
into
json_to_str
(create_at, json_data)
values
('2024-12-31T21:41:39.340+0900', cast('{"key1": "value1", "key2": 30000, "key3": "2024-12-30 02:27:00"}' as json))
Expected :value1
Actual :null
<Click to see difference>
org.opentest4j.AssertionFailedError: expected: <value1> but was: <null>
영속성 컨텍스트에 캐시된 데이터는 jsonData밖에 없기 때문에 조회시 null일 수 밖에 없습니다
2. findById를 통해 데이터 리프래시
@Autowired
JsonToStrRepository jsonToStrRepository;
@Test
void test2() {
String json = "{\"key1\": \"value1\", \"key2\": 30000, \"key3\": \"2024-12-30 02:27:00\"}";
JsonToStr jsonToStr = jsonToStrRepository.save(JsonToStr.builder()
.jsonData(json)
.build());
// Id를 통해 데이터를 다시한번 불러옴
JsonToStr refreshJsonToStr = jsonToStrRepository.findById(jsonToStr.getId())
.orElseThrow(RuntimeException::new);
Assertions.assertEquals("value1", refreshJsonToStr.getKey1());
Assertions.assertEquals(30000, refreshJsonToStr.getKey2());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
Assertions.assertEquals(LocalDateTime.parse("2024-12-30 02:27:00", formatter), refreshJsonToStr.getKey3());
}
Execute DML :
insert
into
json_to_str
(create_at, json_data)
values
('2024-12-31T22:07:17.462+0900', cast('{"key1": "value1", "key2": 30000, "key3": "2024-12-30 02:27:00"}' as json))
Execute DML :
select
jts1_0.json_test_id,
jts1_0.create_at,
jts1_0.json_data,
jts1_0.key1,
jts1_0.key2,
jts1_0.key3
from
json_to_str jts1_0
where
jts1_0.json_test_id=6
Tests passed: 1
데이터를 재 조회 해옴으로써 테스트에 통과하게 됩니다.
반응형
'Spring Boot > JPA' 카테고리의 다른 글
Mysql에서 Json type 활용하기(3) (0) | 2025.01.02 |
---|---|
Mysql에서 Json type 활용하기(1) (0) | 2024.12.30 |