1 16 17 package org.springframework.orm.jdo; 18 19 import java.lang.reflect.InvocationHandler ; 20 import java.lang.reflect.InvocationTargetException ; 21 import java.lang.reflect.Method ; 22 import java.lang.reflect.Proxy ; 23 import java.util.Collection ; 24 import java.util.Map ; 25 26 import javax.jdo.JDOException; 27 import javax.jdo.PersistenceManager; 28 import javax.jdo.PersistenceManagerFactory; 29 import javax.jdo.Query; 30 31 import org.springframework.dao.DataAccessException; 32 import org.springframework.dao.InvalidDataAccessApiUsageException; 33 import org.springframework.transaction.support.TransactionSynchronizationManager; 34 import org.springframework.util.Assert; 35 import org.springframework.util.ClassUtils; 36 import org.springframework.util.ReflectionUtils; 37 38 108 public class JdoTemplate extends JdoAccessor implements JdoOperations { 109 110 private static Method newObjectIdInstanceMethod; 111 112 private static Method makePersistentMethod; 113 114 private static Method makePersistentAllMethod; 115 116 static { 117 try { 120 newObjectIdInstanceMethod = PersistenceManager.class.getMethod( 121 "newObjectIdInstance", new Class [] {Class .class, String .class}); 122 } 123 catch (NoSuchMethodException ex) { 124 newObjectIdInstanceMethod = null; 125 } 126 try { 130 makePersistentMethod = PersistenceManager.class.getMethod( 131 "makePersistent", new Class [] {Object .class}); 132 } 133 catch (NoSuchMethodException ex) { 134 throw new IllegalStateException ("JDO makePersistent(Object) method not available"); 135 } 136 try { 140 makePersistentAllMethod = PersistenceManager.class.getMethod( 141 "makePersistentAll", new Class [] {Collection .class}); 142 } 143 catch (NoSuchMethodException ex) { 144 throw new IllegalStateException ("JDO makePersistentAll(Collection) method not available"); 145 } 146 } 147 148 149 private boolean allowCreate = true; 150 151 private boolean exposeNativePersistenceManager = false; 152 153 154 157 public JdoTemplate() { 158 } 159 160 164 public JdoTemplate(PersistenceManagerFactory pmf) { 165 setPersistenceManagerFactory(pmf); 166 afterPropertiesSet(); 167 } 168 169 175 public JdoTemplate(PersistenceManagerFactory pmf, boolean allowCreate) { 176 setPersistenceManagerFactory(pmf); 177 setAllowCreate(allowCreate); 178 afterPropertiesSet(); 179 } 180 181 191 public void setAllowCreate(boolean allowCreate) { 192 this.allowCreate = allowCreate; 193 } 194 195 198 public boolean isAllowCreate() { 199 return allowCreate; 200 } 201 202 216 public void setExposeNativePersistenceManager(boolean exposeNativePersistenceManager) { 217 this.exposeNativePersistenceManager = exposeNativePersistenceManager; 218 } 219 220 224 public boolean isExposeNativePersistenceManager() { 225 return exposeNativePersistenceManager; 226 } 227 228 229 public Object execute(JdoCallback action) throws DataAccessException { 230 return execute(action, isExposeNativePersistenceManager()); 231 } 232 233 public Collection executeFind(JdoCallback action) throws DataAccessException { 234 Object result = execute(action, isExposeNativePersistenceManager()); 235 if (result != null && !(result instanceof Collection )) { 236 throw new InvalidDataAccessApiUsageException( 237 "Result object returned from JdoCallback isn't a Collection: [" + result + "]"); 238 } 239 return (Collection ) result; 240 } 241 242 251 public Object execute(JdoCallback action, boolean exposeNativePersistenceManager) throws DataAccessException { 252 Assert.notNull(action, "Callback object must not be null"); 253 254 PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager( 255 getPersistenceManagerFactory(), isAllowCreate()); 256 boolean existingTransaction = 257 TransactionSynchronizationManager.hasResource(getPersistenceManagerFactory()); 258 try { 259 PersistenceManager pmToExpose = (exposeNativePersistenceManager ? pm : createPersistenceManagerProxy(pm)); 260 Object result = action.doInJdo(pmToExpose); 261 flushIfNecessary(pm, existingTransaction); 262 return postProcessResult(result, pm, existingTransaction); 263 } 264 catch (JDOException ex) { 265 throw convertJdoAccessException(ex); 266 } 267 catch (RuntimeException ex) { 268 throw ex; 270 } 271 finally { 272 PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory()); 273 } 274 } 275 276 288 protected PersistenceManager createPersistenceManagerProxy(PersistenceManager pm) { 289 Class [] ifcs = ClassUtils.getAllInterfaces(pm); 290 return (PersistenceManager) Proxy.newProxyInstance( 291 getClass().getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(pm)); 292 } 293 294 307 protected Object postProcessResult(Object result, PersistenceManager pm, boolean existingTransaction) { 308 return result; 309 } 310 311 312 316 public Object getObjectById(final Object objectId) throws DataAccessException { 317 return execute(new JdoCallback() { 318 public Object doInJdo(PersistenceManager pm) throws JDOException { 319 return pm.getObjectById(objectId, true); 320 } 321 }, true); 322 } 323 324 public Object getObjectById(final Class entityClass, final Object idValue) throws DataAccessException { 325 return execute(new JdoCallback() { 326 public Object doInJdo(PersistenceManager pm) throws JDOException { 327 if (newObjectIdInstanceMethod != null) { 329 Object id = ReflectionUtils.invokeMethod( 330 newObjectIdInstanceMethod, pm, new Object [] {entityClass, idValue.toString()}); 331 return pm.getObjectById(id, true); 332 } 333 return pm.getObjectById(entityClass, idValue); 335 } 336 }, true); 337 } 338 339 public void evict(final Object entity) throws DataAccessException { 340 execute(new JdoCallback() { 341 public Object doInJdo(PersistenceManager pm) throws JDOException { 342 pm.evict(entity); 343 return null; 344 } 345 }, true); 346 } 347 348 public void evictAll(final Collection entities) throws DataAccessException { 349 execute(new JdoCallback() { 350 public Object doInJdo(PersistenceManager pm) throws JDOException { 351 pm.evictAll(entities); 352 return null; 353 } 354 }, true); 355 } 356 357 public void evictAll() throws DataAccessException { 358 execute(new JdoCallback() { 359 public Object doInJdo(PersistenceManager pm) throws JDOException { 360 pm.evictAll(); 361 return null; 362 } 363 }, true); 364 } 365 366 public void refresh(final Object entity) throws DataAccessException { 367 execute(new JdoCallback() { 368 public Object doInJdo(PersistenceManager pm) throws JDOException { 369 pm.refresh(entity); 370 return null; 371 } 372 }, true); 373 } 374 375 public void refreshAll(final Collection entities) throws DataAccessException { 376 execute(new JdoCallback() { 377 public Object doInJdo(PersistenceManager pm) throws JDOException { 378 pm.refreshAll(entities); 379 return null; 380 } 381 }, true); 382 } 383 384 public void refreshAll() throws DataAccessException { 385 execute(new JdoCallback() { 386 public Object doInJdo(PersistenceManager pm) throws JDOException { 387 pm.refreshAll(); 388 return null; 389 } 390 }, true); 391 } 392 393 public void makePersistent(final Object entity) throws DataAccessException { 394 execute(new JdoCallback() { 395 public Object doInJdo(PersistenceManager pm) throws JDOException { 396 return ReflectionUtils.invokeMethod(makePersistentMethod, pm, new Object [] {entity}); 397 } 398 }, true); 399 } 400 401 public void makePersistentAll(final Collection entities) throws DataAccessException { 402 execute(new JdoCallback() { 403 public Object doInJdo(PersistenceManager pm) throws JDOException { 404 return ReflectionUtils.invokeMethod(makePersistentAllMethod, pm, new Object [] {entities}); 405 } 406 }, true); 407 } 408 409 public void deletePersistent(final Object entity) throws DataAccessException { 410 execute(new JdoCallback() { 411 public Object doInJdo(PersistenceManager pm) throws JDOException { 412 pm.deletePersistent(entity); 413 return null; 414 } 415 }, true); 416 } 417 418 public void deletePersistentAll(final Collection entities) throws DataAccessException { 419 execute(new JdoCallback() { 420 public Object doInJdo(PersistenceManager pm) throws JDOException { 421 pm.deletePersistentAll(entities); 422 return null; 423 } 424 }, true); 425 } 426 427 public Object detachCopy(final Object entity) { 428 return execute(new JdoCallback() { 429 public Object doInJdo(PersistenceManager pm) throws JDOException { 430 return getJdoDialect().detachCopy(pm, entity); 431 } 432 }, true); 433 } 434 435 public Collection detachCopyAll(final Collection entities) { 436 return (Collection ) execute(new JdoCallback() { 437 public Object doInJdo(PersistenceManager pm) throws JDOException { 438 return getJdoDialect().detachCopyAll(pm, entities); 439 } 440 }, true); 441 } 442 443 public Object attachCopy(final Object detachedEntity) { 444 return execute(new JdoCallback() { 445 public Object doInJdo(PersistenceManager pm) throws JDOException { 446 return getJdoDialect().attachCopy(pm, detachedEntity); 447 } 448 }, true); 449 } 450 451 public Collection attachCopyAll(final Collection detachedEntities) { 452 return (Collection ) execute(new JdoCallback() { 453 public Object doInJdo(PersistenceManager pm) throws JDOException { 454 return getJdoDialect().attachCopyAll(pm, detachedEntities); 455 } 456 }, true); 457 } 458 459 public void flush() throws DataAccessException { 460 execute(new JdoCallback() { 461 public Object doInJdo(PersistenceManager pm) throws JDOException { 462 getJdoDialect().flush(pm); 463 return null; 464 } 465 }, true); 466 } 467 468 469 473 public Collection find(Class entityClass) throws DataAccessException { 474 return find(entityClass, null, null); 475 } 476 477 public Collection find(Class entityClass, String filter) throws DataAccessException { 478 return find(entityClass, filter, null); 479 } 480 481 public Collection find(final Class entityClass, final String filter, final String ordering) 482 throws DataAccessException { 483 484 return (Collection ) execute(new JdoCallback() { 485 public Object doInJdo(PersistenceManager pm) throws JDOException { 486 Query query = (filter != null ? pm.newQuery(entityClass, filter) : pm.newQuery(entityClass)); 487 prepareQuery(query); 488 if (ordering != null) { 489 query.setOrdering(ordering); 490 } 491 return query.execute(); 492 } 493 }, true); 494 } 495 496 public Collection find(Class entityClass, String filter, String parameters, Object [] values) 497 throws DataAccessException { 498 499 return find(entityClass, filter, parameters, values, null); 500 } 501 502 public Collection find( 503 final Class entityClass, final String filter, final String parameters, final Object [] values, 504 final String ordering) throws DataAccessException { 505 506 return (Collection ) execute(new JdoCallback() { 507 public Object doInJdo(PersistenceManager pm) throws JDOException { 508 Query query = pm.newQuery(entityClass, filter); 509 prepareQuery(query); 510 query.declareParameters(parameters); 511 if (ordering != null) { 512 query.setOrdering(ordering); 513 } 514 return query.executeWithArray(values); 515 } 516 }, true); 517 } 518 519 public Collection find(Class entityClass, String filter, String parameters, Map values) 520 throws DataAccessException { 521 522 return find(entityClass, filter, parameters, values, null); 523 } 524 525 public Collection find( 526 final Class entityClass, final String filter, final String parameters, final Map values, 527 final String ordering) throws DataAccessException { 528 529 return (Collection ) execute(new JdoCallback() { 530 public Object doInJdo(PersistenceManager pm) throws JDOException { 531 Query query = pm.newQuery(entityClass, filter); 532 prepareQuery(query); 533 query.declareParameters(parameters); 534 if (ordering != null) { 535 query.setOrdering(ordering); 536 } 537 return query.executeWithMap(values); 538 } 539 }, true); 540 } 541 542 public Collection find(final String language, final Object queryObject) throws DataAccessException { 543 return (Collection ) execute(new JdoCallback() { 544 public Object doInJdo(PersistenceManager pm) throws JDOException { 545 Query query = pm.newQuery(language, queryObject); 546 prepareQuery(query); 547 return query.execute(); 548 } 549 }, true); 550 } 551 552 public Collection find(final String queryString) throws DataAccessException { 553 return (Collection ) execute(new JdoCallback() { 554 public Object doInJdo(PersistenceManager pm) throws JDOException { 555 Query query = pm.newQuery(queryString); 556 prepareQuery(query); 557 return query.execute(); 558 } 559 }, true); 560 } 561 562 public Collection find(final String queryString, final Object [] values) throws DataAccessException { 563 return (Collection ) execute(new JdoCallback() { 564 public Object doInJdo(PersistenceManager pm) throws JDOException { 565 Query query = pm.newQuery(queryString); 566 prepareQuery(query); 567 return query.executeWithArray(values); 568 } 569 }, true); 570 } 571 572 public Collection find(final String queryString, final Map values) throws DataAccessException { 573 return (Collection ) execute(new JdoCallback() { 574 public Object doInJdo(PersistenceManager pm) throws JDOException { 575 Query query = pm.newQuery(queryString); 576 prepareQuery(query); 577 return query.executeWithMap(values); 578 } 579 }, true); 580 } 581 582 public Collection findByNamedQuery(final Class entityClass, final String queryName) throws DataAccessException { 583 return (Collection ) execute(new JdoCallback() { 584 public Object doInJdo(PersistenceManager pm) throws JDOException { 585 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName); 586 prepareQuery(query); 587 return query.execute(); 588 } 589 }, true); 590 } 591 592 public Collection findByNamedQuery(final Class entityClass, final String queryName, final Object [] values) 593 throws DataAccessException { 594 595 return (Collection ) execute(new JdoCallback() { 596 public Object doInJdo(PersistenceManager pm) throws JDOException { 597 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName); 598 prepareQuery(query); 599 return query.executeWithArray(values); 600 } 601 }, true); 602 } 603 604 public Collection findByNamedQuery(final Class entityClass, final String queryName, final Map values) 605 throws DataAccessException { 606 607 return (Collection ) execute(new JdoCallback() { 608 public Object doInJdo(PersistenceManager pm) throws JDOException { 609 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName); 610 prepareQuery(query); 611 return query.executeWithMap(values); 612 } 613 }, true); 614 } 615 616 617 632 public void prepareQuery(Query query) throws JDOException { 633 PersistenceManagerFactoryUtils.applyTransactionTimeout( 634 query, getPersistenceManagerFactory(), getJdoDialect()); 635 } 636 637 638 643 private class CloseSuppressingInvocationHandler implements InvocationHandler { 644 645 private final PersistenceManager target; 646 647 public CloseSuppressingInvocationHandler(PersistenceManager target) { 648 this.target = target; 649 } 650 651 public Object invoke(Object proxy, Method method, Object [] args) throws Throwable { 652 654 if (method.getName().equals("equals")) { 655 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE); 657 } 658 else if (method.getName().equals("hashCode")) { 659 return new Integer (hashCode()); 661 } 662 else if (method.getName().equals("close")) { 663 return null; 665 } 666 667 try { 669 Object retVal = method.invoke(this.target, args); 670 671 if (retVal instanceof Query) { 673 prepareQuery(((Query) retVal)); 674 } 675 676 return retVal; 677 } 678 catch (InvocationTargetException ex) { 679 throw ex.getTargetException(); 680 } 681 } 682 } 683 684 } 685 | Popular Tags |