/* * Copyright 2008-2009 MOPAS(Ministry of Public Administration and Security). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package egovframework.rte.fdl.idgnr.impl; import java.math.BigDecimal; import java.util.Locale; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import egovframework.rte.fdl.cmmn.exception.FdlException; /** * ID Generation 서비스를 위한 Table 구현 클래스 * <p> * <b>NOTE</b>: 채번 테이블을 정의하고, 각 관리대상에 대한 현재 최종 Max 번호를 * 관리하여 Table 기반의 유일키를 제공 받을 수 있다. * * <pre> * 필요한 테이블 생성 스크립트 * CREATE TABLE ids ( * table_name varchar(16) NOT NULL, * next_id INTEGER NOT NULL, * PRIMARY KEY (table_name) * ); * </pre> * @author 실행환경 개발팀 김태호 * @since 2009.02.01 * @version 1.0 * @see <pre> * == 개정이력(Modification Information) == * * 수정일 수정자 수정내용 * ------- -------- --------------------------- * 2009.02.01 김태호 최초 생성 * 2013.03.25 한성곤 필드명 속성 처리, JdbcTemplate 방식으로 변경, 초기 id 값 등록(자동 insert 처리), 반복처리 제외 * * </pre> */ public class EgovTableIdGnrService extends AbstractDataBlockIdGnrService { /** * ID생성을 위한 테이블 정보 디폴트는 ids임. */ private String table = "ids"; /** * 테이블 정보에 기록되는 대상 키정보 대개의 경우는 아이디로 생성되는 테이블명을 기재함 */ private String tableName = "id"; /** * 테이블명(구분값)에 대한 테이블 필드명 지정 */ private String tableNameFieldName = "table_name"; /** * Next Id 정보를 보관하는 필드명 지정 */ private String nextIdFieldName = "next_id"; /** * Jdbc template */ private JdbcTemplate jdbcTemplate; /** * 생성자 */ public EgovTableIdGnrService() { } @Override public void setDataSource(DataSource dataSource) { super.setDataSource(dataSource); this.jdbcTemplate = new JdbcTemplate(dataSource); } /** * tableName에 대한 초기 값이 없는 경우 초기 id 값 등록 (blockSize 처리) * * @param useBigDecimals * @param initId */ private Object insertInitId(boolean useBigDecimals, int blockSize) { if (getLogger().isDebugEnabled()) { getLogger().debug( messageSource.getMessage("debug.idgnr.init.idblock", new Object[] { tableName }, Locale.getDefault())); } Object initId = null; String insertQuery = "INSERT INTO " + table + "(" + tableNameFieldName + ", " + nextIdFieldName + ") " + "values('" + tableName + "', ?)"; if (getLogger().isDebugEnabled()) { getLogger().debug("Insert Query : " + insertQuery); } if (useBigDecimals) { initId = new BigDecimal(blockSize); } else { initId = new Long(blockSize); } jdbcTemplate.update(insertQuery, initId); return initId; } /** * blockSize 대로 ID 지정 * * @param blockSize 지정되는 blockSize * @param useBigDecimals BigDecimal 사용 여부 * @return BigDecimal을 사용하면 BigDecimal 아니면 long 리턴 * @throws FdlException ID생성을 위한 블럭 할당이 불가능할때 */ private Object allocateIdBlock(int blockSize, boolean useBigDecimals) throws FdlException { if (getLogger().isDebugEnabled()) { getLogger().debug( messageSource.getMessage("debug.idgnr.allocate.idblock", new Object[] { new Integer(blockSize), tableName }, Locale.getDefault())); } Object nextId; Object newNextId; try { String selectQuery = "SELECT " + nextIdFieldName + " FROM " + table + " WHERE " + tableNameFieldName + " = ?"; if (getLogger().isDebugEnabled()) { getLogger().debug("Select Query : " + selectQuery); } if (useBigDecimals) { try { nextId = jdbcTemplate.queryForObject(selectQuery, new Object[] { tableName }, BigDecimal.class); } catch (EmptyResultDataAccessException erdae) { nextId = null; } if (nextId == null) { // no row insertInitId(useBigDecimals, blockSize); return new BigDecimal(0); } } else { try { nextId = jdbcTemplate.queryForLong(selectQuery, tableName); } catch (EmptyResultDataAccessException erdae) { nextId = -1L; } if ((Long)nextId == -1L) { // no row insertInitId(useBigDecimals, blockSize); return new Long(0); } } } catch (DataAccessException dae) { dae.printStackTrace(); if (getLogger().isDebugEnabled()) { getLogger().debug("", dae); } throw new FdlException(messageSource, "error.idgnr.select.idblock", new String[] { tableName }, null); } try { String updateQuery = "UPDATE " + table + " SET " + nextIdFieldName + " = ?" + " WHERE " + tableNameFieldName + " = ?"; if (getLogger().isDebugEnabled()) { getLogger().debug("Update Query : " + updateQuery); } if (useBigDecimals) { newNextId = ((BigDecimal) nextId).add(new BigDecimal(blockSize)); } else { newNextId = new Long(((Long) nextId).longValue() + blockSize); } jdbcTemplate.update(updateQuery, newNextId, tableName); return nextId; } catch (DataAccessException dae) { throw new FdlException(messageSource, "error.idgnr.update.idblockk", new String[] { tableName }, null); } } /** * blockSize 대로 ID 지정(BigDecimal) * * @param blockSize 지정되는 blockSize * @return 할당된 블럭의 첫번째 아이디 * @throws FdlException ID생성을 위한 블럭 할당이 불가능할때 */ protected BigDecimal allocateBigDecimalIdBlock(int blockSize) throws FdlException { return (BigDecimal) allocateIdBlock(blockSize, true); } /** * blockSize 대로 ID 지정(long) * * @param blockSize 지정되는 blockSize * @return 할당된 블럭의 첫번째 아이디 * @throws FdlException ID생성을 위한 블럭 할당이 불가능할때 */ protected long allocateLongIdBlock(int blockSize) throws FdlException { Long id = (Long) allocateIdBlock(blockSize, false); return id.longValue(); } /** * ID생성을 위한 테이블 정보 Injection * * @param table config로 지정되는 정보 */ public void setTable(String table) { this.table = table; } /** * ID 생성을 위한 테이블의 키정보 ( 대개의경우는 대상 테이블명을 기재함 ) * * @param tableName config로 지정되는 정보 */ public void setTableName(String tableName) { this.tableName = tableName; } /** * 테이블명(구분값)에 대한 테이블 필드명 정보 지정 * * @param tableNameFieldName */ public void setTableNameFieldName(String tableNameFieldName) { this.tableNameFieldName = tableNameFieldName; } /** * Next Id 정보를 보관하는 필드명 정보 지정 * * @param nextIdFieldName */ public void setNextIdFieldName(String nextIdFieldName) { this.nextIdFieldName = nextIdFieldName; } }