001/* 002 * Copyright 2002-2012 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jdbc.support.incrementer; 018 019import java.sql.Connection; 020import java.sql.ResultSet; 021import java.sql.SQLException; 022import java.sql.Statement; 023 024import javax.sql.DataSource; 025 026import org.springframework.dao.DataAccessException; 027import org.springframework.dao.DataAccessResourceFailureException; 028import org.springframework.jdbc.datasource.DataSourceUtils; 029import org.springframework.jdbc.support.JdbcUtils; 030 031/** 032 * Abstract base class for {@link DataFieldMaxValueIncrementer} implementations that use 033 * a database sequence. Subclasses need to provide the database-specific SQL to use. 034 * 035 * @author Juergen Hoeller 036 * @since 26.02.2004 037 * @see #getSequenceQuery 038 */ 039public abstract class AbstractSequenceMaxValueIncrementer extends AbstractDataFieldMaxValueIncrementer { 040 041 /** 042 * Default constructor for bean property style usage. 043 * @see #setDataSource 044 * @see #setIncrementerName 045 */ 046 public AbstractSequenceMaxValueIncrementer() { 047 } 048 049 /** 050 * Convenience constructor. 051 * @param dataSource the DataSource to use 052 * @param incrementerName the name of the sequence/table to use 053 */ 054 public AbstractSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) { 055 super(dataSource, incrementerName); 056 } 057 058 059 /** 060 * Executes the SQL as specified by {@link #getSequenceQuery()}. 061 */ 062 @Override 063 protected long getNextKey() throws DataAccessException { 064 Connection con = DataSourceUtils.getConnection(getDataSource()); 065 Statement stmt = null; 066 ResultSet rs = null; 067 try { 068 stmt = con.createStatement(); 069 DataSourceUtils.applyTransactionTimeout(stmt, getDataSource()); 070 rs = stmt.executeQuery(getSequenceQuery()); 071 if (rs.next()) { 072 return rs.getLong(1); 073 } 074 else { 075 throw new DataAccessResourceFailureException("Sequence query did not return a result"); 076 } 077 } 078 catch (SQLException ex) { 079 throw new DataAccessResourceFailureException("Could not obtain sequence value", ex); 080 } 081 finally { 082 JdbcUtils.closeResultSet(rs); 083 JdbcUtils.closeStatement(stmt); 084 DataSourceUtils.releaseConnection(con, getDataSource()); 085 } 086 } 087 088 /** 089 * Return the database-specific query to use for retrieving a sequence value. 090 * <p>The provided SQL is supposed to result in a single row with a single 091 * column that allows for extracting a {@code long} value. 092 */ 093 protected abstract String getSequenceQuery(); 094 095}