View Javadoc
1   /*
2    * Copyright 2002-2012 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.orm.hibernate3.support;
18  
19  import java.io.IOException;
20  import java.io.Serializable;
21  import java.sql.PreparedStatement;
22  import java.sql.ResultSet;
23  import java.sql.SQLException;
24  import javax.transaction.TransactionManager;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  import org.hibernate.HibernateException;
29  import org.hibernate.usertype.UserType;
30  import org.hibernate.util.EqualsHelper;
31  
32  import org.springframework.jdbc.support.lob.LobCreator;
33  import org.springframework.jdbc.support.lob.LobCreatorUtils;
34  import org.springframework.jdbc.support.lob.LobHandler;
35  import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
36  
37  /**
38   * Abstract base class for Hibernate UserType implementations that map to LOBs.
39   * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
40   *
41   * <p>For writing LOBs, either an active Spring transaction synchronization
42   * or an active JTA transaction (with "jtaTransactionManager" specified on
43   * LocalSessionFactoryBean or a Hibernate TransactionManagerLookup configured
44   * through the corresponding Hibernate property) is required.
45   *
46   * <p>Offers template methods for setting parameters and getting result values,
47   * passing in the LobHandler or LobCreator to use.
48   *
49   * @author Juergen Hoeller
50   * @since 1.2
51   * @see org.springframework.jdbc.support.lob.LobHandler
52   * @see org.springframework.jdbc.support.lob.LobCreator
53   * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler
54   * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setJtaTransactionManager
55   */
56  public abstract class AbstractLobType implements UserType {
57  
58  	protected final Log logger = LogFactory.getLog(getClass());
59  
60  	private final LobHandler lobHandler;
61  
62  	private final TransactionManager jtaTransactionManager;
63  
64  
65  	/**
66  	 * Constructor used by Hibernate: fetches config-time LobHandler and
67  	 * config-time JTA TransactionManager from LocalSessionFactoryBean.
68  	 * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler
69  	 * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager
70  	 */
71  	protected AbstractLobType() {
72  		this(LocalSessionFactoryBean.getConfigTimeLobHandler(),
73  			LocalSessionFactoryBean.getConfigTimeTransactionManager());
74  	}
75  
76  	/**
77  	 * Constructor used for testing: takes an explicit LobHandler
78  	 * and an explicit JTA TransactionManager (can be {@code null}).
79  	 */
80  	protected AbstractLobType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
81  		this.lobHandler = lobHandler;
82  		this.jtaTransactionManager = jtaTransactionManager;
83  	}
84  
85  
86  	/**
87  	 * This implementation returns false.
88  	 */
89  	@Override
90  	public boolean isMutable() {
91  		return false;
92  	}
93  
94  	/**
95  	 * This implementation delegates to the Hibernate EqualsHelper.
96  	 * @see org.hibernate.util.EqualsHelper#equals
97  	 */
98  	@Override
99  	public boolean equals(Object x, Object y) throws HibernateException {
100 		return EqualsHelper.equals(x, y);
101 	}
102 
103 	/**
104 	 * This implementation returns the hashCode of the given objectz.
105 	 */
106 	@Override
107 	public int hashCode(Object x) throws HibernateException {
108 		return x.hashCode();
109 	}
110 
111 	/**
112 	 * This implementation returns the passed-in value as-is.
113 	 */
114 	@Override
115 	public Object deepCopy(Object value) throws HibernateException {
116 		return value;
117 	}
118 
119 	/**
120 	 * This implementation returns the passed-in value as-is.
121 	 */
122 	@Override
123 	public Serializable disassemble(Object value) throws HibernateException {
124 		return (Serializable) value;
125 	}
126 
127 	/**
128 	 * This implementation returns the passed-in value as-is.
129 	 */
130 	@Override
131 	public Object assemble(Serializable cached, Object owner) throws HibernateException {
132 		return cached;
133 	}
134 
135 	/**
136 	 * This implementation returns the passed-in original as-is.
137 	 */
138 	@Override
139 	public Object replace(Object original, Object target, Object owner) throws HibernateException {
140 		return original;
141 	}
142 
143 
144 	/**
145 	 * This implementation delegates to nullSafeGetInternal,
146 	 * passing in the LobHandler of this type.
147 	 * @see #nullSafeGetInternal
148 	 */
149 	@Override
150 	@Deprecated
151 	public final Object nullSafeGet(ResultSet rs, String[] names, Object owner)
152 			throws HibernateException, SQLException {
153 
154 		if (this.lobHandler == null) {
155 			throw new IllegalStateException("No LobHandler found for configuration - " +
156 				"lobHandler property must be set on LocalSessionFactoryBean");
157 		}
158 
159 		try {
160 			return nullSafeGetInternal(rs, names, owner, this.lobHandler);
161 		}
162 		catch (IOException ex) {
163 			throw new HibernateException("I/O errors during LOB access", ex);
164 		}
165 	}
166 
167 	/**
168 	 * This implementation delegates to nullSafeSetInternal,
169 	 * passing in a transaction-synchronized LobCreator for the
170 	 * LobHandler of this type.
171 	 * @see #nullSafeSetInternal
172 	 */
173 	@Override
174 	@Deprecated
175 	public final void nullSafeSet(PreparedStatement st, Object value, int index)
176 			throws HibernateException, SQLException {
177 
178 		if (this.lobHandler == null) {
179 			throw new IllegalStateException("No LobHandler found for configuration - " +
180 				"lobHandler property must be set on LocalSessionFactoryBean");
181 		}
182 
183 		LobCreator lobCreator = this.lobHandler.getLobCreator();
184 		try {
185 			nullSafeSetInternal(st, index, value, lobCreator);
186 		}
187 		catch (IOException ex) {
188 			throw new HibernateException("I/O errors during LOB access", ex);
189 		}
190 		LobCreatorUtils.registerTransactionSynchronization(lobCreator, this.jtaTransactionManager);
191 	}
192 
193 	/**
194 	 * Template method to extract a value from the given result set.
195 	 * @param rs the ResultSet to extract from
196 	 * @param names the column names
197 	 * @param owner the containing entity
198 	 * @param lobHandler the LobHandler to use
199 	 * @return the extracted value
200 	 * @throws SQLException if thrown by JDBC methods
201 	 * @throws IOException if thrown by streaming methods
202 	 * @throws HibernateException in case of any other exceptions
203 	 */
204 	protected abstract Object nullSafeGetInternal(
205 			ResultSet rs, String[] names, Object owner, LobHandler lobHandler)
206 			throws SQLException, IOException, HibernateException;
207 
208 	/**
209 	 * Template method to set the given parameter value on the given statement.
210 	 * @param ps the PreparedStatement to set on
211 	 * @param index the statement parameter index
212 	 * @param value the value to set
213 	 * @param lobCreator the LobCreator to use
214 	 * @throws SQLException if thrown by JDBC methods
215 	 * @throws IOException if thrown by streaming methods
216 	 * @throws HibernateException in case of any other exceptions
217 	 */
218 	protected abstract void nullSafeSetInternal(
219 		PreparedStatement ps, int index, Object value, LobCreator lobCreator)
220 			throws SQLException, IOException, HibernateException;
221 
222 }