0. 해당 기능을 사용하게 된 배경
DB에 3개의 공통된 값을 가지는 17개의 리스트형 데이터를 받아서 넣어줘야 할 일이 생겼는데, 이를 해결하기 위해서는 3개 + α(Id, 생성시간 등)의 컬럼을 가지는 17개의 엔티티를 생성 하던가, 51가지 + α(Id, 생성시간 등) 의 컬럼을 가지는 하나의 테이블을 생성하여야 했는데, 이를 컨트롤 하기에는 DB에 부담이 너무 많이 갈 것으로 판단하여, 데이터를 한 컬럼에 JSON 형태로 넣기로 결정하였습니다.
1. 환경 및 라이브러리 설치
해당 포스팅은 MariaDB를 사용한 환경이며 라이브러리를 설치하기 전에 사용하는 DB와 맞는 hibernate 버전을 설치해주시면 됩니다.
https://github.com/vladmihalcea/hypersistence-utils
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<>();
}
해당 컨트롤러에 요청을 하면, 데이터가 잘 들어가는 모습을 확인할 수 있습니다.