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; 023import javax.sql.DataSource; 024 025import org.springframework.dao.DataAccessException; 026import org.springframework.dao.DataAccessResourceFailureException; 027import org.springframework.jdbc.datasource.DataSourceUtils; 028import org.springframework.jdbc.support.JdbcUtils; 029 030/** 031 * Abstract base class for {@link DataFieldMaxValueIncrementer} implementations that use 032 * a database sequence. Subclasses need to provide the database-specific SQL to use. 033 * 034 * @author Juergen Hoeller 035 * @since 26.02.2004 036 * @see #getSequenceQuery 037 */ 038public abstract class AbstractSequenceMaxValueIncrementer extends AbstractDataFieldMaxValueIncrementer { 039 040 /** 041 * Default constructor for bean property style usage. 042 * @see #setDataSource 043 * @see #setIncrementerName 044 */ 045 public AbstractSequenceMaxValueIncrementer() { 046 } 047 048 /** 049 * Convenience constructor. 050 * @param dataSource the DataSource to use 051 * @param incrementerName the name of the sequence/table to use 052 */ 053 public AbstractSequenceMaxValueIncrementer(DataSource dataSource, String incrementerName) { 054 super(dataSource, incrementerName); 055 } 056 057 058 /** 059 * Executes the SQL as specified by {@link #getSequenceQuery()}. 060 */ 061 @Override 062 protected long getNextKey() throws DataAccessException { 063 Connection con = DataSourceUtils.getConnection(getDataSource()); 064 Statement stmt = null; 065 ResultSet rs = null; 066 try { 067 stmt = con.createStatement(); 068 DataSourceUtils.applyTransactionTimeout(stmt, getDataSource()); 069 rs = stmt.executeQuery(getSequenceQuery()); 070 if (rs.next()) { 071 return rs.getLong(1); 072 } 073 else { 074 throw new DataAccessResourceFailureException("Sequence query did not return a result"); 075 } 076 } 077 catch (SQLException ex) { 078 throw new DataAccessResourceFailureException("Could not obtain sequence value", ex); 079 } 080 finally { 081 JdbcUtils.closeResultSet(rs); 082 JdbcUtils.closeStatement(stmt); 083 DataSourceUtils.releaseConnection(con, getDataSource()); 084 } 085 } 086 087 /** 088 * Return the database-specific query to use for retrieving a sequence value. 089 * <p>The provided SQL is supposed to result in a single row with a single 090 * column that allows for extracting a {@code long} value. 091 */ 092 protected abstract String getSequenceQuery(); 093 094}