model에 enum type을 넣고
mybatis에서 아래 테이블의 data를 받아오려고 한다.

enum은 여러 형태를 가질 수 있다.
아래와 같이 그냥 단건의 데이터만 지정하여 만드는 경우가 있을 수 있고
package com.shlee.toy1.repository.product.type; | |
public enum ProductType { | |
NORMAL, TOY, FOOD | |
} |
db에 쌓이는 데이터유형이 숫자( 1_VERSION, 2_VERSION )나
특수문자로 시작할 경우 enum을 아래와 같이 인자를 2개씩 갖게 지정될 수 있다.
package com.shlee.toy1.repository.product.type; | |
public enum ProductVersionType { | |
VERSION1("1_VERSION", "VAL1"), | |
VERSION2("2_VERSION", "VAL2"); | |
public String code; | |
public String value; | |
private ProductVersionType(String code, String value) { | |
this.code = code; | |
this.value = value; | |
} | |
public String getCode() { | |
return code; | |
} | |
public String getValue() { | |
return value; | |
} | |
public static ProductVersionType get(String code) { | |
for (ProductVersionType element : values()) { | |
if (element.code.equalsIgnoreCase(code)) { | |
return element; | |
} | |
} | |
return null; | |
} | |
public static ProductVersionType lookup(String code) { | |
for (ProductVersionType element : ProductVersionType.values()) { | |
if (element.code.equalsIgnoreCase(code)) { | |
return element; | |
} | |
} | |
return null; | |
} | |
} |
그럴경우 여러 형태의 enum 데이터를 바인딩 하지 못해
아래와 같은 오류가 발생 할 수 있다.

Caused by: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column '' from result set.
Caused by: java.lang.IllegalArgumentException: No enum constant
package com.shlee.toy1.repository.product.entity; | |
import com.shlee.toy1.repository.product.type.ProductType; | |
import com.shlee.toy1.repository.product.type.ProductVersionType; | |
import lombok.Data; | |
import java.io.Serializable; | |
@Data | |
public class ProductEntity implements Serializable { | |
private static final long serialVersionUID = 5846732176522273471L; | |
private String productId; | |
private String productName; | |
private ProductType productType; | |
private ProductVersionType productVersionType; | |
} |
<?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="com.shlee.toy1.repository.product.ProductRepository"> | |
<select id="selectProductById" resultType="ProductEntity"> | |
SELECT product_id | |
, product_name | |
, product_type | |
, product_version_type | |
FROM test.products p | |
WHERE p.product_id = #{productId} | |
</select> | |
</mapper> |
package com.shlee.toy1.controller.product; | |
import com.shlee.toy1.common.message.MessageCode; | |
import com.shlee.toy1.common.message.response.ServiceCommonResponse; | |
import com.shlee.toy1.domain.product.service.ProductService; | |
import com.shlee.toy1.repository.product.entity.ProductEntity; | |
import io.swagger.annotations.Api; | |
import io.swagger.annotations.ApiOperation; | |
import io.swagger.annotations.ApiParam; | |
import lombok.extern.slf4j.Slf4j; | |
import org.springframework.http.HttpStatus; | |
import org.springframework.http.ResponseEntity; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.PathVariable; | |
import org.springframework.web.bind.annotation.RequestMapping; | |
import org.springframework.web.bind.annotation.ResponseStatus; | |
import javax.servlet.http.HttpServletRequest; | |
import java.util.List; | |
@Controller | |
@Slf4j | |
@Api(tags = {"Product"}) | |
@RequestMapping("/v1/product") | |
public class ProductRestController { | |
public final ProductService productService; | |
public ProductRestController(ProductService productService) { | |
this.productService = productService; | |
} | |
@GetMapping("/{productId}") | |
@ApiOperation(value = "상품정보") | |
@ResponseStatus(HttpStatus.OK) | |
public ResponseEntity<ServiceCommonResponse> getProductInfo(HttpServletRequest request | |
, @ApiParam(value = "Product ID", required = true) @PathVariable("productId") Integer productId) { | |
List<ProductEntity> lists = null; | |
try{ | |
lists = productService.selectProductListsById(productId); | |
}catch (Exception e){ | |
return new ResponseEntity<>( | |
new ServiceCommonResponse(MessageCode.NOTE_FOUND, lists), HttpStatus.NOT_FOUND); | |
} | |
return new ResponseEntity<>( | |
new ServiceCommonResponse(MessageCode.SUCCESS, lists), HttpStatus.OK); | |
} | |
} |
위소스를 보면 상품정보 rest controller에서 service를 거쳐 mapper에 해당하는 쿼리결과를 lists 객체에
담겨야 하는데 데이터를 못받아와 catch절 NOT_FOUND로 빠져
swagger에서해당 data를 알지 못해 못받아오는 경우도 생긴다.

이럴경우 TypeHandler를 생성하여 해결할 수 있다.
package com.shlee.toy1.common.handler.type; | |
import com.shlee.toy1.repository.product.type.ProductVersionType; | |
import org.apache.ibatis.type.BaseTypeHandler; | |
import org.apache.ibatis.type.JdbcType; | |
import java.sql.CallableStatement; | |
import java.sql.PreparedStatement; | |
import java.sql.ResultSet; | |
import java.sql.SQLException; | |
public class ProductVersionTypeHandler extends BaseTypeHandler<ProductVersionType> { | |
@Override | |
public void setNonNullParameter(PreparedStatement ps, int i, ProductVersionType parameter, JdbcType jdbcType) throws SQLException { | |
ps.setString(i, parameter.getValue()); | |
} | |
@Override | |
public ProductVersionType getNullableResult(ResultSet rs, String columnName) throws SQLException { | |
return ProductVersionType.lookup(rs.getString(columnName)); | |
} | |
@Override | |
public ProductVersionType getNullableResult(ResultSet rs, int columnIndex) throws SQLException { | |
return ProductVersionType.valueOf(rs.getString(columnIndex)); | |
} | |
@Override | |
public ProductVersionType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { | |
return ProductVersionType.valueOf(cs.getString(columnIndex)); | |
} | |
} |
그리고 생성한 type handler 위치의 패키지명을 아래와 같이 지정해준다.
type-handlers-package: com.shlee.toy1.common.handler.type
mybatis: | |
type-aliases-package: com.shlee.toy1 | |
mapper-locations: classpath:mapper/*.xml,mapper/**/*.xml | |
configuration: | |
map-underscore-to-camel-case: true | |
aggressive-lazy-loading: false | |
lazy-loading-enabled: true | |
lazy-load-trigger-methods: '' | |
type-handlers-package: com.shlee.toy1.common.handler.type |
그리고 api를 조회해보면 아래와 같이 enum으로 정의한 키값으로 나온다.

이제 이 반환된 키 값으로 서비스 로직에서 데이터를 가공해서 반환해주면 된다.

이제 여러개의 enum type에 대응가능한 mybatis type handler에 대해 작성할 수 있게 되었다.
'전체 > Spring Boot' 카테고리의 다른 글
Could not autowire. No beans of type found. error 해결 (1) | 2021.02.14 |
---|---|
spring boot swagger 적용하기 (0) | 2021.02.14 |
Caused by: java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) 해결하기 (6) | 2021.02.14 |
Spring Boot JPA CRUD테스트 프로젝트 만들기 - 6 (0) | 2019.08.09 |
Spring Boot JPA 설정 프로젝트 만들기 - 5 (4) | 2019.07.28 |