JdoTemplate.java
Upload User: jiancairen
Upload Date: 2007-08-27
Package Size: 26458k
Code Size: 12k
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.jdo;
  17. import java.io.Serializable;
  18. import java.util.Collection;
  19. import java.util.Map;
  20. import javax.jdo.JDOException;
  21. import javax.jdo.PersistenceManager;
  22. import javax.jdo.PersistenceManagerFactory;
  23. import javax.jdo.Query;
  24. import org.springframework.dao.DataAccessException;
  25. import org.springframework.transaction.support.TransactionSynchronizationManager;
  26. /**
  27.  * Helper class that simplifies JDO data access code, and converts
  28.  * JDOExceptions into JdoUsage/JdoSystemException, compatible to the
  29.  * org.springframework.dao exception hierarchy.
  30.  *
  31.  * <p>The central method is "execute", supporting JDO code implementing
  32.  * the JdoCallback interface. It provides JDO PersistenceManager handling
  33.  * such that neither the JdoCallback implementation nor the calling code
  34.  * needs to explicitly care about retrieving/closing PersistenceManagers,
  35.  * or handling JDO lifecycle exceptions.
  36.  *
  37.  * <p>Typically used to implement data access or business logic services that
  38.  * use JDO within their implementation but are JDO-agnostic in their interface.
  39.  * The latter resp. code calling the latter only have to deal with business
  40.  * objects, query objects, and org.springframework.dao exceptions.
  41.  *
  42.  * <p>Can be used within a service implementation via direct instantiation
  43.  * with a PersistenceManagerFactory reference, or get prepared in an
  44.  * application context and given to services as bean reference.
  45.  * Note: The PersistenceManagerFactory should always be configured as bean in
  46.  * the application context, in the first case given to the service directly,
  47.  * in the second case to the prepared template.
  48.  *
  49.  * <p>This class can be considered a programmatic alternative to
  50.  * JdoInterceptor. The major advantage is its straightforwardness, the
  51.  * major disadvantage that no checked application exceptions can get thrown
  52.  * from within data access code. Respective checks and the actual throwing of
  53.  * such exceptions can often be deferred to after callback execution, though.
  54.  *
  55.  * <p>Note that even if JdoTransactionManager is used for transaction
  56.  * demarcation in higher-level services, all those services above the data
  57.  * access layer don't need need to be JDO-aware. Setting such a special
  58.  * PlatformTransactionManager is a configuration issue, without introducing
  59.  * code dependencies.
  60.  *
  61.  * <p>LocalPersistenceManagerFactoryBean is the preferred way of obtaining a
  62.  * reference to a specific PersistenceManagerFactory, at least in a non-EJB
  63.  * environment. Registering a PersistenceManagerFactory with JNDI is only
  64.  * advisable when using a JCA Connector, i.e. when the application server
  65.  * cares for initialization. Else, portability is rather limited: Manual
  66.  * JNDI binding isn't supported by some application servers (e.g. Tomcat).
  67.  *
  68.  * @author Juergen Hoeller
  69.  * @since 03.06.2003
  70.  * @see JdoCallback
  71.  * @see JdoTransactionManager
  72.  */
  73. public class JdoTemplate extends JdoAccessor implements JdoOperations {
  74. private boolean allowCreate = true;
  75. /**
  76.  * Create a new JdoTemplate instance.
  77.  */
  78. public JdoTemplate() {
  79. }
  80. /**
  81.  * Create a new JdoTemplate instance.
  82.  * @param pmf PersistenceManagerFactory to create PersistenceManagers
  83.  */
  84. public JdoTemplate(PersistenceManagerFactory pmf) {
  85. setPersistenceManagerFactory(pmf);
  86. afterPropertiesSet();
  87. }
  88. /**
  89.  * Create a new JdoTemplate instance.
  90.  * @param pmf PersistenceManagerFactory to create PersistenceManagers
  91.  * @param allowCreate if a new PersistenceManager should be created
  92.  * if no thread-bound found
  93.  */
  94. public JdoTemplate(PersistenceManagerFactory pmf, boolean allowCreate) {
  95. setPersistenceManagerFactory(pmf);
  96. setAllowCreate(allowCreate);
  97. afterPropertiesSet();
  98. }
  99. /**
  100.  * Set if a new PersistenceManager should be created if no thread-bound found.
  101.  * <p>JdoTemplate is aware of a respective PersistenceManager bound to the
  102.  * current thread, for example when using JdoTransactionManager.
  103.  * If allowCreate is true, a new PersistenceManager will be created if none
  104.  * found. If false, an IllegalStateException will get thrown in this case.
  105.  * @see PersistenceManagerFactoryUtils#getPersistenceManager
  106.  */
  107. public void setAllowCreate(boolean allowCreate) {
  108. this.allowCreate = allowCreate;
  109. }
  110. /**
  111.  * Return if a new PersistenceManager should be created if no thread-bound found.
  112.  */
  113. public boolean isAllowCreate() {
  114. return allowCreate;
  115. }
  116. public Object execute(JdoCallback action) throws DataAccessException {
  117. PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager(
  118.     getPersistenceManagerFactory(), isAllowCreate());
  119. boolean existingTransaction =
  120.     TransactionSynchronizationManager.hasResource(getPersistenceManagerFactory());
  121. try {
  122. Object result = action.doInJdo(pm);
  123. flushIfNecessary(pm, existingTransaction);
  124. return result;
  125. }
  126. catch (JDOException ex) {
  127. throw convertJdoAccessException(ex);
  128. }
  129. catch (RuntimeException ex) {
  130. // callback code threw application exception
  131. throw ex;
  132. }
  133. finally {
  134. PersistenceManagerFactoryUtils.closePersistenceManagerIfNecessary(pm, getPersistenceManagerFactory());
  135. }
  136. }
  137. public Collection executeFind(JdoCallback action) throws DataAccessException {
  138. return (Collection) execute(action);
  139. }
  140. //-------------------------------------------------------------------------
  141. // Convenience methods for load, save, delete
  142. //-------------------------------------------------------------------------
  143. public Object getObjectById(final Serializable objectId) throws DataAccessException {
  144. return execute(new JdoCallback() {
  145. public Object doInJdo(PersistenceManager pm) throws JDOException {
  146. return pm.getObjectById(objectId, true);
  147. }
  148. });
  149. }
  150. public Object getObjectById(final Class entityClass, final Serializable idValue) throws DataAccessException {
  151. return execute(new JdoCallback() {
  152. public Object doInJdo(PersistenceManager pm) throws JDOException {
  153. Object oid = pm.newObjectIdInstance(entityClass, idValue.toString());
  154. return pm.getObjectById(oid, true);
  155. }
  156. });
  157. }
  158. public void evict(final Object entity) throws DataAccessException {
  159. execute(new JdoCallback() {
  160. public Object doInJdo(PersistenceManager pm) throws JDOException {
  161. pm.evict(entity);
  162. return null;
  163. }
  164. });
  165. }
  166. public void evictAll() throws DataAccessException {
  167. execute(new JdoCallback() {
  168. public Object doInJdo(PersistenceManager pm) throws JDOException {
  169. pm.evictAll();
  170. return null;
  171. }
  172. });
  173. }
  174. public void refresh(final Object entity) throws DataAccessException {
  175. execute(new JdoCallback() {
  176. public Object doInJdo(PersistenceManager pm) throws JDOException {
  177. pm.refresh(entity);
  178. return null;
  179. }
  180. });
  181. }
  182. public void refreshAll() throws DataAccessException {
  183. execute(new JdoCallback() {
  184. public Object doInJdo(PersistenceManager pm) throws JDOException {
  185. pm.refreshAll();
  186. return null;
  187. }
  188. });
  189. }
  190. public void makePersistent(final Object entity) throws DataAccessException {
  191. execute(new JdoCallback() {
  192. public Object doInJdo(PersistenceManager pm) throws JDOException {
  193. pm.makePersistent(entity);
  194. return null;
  195. }
  196. });
  197. }
  198. public void deletePersistent(final Object entity) throws DataAccessException {
  199. execute(new JdoCallback() {
  200. public Object doInJdo(PersistenceManager pm) throws JDOException {
  201. pm.deletePersistent(entity);
  202. return null;
  203. }
  204. });
  205. }
  206. public void deletePersistentAll(final Collection entities) throws DataAccessException {
  207. execute(new JdoCallback() {
  208. public Object doInJdo(PersistenceManager pm) throws JDOException {
  209. pm.deletePersistentAll(entities);
  210. return null;
  211. }
  212. });
  213. }
  214. public void flush() throws DataAccessException {
  215. execute(new JdoCallback() {
  216. public Object doInJdo(PersistenceManager pm) throws JDOException {
  217. getJdoDialect().flush(pm);
  218. return null;
  219. }
  220. });
  221. }
  222. //-------------------------------------------------------------------------
  223. // Convenience finder methods
  224. //-------------------------------------------------------------------------
  225. public Collection find(final Class entityClass) throws DataAccessException {
  226. return executeFind(new JdoCallback() {
  227. public Object doInJdo(PersistenceManager pm) throws JDOException {
  228. Query query = pm.newQuery(entityClass);
  229. prepareQuery(query);
  230. return query.execute();
  231. }
  232. });
  233. }
  234. public Collection find(final Class entityClass, final String filter) throws DataAccessException {
  235. return executeFind(new JdoCallback() {
  236. public Object doInJdo(PersistenceManager pm) throws JDOException {
  237. Query query = pm.newQuery(entityClass, filter);
  238. prepareQuery(query);
  239. return query.execute();
  240. }
  241. });
  242. }
  243. public Collection find(final Class entityClass, final String filter, final String ordering)
  244. throws DataAccessException {
  245. return executeFind(new JdoCallback() {
  246. public Object doInJdo(PersistenceManager pm) throws JDOException {
  247. Query query = pm.newQuery(entityClass, filter);
  248. query.setOrdering(ordering);
  249. prepareQuery(query);
  250. return query.execute();
  251. }
  252. });
  253. }
  254. public Collection find(
  255. final Class entityClass, final String filter, final String parameters, final Object[] values)
  256. throws DataAccessException {
  257. return executeFind(new JdoCallback() {
  258. public Object doInJdo(PersistenceManager pm) throws JDOException {
  259. Query query = pm.newQuery(entityClass, filter);
  260. query.declareParameters(parameters);
  261. prepareQuery(query);
  262. return query.executeWithArray(values);
  263. }
  264. });
  265. }
  266. public Collection find(
  267. final Class entityClass, final String filter, final String parameters, final Object[] values,
  268. final String ordering) throws DataAccessException {
  269. return executeFind(new JdoCallback() {
  270. public Object doInJdo(PersistenceManager pm) throws JDOException {
  271. Query query = pm.newQuery(entityClass, filter);
  272. query.declareParameters(parameters);
  273. query.setOrdering(ordering);
  274. prepareQuery(query);
  275. return query.executeWithArray(values);
  276. }
  277. });
  278. }
  279. public Collection find(
  280. final Class entityClass, final String filter, final String parameters, final Map values)
  281. throws DataAccessException {
  282. return executeFind(new JdoCallback() {
  283. public Object doInJdo(PersistenceManager pm) throws JDOException {
  284. Query query = pm.newQuery(entityClass, filter);
  285. query.declareParameters(parameters);
  286. prepareQuery(query);
  287. return query.executeWithMap(values);
  288. }
  289. });
  290. }
  291. public Collection find(
  292. final Class entityClass, final String filter, final String parameters, final Map values,
  293. final String ordering) throws DataAccessException {
  294. return executeFind(new JdoCallback() {
  295. public Object doInJdo(PersistenceManager pm) throws JDOException {
  296. Query query = pm.newQuery(entityClass, filter);
  297. query.declareParameters(parameters);
  298. query.setOrdering(ordering);
  299. prepareQuery(query);
  300. return query.executeWithMap(values);
  301. }
  302. });
  303. }
  304. /**
  305.  * Prepare the given JDO query object. To be used within a JdoCallback.
  306.  * <p>Applies a transaction timeout, if any. If you don't use such timeouts,
  307.  * the call is a no-op.
  308.  * @param query the JDO query object
  309.  * @throws JDOException if the query could not be properly prepared
  310.  * @see JdoCallback#doInJdo
  311.  * @see PersistenceManagerFactoryUtils#applyTransactionTimeout
  312.  */
  313. public void prepareQuery(Query query) throws JDOException {
  314. PersistenceManagerFactoryUtils.applyTransactionTimeout(
  315. query, getPersistenceManagerFactory(), getJdoDialect());
  316. }
  317. }