001/* 002 * Copyright 2002-2018 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.core.support; 018 019import java.sql.Connection; 020 021import javax.sql.DataSource; 022 023import org.springframework.dao.support.DaoSupport; 024import org.springframework.jdbc.CannotGetJdbcConnectionException; 025import org.springframework.jdbc.core.JdbcTemplate; 026import org.springframework.jdbc.datasource.DataSourceUtils; 027import org.springframework.jdbc.support.SQLExceptionTranslator; 028import org.springframework.lang.Nullable; 029import org.springframework.util.Assert; 030 031/** 032 * Convenient super class for JDBC-based data access objects. 033 * 034 * <p>Requires a {@link javax.sql.DataSource} to be set, providing a 035 * {@link org.springframework.jdbc.core.JdbcTemplate} based on it to 036 * subclasses through the {@link #getJdbcTemplate()} method. 037 * 038 * <p>This base class is mainly intended for JdbcTemplate usage but can 039 * also be used when working with a Connection directly or when using 040 * {@code org.springframework.jdbc.object} operation objects. 041 * 042 * @author Juergen Hoeller 043 * @since 28.07.2003 044 * @see #setDataSource 045 * @see #getJdbcTemplate 046 * @see org.springframework.jdbc.core.JdbcTemplate 047 */ 048public abstract class JdbcDaoSupport extends DaoSupport { 049 050 @Nullable 051 private JdbcTemplate jdbcTemplate; 052 053 054 /** 055 * Set the JDBC DataSource to be used by this DAO. 056 */ 057 public final void setDataSource(DataSource dataSource) { 058 if (this.jdbcTemplate == null || dataSource != this.jdbcTemplate.getDataSource()) { 059 this.jdbcTemplate = createJdbcTemplate(dataSource); 060 initTemplateConfig(); 061 } 062 } 063 064 /** 065 * Create a JdbcTemplate for the given DataSource. 066 * Only invoked if populating the DAO with a DataSource reference! 067 * <p>Can be overridden in subclasses to provide a JdbcTemplate instance 068 * with different configuration, or a custom JdbcTemplate subclass. 069 * @param dataSource the JDBC DataSource to create a JdbcTemplate for 070 * @return the new JdbcTemplate instance 071 * @see #setDataSource 072 */ 073 protected JdbcTemplate createJdbcTemplate(DataSource dataSource) { 074 return new JdbcTemplate(dataSource); 075 } 076 077 /** 078 * Return the JDBC DataSource used by this DAO. 079 */ 080 @Nullable 081 public final DataSource getDataSource() { 082 return (this.jdbcTemplate != null ? this.jdbcTemplate.getDataSource() : null); 083 } 084 085 /** 086 * Set the JdbcTemplate for this DAO explicitly, 087 * as an alternative to specifying a DataSource. 088 */ 089 public final void setJdbcTemplate(@Nullable JdbcTemplate jdbcTemplate) { 090 this.jdbcTemplate = jdbcTemplate; 091 initTemplateConfig(); 092 } 093 094 /** 095 * Return the JdbcTemplate for this DAO, 096 * pre-initialized with the DataSource or set explicitly. 097 */ 098 @Nullable 099 public final JdbcTemplate getJdbcTemplate() { 100 return this.jdbcTemplate; 101 } 102 103 /** 104 * Initialize the template-based configuration of this DAO. 105 * Called after a new JdbcTemplate has been set, either directly 106 * or through a DataSource. 107 * <p>This implementation is empty. Subclasses may override this 108 * to configure further objects based on the JdbcTemplate. 109 * @see #getJdbcTemplate() 110 */ 111 protected void initTemplateConfig() { 112 } 113 114 @Override 115 protected void checkDaoConfig() { 116 if (this.jdbcTemplate == null) { 117 throw new IllegalArgumentException("'dataSource' or 'jdbcTemplate' is required"); 118 } 119 } 120 121 122 /** 123 * Return the SQLExceptionTranslator of this DAO's JdbcTemplate, 124 * for translating SQLExceptions in custom JDBC access code. 125 * @see org.springframework.jdbc.core.JdbcTemplate#getExceptionTranslator() 126 */ 127 protected final SQLExceptionTranslator getExceptionTranslator() { 128 JdbcTemplate jdbcTemplate = getJdbcTemplate(); 129 Assert.state(jdbcTemplate != null, "No JdbcTemplate set"); 130 return jdbcTemplate.getExceptionTranslator(); 131 } 132 133 /** 134 * Get a JDBC Connection, either from the current transaction or a new one. 135 * @return the JDBC Connection 136 * @throws CannotGetJdbcConnectionException if the attempt to get a Connection failed 137 * @see org.springframework.jdbc.datasource.DataSourceUtils#getConnection(javax.sql.DataSource) 138 */ 139 protected final Connection getConnection() throws CannotGetJdbcConnectionException { 140 DataSource dataSource = getDataSource(); 141 Assert.state(dataSource != null, "No DataSource set"); 142 return DataSourceUtils.getConnection(dataSource); 143 } 144 145 /** 146 * Close the given JDBC Connection, created via this DAO's DataSource, 147 * if it isn't bound to the thread. 148 * @param con the Connection to close 149 * @see org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection 150 */ 151 protected final void releaseConnection(Connection con) { 152 DataSourceUtils.releaseConnection(con, getDataSource()); 153 } 154 155}