JPA 데이터 포맷 조작 @Converter

아무튼 간에·2022년 10월 14일
0

JPA

목록 보기
2/2

개발환경
OS: Windows 11
IDE: Spring Tool Suite 4.14.1
JAVA: 17


  • 단순 조회가 아닌 date_format() 등과 같이 컨버팅하여 조회하고 싶은 경우 @Convert 어노테이션을 사용한다.
  • 쿼리를 직접적으로 조작할 순 없고, 조회나 조작한 값을 DB 컬럼과 엔티티 필드에 매칭할 때 컨버팅한 값을 넣어주는 방식인 듯하다.
  • 데이터를 조작할 클래스(AttributeConverter구현)를 생성하고 필드에 @Convert와 함께 붙여주면 된다. 간편함.
  • 아래 예시들은 방식이 모두 같고 데이터 조작을 어떻게 했는지만 다름.

- 날짜 데이터 포맷

- varchar to dateformatString

예시) ‘YYYYMMDDHHmmssSSS’ 포맷의 varchar 타입으로 저장하고 있는데 이를 ‘YYYY/MM/DD HH:mm:ss’ 형식으로 포맷팅하여 조회하고 싶을 경우

1. 컬럼 설정

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import org.h2.util.json.JSONObject;

// 컨버팅 클래스
import com.armton.history.util.StringToFormatDateStringConverter;
import com.armton.history.util.StringToJson;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Entity
@Setter
@Getter
@Table(name = "service_history")
@ToString
@NoArgsConstructor
public class ServiceHistory {

	@Id
	@Column
	private String id;
	
	@Column(name = "log_dt")
	@Convert(converter=StringToFormatDateStringConverter.class)
	private String logDt;
		
}
  • 변환하고 싶은 필드에 @Convert(converter={컨버트 클래스}) 어노테이션을 붙인다.
  1. 컨버팅 클래스 생성
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

/**
* varchar 타입 데이터를 Date 포맷의 String으로 변환하는 클래스
*/
@Converter
public class StringToFormatDateStringConverter implements AttributeConverter<String, String>{	//AttributeConverter<엔티티 컬럼 타입, 데이터베이스 컬럼 타입>
	
	private static final Logger logger = LoggerFactory.getLogger(StringToFormatDateStringConverter.class);  // logger

	@Override	// 엔티티 -> DB 시
	public String convertToDatabaseColumn(String attribute) {
		// TODO Auto-generated method stub
		return attribute;
	}

	@Override	// DB값 -> 엔티티 시
	public String convertToEntityAttribute(String dbData) {   // dbData = "20221006102259045"
		
		StringBuilder sb = new StringBuilder();
		if(dbData!=null) {
			SimpleDateFormat dbFormat = new SimpleDateFormat("yyyyMMddHHmmSSSS");
			Date date = null;
			try {
				date = dbFormat.parse(dbData);    // date = "Thu Oct 06 10:22:59 KST 2022"
				SimpleDateFormat entityFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				sb.append(entityFormat.format(date));       // entityFormat.format(date) = "2022/10/06 10:22:59"
			} catch (ParseException e) {
				e.printStackTrace();
				logger.error("Error Occured during convert \"log_dt\" value to entity attribute format.");
			}
		}
		
		return sb.toString();
	}

}
  • AttributeConverter를 구현한 클래스를 생성한다.
    • AttributeConverter<엔티티 컬럼 타입, 데이터베이스 컬럼 타입>
  • convertToDatabaseColumn(String attribute): 만약 insertable=true이거나 updatable=true일 경우 데이터를 DB 타입에 맞게 컨버팅하는 메소드
    • ⚠️주의: insertable=false, updatable=false의 경우에도 무조건 null이 아닌 파라미터를 리턴해야 함. 데이터 조작 없이 조회만 한다고 이 메소드를 기본 override된 상태(return null)로 사용할 경우 조회 결과가 null 일 수 있음.
    • 잘못된 코드
      @Override	// 엔티티 -> DB 시
      	public String convertToDatabaseColumn(String attribute) {
      		// TODO Auto-generated method stub
      		return null;  // 조회도 null이 될 수 있음
      	}
  • convertToEntityAttribute(String dbData): 조회 시 데이터를 엔티티 자료형에 맞게 컨버팅하는 메소드. 조회된 레코드가 파라미터로 들어옴
    • ⚠️주의: 로직 코드 실행 전 레코드 파라미터 null 체크해야 함. null일 경우 오류남
    • SimpleDateFormat dbFormat = new SimpleDateFormat("yyyyMMddHHmmSSSS"): 조회된 데이터의 포맷
    • date = dbFormat.parse(dbData): 조회된 데이터의 포맷에 맞춰 date 자료형으로 변환
    • SimpleDateFormat entityFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"): 원하는 데이터 포맷
    • entityFormat.format(date): date 타입이 된 데이터를 원하는 포맷으로 변환

- datetime to String

예시) datetime 타입으로 저장되고 있는 데이터를 ‘YYYY/MM/DD HH:mm:ss’ 형식의 String으로 포맷팅하여 조회하고 싶을 경우

  1. 컬럼 설정
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

// 컨버팅 클래스
import com.armton.user.util.DateToStringConverter;

@Entity
@Setter
@Getter
@Table(name = "user")
@ToString
@NoArgsConstructor
public class User {
	
	@Id
	@Column
	private String id;
	
	@Column(name = "last_login_dt")
	@Convert(converter=DateToStringConverter.class)
	private String lastLoginDt; 
	    
}
  1. 컨버팅 클래스 생성
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class DateToStringConverter implements AttributeConverter<String, String>{

	private static final Logger logger = LoggerFactory.getLogger(DateToStringConverter.class);    // logger
	
	@Override
	public String convertToDatabaseColumn(String attribute) {
		return attribute;
	}

  @Override
	public String convertToEntityAttribute(String dbData) {
		StringBuilder sb = new StringBuilder();
		if(dbData!=null) {
			SimpleDateFormat dbFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:SSSS");
			Date date = null;
			try {
				date = dbFormat.parse(dbData);
				SimpleDateFormat entityFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				sb.append(entityFormat.format(date));
			} catch (ParseException e) {
				e.printStackTrace();
				logger.error("Error Occured during convert \"_dt\" value to entity attribute format.");
			}
			return sb.toString();
		}
		return dbData;
	}

}
  • AttributeConverter를 구현한 클래스를 생성한다.
    • AttributeConverter<엔티티 컬럼 타입, 데이터베이스 컬럼 타입>
    • DB 컬럼 타입은 datetime이었는데 String으로 받아도 무방하네..
  • convertToDatabaseColumn(String attribute): 만약 insertable=true이거나 updatable=true일 경우 데이터를 DB 타입에 맞게 컨버팅하는 메소드
    • ⚠️주의: insertable=false, updatable=false의 경우에도 무조건 null이 아닌 파라미터를 리턴해야 함. 데이터 조작 없이 조회만 한다고 이 메소드를 기본 override된 상태(return null)로 사용할 경우 조회 결과가 null 일 수 있음.
    • 잘못된 코드
      @Override	// 엔티티 -> DB 시
      	public String convertToDatabaseColumn(String attribute) {
      		// TODO Auto-generated method stub
      		return null;  // 조회도 null이 될 수 있음
      	}
  • convertToEntityAttribute(String dbData): 조회 시 데이터를 엔티티 자료형에 맞게 컨버팅하는 메소드. 조회된 레코드가 파라미터로 들어옴
    • ⚠️주의: 로직 코드 실행 전 레코드 파라미터 null 체크해야 함. null일 경우 오류남

- JSON 타입 포맷

예시) varchar, clob 등의 자료형을 JSON 형식으로 포맷팅하여 조회하고 싶을 경우

  1. 컬럼 설정
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import org.h2.util.json.JSONObject;

// 컨버팅 클래스
import com.armton.history.util.StringToFormatDateStringConverter;
import com.armton.history.util.StringToJson;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Entity
@Setter
@Getter
@Table(name = "service_history")
@ToString
@NoArgsConstructor
public class ServiceHistory {

	@Id
	@Column
	private String id;
	
  @Column(name = "res_data")
	@Convert(converter=StringToJson.class)
	private String resData;
		
}
  • 변환하고 싶은 필드에 @Convert(converter={컨버트 클래스}) 어노테이션을 붙인다.
  1. 컨버팅 클래스 생성
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

@Converter
public class StringToJson implements AttributeConverter<String, String>{
	
	private static final Logger logger = LoggerFactory.getLogger(StringToJson.class);

	@Override
	public String convertToDatabaseColumn(String attribute) {
		return attribute;
	}

	@Override
	public String convertToEntityAttribute(String dbData) {   // dbData = “{\"name\" : \“armton\”,\"age\" : 55,\"address\" : \“\”,\"tel\" : \"010-8888-9999\”}”
		if(dbData!=null) {
			ObjectMapper om = new ObjectMapper();
			JsonNode requestResult = null;
			try {
				requestResult = om.readTree(dbData);
			} catch (JsonProcessingException e) {
				logger.error("Error Occured during convert \"res_data\" value to entity attribute format(JSON).");
				e.printStackTrace();
			}
			return requestResult.toPrettyString();
		}else {
			return null;
		}
	}

	
}
  • AttributeConverter를 구현한 클래스를 생성한다.
    • AttributeConverter<엔티티 컬럼 타입, 데이터베이스 컬럼 타입>
  • convertToDatabaseColumn(String attribute): 만약 insertable=true이거나 updatable=true일 경우 데이터를 DB 타입에 맞게 컨버팅하는 메소드
    • ⚠️주의: insertable=false, updatable=false의 경우에도 무조건 null이 아닌 파라미터를 리턴해야 함. 데이터 조작 없이 조회만 한다고 이 메소드를 기본 override된 상태(return null)로 사용할 경우 조회 결과가 null 일 수 있음.
    • 잘못된 코드
      @Override	// 엔티티 -> DB 시
      	public String convertToDatabaseColumn(String attribute) {
      		// TODO Auto-generated method stub
      		return null;  // 단순 조회도 null이 될 수 있음
      	}
  • convertToEntityAttribute(String dbData): 조회 시 데이터를 엔티티 자료형에 맞게 컨버팅하는 메소드. 조회된 레코드가 파라미터로 들어옴
    • ⚠️주의: 로직 코드 실행 전 레코드 파라미터 null 체크해야 함. null일 경우 오류남
profile
armton garnet

0개의 댓글