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.orm.hibernate3.support;
018
019import java.io.IOException;
020import java.io.Serializable;
021import java.sql.PreparedStatement;
022import java.sql.ResultSet;
023import java.sql.SQLException;
024import javax.transaction.TransactionManager;
025
026import org.apache.commons.logging.Log;
027import org.apache.commons.logging.LogFactory;
028import org.hibernate.HibernateException;
029import org.hibernate.usertype.UserType;
030import org.hibernate.util.EqualsHelper;
031
032import org.springframework.jdbc.support.lob.LobCreator;
033import org.springframework.jdbc.support.lob.LobCreatorUtils;
034import org.springframework.jdbc.support.lob.LobHandler;
035
036/**
037 * Abstract base class for Hibernate UserType implementations that map to LOBs.
038 * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
039 *
040 * <p>For writing LOBs, either an active Spring transaction synchronization
041 * or an active JTA transaction (with "jtaTransactionManager" specified on
042 * LocalSessionFactoryBean or a Hibernate TransactionManagerLookup configured
043 * through the corresponding Hibernate property) is required.
044 *
045 * <p>Offers template methods for setting parameters and getting result values,
046 * passing in the LobHandler or LobCreator to use.
047 *
048 * @author Juergen Hoeller
049 * @since 1.2
050 * @see org.springframework.jdbc.support.lob.LobHandler
051 * @see org.springframework.jdbc.support.lob.LobCreator
052 * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
053 * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setJtaTransactionManager
054 * @deprecated as of Spring 4.3, in favor of Hibernate 4.x/5.x
055 */
056@Deprecated
057public abstract class AbstractLobType implements UserType {
058
059        protected final Log logger = LogFactory.getLog(getClass());
060
061        private final LobHandler lobHandler;
062
063        private final TransactionManager jtaTransactionManager;
064
065
066        /**
067         * Constructor used by Hibernate: fetches config-time LobHandler and
068         * config-time JTA TransactionManager from LocalSessionFactoryBean.
069         * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
070         * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
071         */
072        protected AbstractLobType() {
073                this(org.springframework.orm.hibernate3.LocalSessionFactoryBean.getConfigTimeLobHandler(),
074                                org.springframework.orm.hibernate3.LocalSessionFactoryBean.getConfigTimeTransactionManager());
075        }
076
077        /**
078         * Constructor used for testing: takes an explicit LobHandler
079         * and an explicit JTA TransactionManager (can be {@code null}).
080         */
081        protected AbstractLobType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
082                this.lobHandler = lobHandler;
083                this.jtaTransactionManager = jtaTransactionManager;
084        }
085
086
087        /**
088         * This implementation returns false.
089         */
090        @Override
091        public boolean isMutable() {
092                return false;
093        }
094
095        /**
096         * This implementation delegates to the Hibernate EqualsHelper.
097         * @see org.hibernate.util.EqualsHelper#equals
098         */
099        @Override
100        public boolean equals(Object x, Object y) throws HibernateException {
101                return EqualsHelper.equals(x, y);
102        }
103
104        /**
105         * This implementation returns the hashCode of the given objectz.
106         */
107        @Override
108        public int hashCode(Object x) throws HibernateException {
109                return x.hashCode();
110        }
111
112        /**
113         * This implementation returns the passed-in value as-is.
114         */
115        @Override
116        public Object deepCopy(Object value) throws HibernateException {
117                return value;
118        }
119
120        /**
121         * This implementation returns the passed-in value as-is.
122         */
123        @Override
124        public Serializable disassemble(Object value) throws HibernateException {
125                return (Serializable) value;
126        }
127
128        /**
129         * This implementation returns the passed-in value as-is.
130         */
131        @Override
132        public Object assemble(Serializable cached, Object owner) throws HibernateException {
133                return cached;
134        }
135
136        /**
137         * This implementation returns the passed-in original as-is.
138         */
139        @Override
140        public Object replace(Object original, Object target, Object owner) throws HibernateException {
141                return original;
142        }
143
144
145        /**
146         * This implementation delegates to nullSafeGetInternal,
147         * passing in the LobHandler of this type.
148         * @see #nullSafeGetInternal
149         */
150        @Override
151        @Deprecated
152        public final Object nullSafeGet(ResultSet rs, String[] names, Object owner)
153                        throws HibernateException, SQLException {
154
155                if (this.lobHandler == null) {
156                        throw new IllegalStateException("No LobHandler found for configuration - " +
157                                "lobHandler property must be set on LocalSessionFactoryBean");
158                }
159
160                try {
161                        return nullSafeGetInternal(rs, names, owner, this.lobHandler);
162                }
163                catch (IOException ex) {
164                        throw new HibernateException("I/O errors during LOB access", ex);
165                }
166        }
167
168        /**
169         * This implementation delegates to nullSafeSetInternal,
170         * passing in a transaction-synchronized LobCreator for the
171         * LobHandler of this type.
172         * @see #nullSafeSetInternal
173         */
174        @Override
175        @Deprecated
176        public final void nullSafeSet(PreparedStatement st, Object value, int index)
177                        throws HibernateException, SQLException {
178
179                if (this.lobHandler == null) {
180                        throw new IllegalStateException("No LobHandler found for configuration - " +
181                                "lobHandler property must be set on LocalSessionFactoryBean");
182                }
183
184                LobCreator lobCreator = this.lobHandler.getLobCreator();
185                try {
186                        nullSafeSetInternal(st, index, value, lobCreator);
187                }
188                catch (IOException ex) {
189                        throw new HibernateException("I/O errors during LOB access", ex);
190                }
191                LobCreatorUtils.registerTransactionSynchronization(lobCreator, this.jtaTransactionManager);
192        }
193
194        /**
195         * Template method to extract a value from the given result set.
196         * @param rs the ResultSet to extract from
197         * @param names the column names
198         * @param owner the containing entity
199         * @param lobHandler the LobHandler to use
200         * @return the extracted value
201         * @throws SQLException if thrown by JDBC methods
202         * @throws IOException if thrown by streaming methods
203         * @throws HibernateException in case of any other exceptions
204         */
205        protected abstract Object nullSafeGetInternal(
206                        ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
207                        throws SQLException, IOException, HibernateException;
208
209        /**
210         * Template method to set the given parameter value on the given statement.
211         * @param ps the PreparedStatement to set on
212         * @param index the statement parameter index
213         * @param value the value to set
214         * @param lobCreator the LobCreator to use
215         * @throws SQLException if thrown by JDBC methods
216         * @throws IOException if thrown by streaming methods
217         * @throws HibernateException in case of any other exceptions
218         */
219        protected abstract void nullSafeSetInternal(
220                PreparedStatement ps, int index, Object value, LobCreator lobCreator)
221                        throws SQLException, IOException, HibernateException;
222
223}