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