이전 포스팅에서 JPA Entity 설계 시, 각 테이블의 Primary key 값을 [구분 문자] + "_" + sequence 의 형태로 만드는 계획을 세웠다
하지만, sequence의 관리 (증감)을 서비스 단에서 조절하게 되면 제품 등록|
삭제|업데이트 등 다양한 요청을 동시에 (여러 thread)에서 받았을 때 seq가 꼬일 수 있기에, JPA의 custom sequence generator 를 사용하여 sequence가 자동 증가되도록 변경하였다 😺
이를 구현하기 위해 CustomSequenceGenerator를 생성했다 :) 또한, Product 등록 뿐만 아니라 Category 등록 API도 생성하였다.
prefix
라는 parameter로 보내주는 값을 읽은 뒤, 이를 "_"를 구분자로 split한 뒤, db에서 해당 entity의 next seq와 합치는 작업을 수행public class CustomSequenceGenerator extends SequenceStyleGenerator {
private String prefix = "_";
private int incrementSize = 1;
@Override
public Serializable generate(
SharedSessionContractImplementor session,
Object object) throws HibernateException {
String sequenceName = prefix + "seq";
Connection connection = null;
try {
ConnectionProvider connectionProvider = session
.getFactory()
.getServiceRegistry()
.getService(ConnectionProvider.class);
connection = connectionProvider.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(
"SELECT nextval('" + sequenceName + "')");
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
int nextValue = resultSet.getInt(1);
String generatedId = (prefix.contains("_") ? prefix.split("_")[0] : "") + "_" + nextValue;
return generatedId;
}
} catch (SQLException e) {
throw new HibernateException("Unable to generate sequence", e);
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
log.debug("Unexpected error occurs while closing the connection");
}
}
}
return null;
}
@Override
public void configure(
Type type,
Properties params,
ServiceRegistry serviceRegistry) {
super.configure(type, params, serviceRegistry);
String parameterPrefix = params.getProperty("prefix");
if (parameterPrefix != null) {
prefix = parameterPrefix;
}
String incrementSizeParam = params.getProperty("increment_size");
if (incrementSizeParam != null) {
incrementSize = Integer.parseInt(incrementSizeParam);
}
}
}
@Parameter(name = "prefix", value = "category_code_")
해당 부분을 통해 CustomSequenceGenerator에 prefix 문자 값을 전달@Parameter(name = "increment_size", value = "1")
해당 부분을 통해 seq가 1씩 증가되도록 설정@Table(name = "category")
public class Category {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "category_code_seq")
@GenericGenerator(name = "category_code_seq", strategy = "com.madeg.logistics.entity.CustomSequenceGenerator", parameters = {
@Parameter(name = "prefix", value = "category_code_"), @Parameter(name = "increment_size", value = "1") })
@Column(name = "category_code", unique = true, nullable = false)
private String categoryCode;
@ManyToOne
@JoinColumn(name = "parent_category_code", referencedColumnName = "category_code")
private Category parentCategory;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "description")
private String description;
카테고리 등록 API 요청
DB Insert
카테코리 등록 API 요청
DB
category 테이블은 category_code가 parent_category_code를 바라보고 있는 자기 참조 구조이다. 이를 Category 등록 요청을 통해 확인해 보았다
입력한 부모 카테고리 코드가 category 테이블에 존재하지 않을 경우, 카테고리 자체가 등록되지 않음을 확인할 수 있었다!
이전 포스팅에서 정리한 개선이 필요한 사항
중 custom sequence generator에 관련한 내용을 수정하였다. 남은 개선 사항들도 하나씩 수정해 나아갈 계획이다 🖊️🖊️
잘봤습니다만 ㅎ, 화면은 없나요?