AbstractLobType.java
Upload User: jiancairen
Upload Date: 2007-08-27
Package Size: 26458k
Code Size: 9k
Category:

Java Develop

Development Platform:

Java

  1. /*
  2.  * Copyright 2002-2004 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. package org.springframework.orm.hibernate.support;
  17. import java.io.IOException;
  18. import java.sql.PreparedStatement;
  19. import java.sql.ResultSet;
  20. import java.sql.SQLException;
  21. import javax.transaction.Status;
  22. import javax.transaction.Synchronization;
  23. import javax.transaction.TransactionManager;
  24. import net.sf.hibernate.HibernateException;
  25. import net.sf.hibernate.UserType;
  26. import net.sf.hibernate.util.EqualsHelper;
  27. import org.apache.commons.logging.Log;
  28. import org.apache.commons.logging.LogFactory;
  29. import org.springframework.dao.DataAccessResourceFailureException;
  30. import org.springframework.jdbc.support.lob.LobCreator;
  31. import org.springframework.jdbc.support.lob.LobHandler;
  32. import org.springframework.orm.hibernate.LocalSessionFactoryBean;
  33. import org.springframework.transaction.support.TransactionSynchronizationAdapter;
  34. import org.springframework.transaction.support.TransactionSynchronizationManager;
  35. /**
  36.  * Abstract base class for Hibernate UserType implementations that map to LOBs.
  37.  * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time.
  38.  *
  39.  * <p>Requires either active Spring transaction synchronization or a specified
  40.  * "jtaTransactionManager" on LocalSessionFactoryBean plus an active JTA transaction.
  41.  *
  42.  * <p>Offers template methods for getting and setting that pass in the LobHandler
  43.  * respectively LobCreator to use.
  44.  *
  45.  * @author Juergen Hoeller
  46.  * @since 1.1
  47.  * @see org.springframework.jdbc.support.lob.LobHandler
  48.  * @see org.springframework.orm.hibernate.LocalSessionFactoryBean#setLobHandler
  49.  * @see org.springframework.orm.hibernate.LocalSessionFactoryBean#setJtaTransactionManager
  50.  */
  51. public abstract class AbstractLobType implements UserType {
  52. protected final Log logger = LogFactory.getLog(getClass());
  53. private final LobHandler lobHandler;
  54. private final TransactionManager jtaTransactionManager;
  55. /**
  56.  * Constructor used by Hibernate: fetches config-time LobHandler and
  57.  * config-time JTA TransactionManager from LocalSessionFactoryBean.
  58.  * @see org.springframework.orm.hibernate.LocalSessionFactoryBean#getConfigTimeLobHandler
  59.  * @see org.springframework.orm.hibernate.LocalSessionFactoryBean#getConfigTimeTransactionManager
  60.  */
  61. protected AbstractLobType() {
  62. this(LocalSessionFactoryBean.getConfigTimeLobHandler(),
  63.     LocalSessionFactoryBean.getConfigTimeTransactionManager());
  64. }
  65. /**
  66.  * Constructor used for testing: takes an explicit LobHandler
  67.  * and an explicit JTA TransactionManager (can be null).
  68.  */
  69. protected AbstractLobType(LobHandler lobHandler, TransactionManager jtaTransactionManager) {
  70. this.lobHandler = lobHandler;
  71. this.jtaTransactionManager = jtaTransactionManager;
  72. }
  73. /**
  74.  * This implementation returns false.
  75.  */
  76. public boolean isMutable() {
  77. return false;
  78. }
  79. /**
  80.  * This implementation delegates to the Hibernate EqualsHelper.
  81.  * @see net.sf.hibernate.util.EqualsHelper#equals
  82.  */
  83. public boolean equals(Object x, Object y) throws HibernateException {
  84. return EqualsHelper.equals(x, y);
  85. }
  86. /**
  87.  * This implementation returns the passed-in value as-is.
  88.  */
  89. public Object deepCopy(Object value) throws HibernateException {
  90. return value;
  91. }
  92. /**
  93.  * This implementation delegates to nullSafeGetInternal,
  94.  * passing in the LobHandler of this type.
  95.  * @see #nullSafeGetInternal
  96.  */
  97. public final Object nullSafeGet(ResultSet rs, String[] names, Object owner)
  98. throws HibernateException, SQLException {
  99. if (this.lobHandler == null) {
  100. throw new IllegalStateException("No LobHandler found for configuration - " +
  101.     "lobHandler property must be set on LocalSessionFactoryBean");
  102. }
  103. try {
  104. return nullSafeGetInternal(rs, rs.findColumn(names[0]), this.lobHandler);
  105. }
  106. catch (IOException ex) {
  107. throw new HibernateException("I/O errors during LOB access", ex);
  108. }
  109. }
  110. /**
  111.  * This implementation delegates to nullSafeSetInternal,
  112.  * passing in a transaction-synchronized LobCreator for the
  113.  * LobHandler of this type.
  114.  * @see #nullSafeSetInternal
  115.  */
  116. public final void nullSafeSet(PreparedStatement st, Object value, int index)
  117. throws HibernateException, SQLException {
  118. if (this.lobHandler == null) {
  119. throw new IllegalStateException("No LobHandler found for configuration - " +
  120.     "lobHandler property must be set on LocalSessionFactoryBean");
  121. }
  122. LobCreator lobCreator = this.lobHandler.getLobCreator();
  123. try {
  124. nullSafeSetInternal(st, index, value, lobCreator);
  125. }
  126. catch (IOException ex) {
  127. throw new HibernateException("I/O errors during LOB access", ex);
  128. }
  129. if (TransactionSynchronizationManager.isSynchronizationActive()) {
  130. logger.debug("Registering Spring transaction synchronization for Hibernate LOB type");
  131. TransactionSynchronizationManager.registerSynchronization(
  132.     new SpringLobCreatorSynchronization(lobCreator));
  133. }
  134. else {
  135. if (this.jtaTransactionManager != null) {
  136. try {
  137. int jtaStatus = this.jtaTransactionManager.getStatus();
  138. if (jtaStatus == Status.STATUS_ACTIVE || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
  139. logger.debug("Registering JTA transaction synchronization for Hibernate LOB type");
  140. this.jtaTransactionManager.getTransaction().registerSynchronization(
  141. new JtaLobCreatorSynchronization(lobCreator));
  142. return;
  143. }
  144. }
  145. catch (Exception ex) {
  146. throw new DataAccessResourceFailureException(
  147. "Could not register synchronization with JTA TransactionManager", ex);
  148. }
  149. }
  150. throw new IllegalStateException("Active Spring transaction synchronization or " +
  151.     "jtaTransactionManager on LocalSessionFactoryBean plus active JTA transaction required");
  152. }
  153. }
  154. /**
  155.  * Template method to extract a value from the given result set.
  156.  * @param rs the ResultSet to extract from
  157.  * @param index the index in the ResultSet
  158.  * @param lobHandler the LobHandler to use
  159.  * @return the extracted value
  160.  * @throws SQLException if thrown by JDBC methods
  161.  * @throws IOException if thrown by streaming methods
  162.  * @throws HibernateException in case of any other exceptions
  163.  */
  164. protected abstract Object nullSafeGetInternal(ResultSet rs, int index, LobHandler lobHandler)
  165. throws SQLException, IOException, HibernateException;
  166. /**
  167.  * Template method to set the given value on the given statement.
  168.  * @param ps the PreparedStatement to set on
  169.  * @param index the statement parameter index
  170.  * @param value the value to set
  171.  * @param lobCreator the LobCreator to use
  172.  * @throws SQLException if thrown by JDBC methods
  173.  * @throws IOException if thrown by streaming methods
  174.  * @throws HibernateException in case of any other exceptions
  175.  */
  176. protected abstract void nullSafeSetInternal(
  177.     PreparedStatement ps, int index, Object value, LobCreator lobCreator)
  178. throws SQLException, IOException, HibernateException;
  179. /**
  180.  * Callback for resource cleanup at the end of a Spring transaction.
  181.  * Invokes LobCreator.close to clean up temporary LOBs that might have been created.
  182.  * @see org.springframework.jdbc.support.lob.LobCreator#close
  183.  */
  184. private static class SpringLobCreatorSynchronization extends TransactionSynchronizationAdapter {
  185. private final LobCreator lobCreator;
  186. private SpringLobCreatorSynchronization(LobCreator lobCreator) {
  187. this.lobCreator = lobCreator;
  188. }
  189. public void beforeCompletion() {
  190. this.lobCreator.close();
  191. }
  192. }
  193. /**
  194.  * Callback for resource cleanup at the end of a JTA transaction.
  195.  * Invokes LobCreator.close to clean up temporary LOBs that might have been created.
  196.  * @see org.springframework.jdbc.support.lob.LobCreator#close
  197.  */
  198. private static class JtaLobCreatorSynchronization implements Synchronization {
  199. private final LobCreator lobCreator;
  200. public JtaLobCreatorSynchronization(LobCreator lobCreator) {
  201. this.lobCreator = lobCreator;
  202. }
  203. public void beforeCompletion() {
  204. }
  205. public void afterCompletion(int status) {
  206. this.lobCreator.close();
  207. }
  208. }
  209. }