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.jdo;
  17. import javax.jdo.JDOException;
  18. import javax.jdo.PersistenceManager;
  19. import javax.jdo.PersistenceManagerFactory;
  20. import org.apache.commons.logging.Log;
  21. import org.apache.commons.logging.LogFactory;
  22. import org.springframework.beans.factory.InitializingBean;
  23. import org.springframework.dao.DataAccessException;
  24. /**
  25. * Base class for JdoTemplate and JdoInterceptor, defining common
  26. * properties like flushing behavior.
  27. *
  28. * <p>Note: With JDO, modifications to persistent objects are just possible
  29. * within a transaction (in contrast to Hibernate). Therefore, eager flushing
  30. * will just get applied when in a transaction. Furthermore, there is explicit
  31. * notion of flushing never, as this would not imply a performance gain due to
  32. * JDO's field interception mechanism that doesn't involve snapshot comparison.
  33. *
  34. * <p>Eager flushing is just available for specific JDO implementations.
  35. * You need to a corresponding JdoDialect to make eager flushing work.
  36. *
  37. * <p>Not intended to be used directly. See JdoTemplate and JdoInterceptor.
  38. *
  39. * @author Juergen Hoeller
  40. * @since 02.11.2003
  41. * @see JdoTemplate
  42. * @see JdoInterceptor
  43. * @see #setFlushEager
  44. */
  45. public class JdoAccessor implements InitializingBean {
  46. protected final Log logger = LogFactory.getLog(getClass());
  47. private PersistenceManagerFactory persistenceManagerFactory;
  48. private JdoDialect jdoDialect;
  49. private boolean flushEager = false;
  50. /**
  51. * Set the JDO PersistenceManagerFactory that should be used to create
  52. * PersistenceManagers.
  53. */
  54. public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
  55. this.persistenceManagerFactory = pmf;
  56. }
  57. /**
  58. * Return the JDO PersistenceManagerFactory that should be used to create
  59. * PersistenceManagers.
  60. */
  61. public PersistenceManagerFactory getPersistenceManagerFactory() {
  62. return persistenceManagerFactory;
  63. }
  64. /**
  65. * Set the JDO dialect to use for this accessor.
  66. * <p>The dialect object can be used to retrieve the underlying JDBC
  67. * connection or to eagerly flush changes to the database.
  68. */
  69. public void setJdoDialect(JdoDialect jdoDialect) {
  70. this.jdoDialect = jdoDialect;
  71. }
  72. /**
  73. * Return the JDO dialect to use for this accessor.
  74. */
  75. public JdoDialect getJdoDialect() {
  76. return jdoDialect;
  77. }
  78. /**
  79. * Set if this accessor should flush changes to the database eagerly.
  80. * <p>Eager flushing leads to immediate synchronization with the database,
  81. * even if in a transaction. This causes inconsistencies to show up and throw
  82. * a respective exception immediately, and JDBC access code that participates
  83. * in the same transaction will see the changes as the database is already
  84. * aware of them then. But the drawbacks are:
  85. * <ul>
  86. * <li>additional communication roundtrips with the database, instead of a
  87. * single batch at transaction commit;
  88. * <li>the fact that an actual database rollback is needed if the Hibernate
  89. * transaction rolls back (due to already submitted SQL statements).
  90. * </ul>
  91. */
  92. public void setFlushEager(boolean flushEager) {
  93. this.flushEager = flushEager;
  94. }
  95. /**
  96. * Return if this accessor should flush changes to the database eagerly.
  97. */
  98. public boolean isFlushEager() {
  99. return flushEager;
  100. }
  101. public void afterPropertiesSet() {
  102. if (this.persistenceManagerFactory == null) {
  103. throw new IllegalArgumentException("persistenceManagerFactory is required");
  104. }
  105. if (this.flushEager && this.jdoDialect == null) {
  106. throw new IllegalArgumentException("Cannot flush eagerly without a jdoDialect setting");
  107. }
  108. }
  109. /**
  110. * Flush the given JDO persistence manager if necessary.
  111. * @param pm the current JDO PersistenceManage
  112. * @param existingTransaction if executing within an existing transaction
  113. * @throws JDOException in case of JDO flushing errors
  114. */
  115. public void flushIfNecessary(PersistenceManager pm, boolean existingTransaction) throws JDOException {
  116. if (this.flushEager && this.jdoDialect != null) {
  117. logger.debug("Eagerly flushing JDO persistence manager");
  118. this.jdoDialect.flush(pm);
  119. }
  120. }
  121. /**
  122. * Convert the given JDOException to an appropriate exception from the
  123. * org.springframework.dao hierarchy. Delegates to the JdoDialect if set, falls
  124. * back to PersistenceManagerFactoryUtils' standard exception translation else.
  125. * May be overridden in subclasses.
  126. * @param ex JDOException that occured
  127. * @return the corresponding DataAccessException instance
  128. * @see JdoDialect#translateException
  129. * @see PersistenceManagerFactoryUtils#convertJdoAccessException
  130. */
  131. public DataAccessException convertJdoAccessException(JDOException ex) {
  132. if (getJdoDialect() != null) {
  133. return getJdoDialect().translateException(ex);
  134. }
  135. else {
  136. return PersistenceManagerFactoryUtils.convertJdoAccessException(ex);
  137. }
  138. }
  139. }