0. 해당 기능을 사용하게 된 배경
DB에 3개의 공통된 값을 가지는 17개의 리스트형 데이터를 받아서 넣어줘야 할 일이 생겼는데, 이를 해결하기 위해서는 3개 + α(Id, 생성시간 등)의 컬럼을 가지는 17개의 엔티티를 생성 하던가, 51가지 + α(Id, 생성시간 등) 의 컬럼을 가지는 하나의 테이블을 생성하여야 했는데, 이를 컨트롤 하기에는 DB에 부담이 너무 많이 갈 것으로 판단하여, 데이터를 한 컬럼에 JSON 형태로 넣기로 결정하였습니다.
1. 환경 및 라이브러리 설치
해당 포스팅은 MariaDB를 사용한 환경이며 라이브러리를 설치하기 전에 사용하는 DB와 맞는 hibernate 버전을 설치해주시면 됩니다.
https://github.com/vladmihalcea/hypersistence-utils
GitHub - vladmihalcea/hypersistence-utils: The Hypersistence Utils library (previously known as Hibernate Types) gives you Sprin
The Hypersistence Utils library (previously known as Hibernate Types) gives you Spring and Hibernate utilities that can help you get the most out of your data access layer. - GitHub - vladmihalcea/...
github.com
gradle에 해당 라이브러리를 설치 해 줍니다.
implementation("com.vladmihalcea:hibernate-types-55:2.20.0")
해당 라이브러리에서는 JsonType
을 컬럼에 매핑하는 것은 Oracle, SQL Server, PostgreSQL, mySQL에서만 허용된다고 설명합니다.
2. 요청 데이터와 컨트롤러 확인하기
먼저 요청 데이터를 확인 해 보겠습니다.
{"userId": 1,
"data": [
[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, 32, 33],
[34, 35, 36],
[37, 38, 39],
[40, 41, 42],
[43, 44, 45],
[46, 47, 48],
[49, 50, 51]
]
}
해당 데이터가 컨트롤러로 요청이 됩니다.
Controller
@PostMapping
Response<ExampleDto> saveData(@RequestBody ExampleDto ExampleDto) {
return Response.ok(exampleService.saveExample(exampleDto));
}
3. DTO와 서비스 로직 확인하기
ExampleDto에서는 UserId와 data를 매핑해 줍니다.
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ExampleDto {
long userId;
ArrayList<Object> data;
}
이번 요청에서는 List값을 넘겨주기 때문에, 서비스에서 Json값으로 매핑 해주기위해서 Map으로 바꿔 줍니다.
이는 해당 라이브러리에서 JsonType만 지원하기 때문에 List형태의 값을 넣기위해 Map에 값을 넣게 됩니다.
만약 요청 데이터의 값 자체가 JSON형식이라면 Dto에서 data의 자료형을 Map<String, Object>
으로 매핑하면 되겠지요?
@Service
@RequiredArgsConstructor
public class ExampleServiceImpl implements ExampleService {
final ExampleRepository exampleRepository;
@Override
@Transactional
public ExampleDto saveExample(ExampleDto exampleDto) {
HashMap<String, Object> data = new HashMap<>();
data.put("data", ExampleDto.getdata());
exampleRepository.save(Example.builder()
.userId(ExampleDto.getUserId())
.data(keypoints)
.build());
return ExampleDto;
}
}
4. 엔티티의 데이터 타입 작성하기
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@TypeDef(name = "json", typeClass = JsonType.class) //JsonType의 클래스 정의
public class Example extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long userid;
@Type(type = "json")
@Column(name = "data", columnDefinition = "longtext") //MariaDB에서는 JSON타입을 longtext타입으로 선언합니다.
Map<String, Object> data= new HashMap<>();
}

해당 컨트롤러에 요청을 하면, 데이터가 잘 들어가는 모습을 확인할 수 있습니다.