package egovframework.com.idgen.impl; import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; // java.sql.PreparedStatement로 임포트 import java.sql.ResultSet; import java.sql.SQLException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.sql.DataSource; import org.springframework.jdbc.datasource.DataSourceUtils; import egovframework.com.idgen.CustomIdGnrService; import egovframework.rte.fdl.cmmn.exception.FdlException; import egovframework.rte.fdl.idgnr.EgovIdGnrStrategy; public class CustomTableIdGnrServiceImpl implements CustomIdGnrService { private long allocatedId; private long allocatedMaxId; private int blockSize = 10; // 기본값, 필요에 따라 변경 private DataSource dataSource; private String table; // 실제 테이블 이름 (예: IDS) private String tableName; // TABLE_NAME 컬럼에서 사용할 값 (예: MSG_ID) private String columnName = "NEXT_ID"; // NEXT_ID 컬럼명 private String prefix; private String fillChar = "0"; // 채울 문자 (예: 0) private int cipers = 14; // 자리수 (예: 14) private boolean applyYear; private boolean useBigDecimals = false; @Override public synchronized List getNextStringId(int count) throws FdlException { List idList = new ArrayList<>(count); try { for (int i = 0; i < count; i++) { if (allocatedId >= allocatedMaxId) { allocateIdBlock(count); } long id = allocatedId++; idList.add(createStringId(id)); } } catch (Exception e) { throw new FdlException("ID Generation Error", e); } return idList; } private void allocateIdBlock(int requiredCount) throws SQLException, FdlException { Connection conn = DataSourceUtils.getConnection(dataSource); try { conn.setAutoCommit(false); int newBlockSize = Math.max(this.blockSize, requiredCount); // SELECT 쿼리 수정 String query = "SELECT " + columnName + " FROM " + table + " WHERE TABLE_NAME = ? FOR UPDATE"; try (PreparedStatement stmt = conn.prepareStatement(query)) { stmt.setString(1, tableName); try (ResultSet rs = stmt.executeQuery()) { long oldId = 0; if (rs.next()) { oldId = rs.getLong(1); } else { throw new FdlException( "ID Generation Error: No record found in " + table + " for TABLE_NAME = " + tableName); } long newId = oldId + newBlockSize; // UPDATE 쿼리 수정 String update = "UPDATE " + table + " SET " + columnName + " = ? WHERE TABLE_NAME = ? AND " + columnName + " = ?"; try (PreparedStatement updateStmt = conn.prepareStatement(update)) { updateStmt.setLong(1, newId); updateStmt.setString(2, tableName); updateStmt.setLong(3, oldId); int row = updateStmt.executeUpdate(); if (row == 0) { throw new FdlException( "ID Generation Error: Failed to update ID. Possible concurrent modification."); } } conn.commit(); allocatedId = oldId; allocatedMaxId = newId; } } catch (SQLException e) { conn.rollback(); throw e; } } catch (SQLException e) { throw new FdlException("ID Generation Error", e); } finally { DataSourceUtils.releaseConnection(conn, dataSource); } } private String createStringId(long id) { StringBuilder sb = new StringBuilder(); if (prefix != null) { sb.append(prefix); } if (applyYear) { sb.append(new SimpleDateFormat("yyyy").format(new Date())); } String idStr = String.format("%0" + cipers + "d", id); sb.append(idStr); return sb.toString(); } // 인터페이스의 다른 메서드 구현 (필요에 따라 UnsupportedOperationException 또는 직접 구현) @Override public BigDecimal getNextBigDecimalId() throws FdlException { throw new UnsupportedOperationException("getNextBigDecimalId is not supported"); } @Override public long getNextLongId() throws FdlException { throw new UnsupportedOperationException("getNextLongId is not supported"); } @Override public int getNextIntegerId() throws FdlException { throw new UnsupportedOperationException("getNextIntegerId is not supported"); } @Override public short getNextShortId() throws FdlException { throw new UnsupportedOperationException("getNextShortId is not supported"); } @Override public byte getNextByteId() throws FdlException { throw new UnsupportedOperationException("getNextByteId is not supported"); } @Override public String getNextStringId() throws FdlException { throw new UnsupportedOperationException("getNextStringId is not supported"); } @Override public String getNextStringId(String strategyId) throws FdlException { throw new UnsupportedOperationException("getNextStringId(String strategyId) is not supported"); } @Override public String getNextStringId(EgovIdGnrStrategy strategy) throws FdlException { throw new UnsupportedOperationException("getNextStringId(EgovIdGnrStrategy strategy) is not supported"); } // 필요한 setter 메서드들 추가 public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public void setTable(String table) { this.table = table; } public void setTableName(String tableName) { this.tableName = tableName; } public void setColumnName(String columnName) { this.columnName = columnName; } public void setPrefix(String prefix) { this.prefix = prefix; } public void setFillChar(String fillChar) { this.fillChar = fillChar; } public void setCipers(int cipers) { this.cipers = cipers; } public void setApplyYear(boolean applyYear) { this.applyYear = applyYear; } public void setBlockSize(int blockSize) { this.blockSize = blockSize; } }