1 /* 2 * Copyright (C) 2003-2012 David E. Berry 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * A copy of the GNU Lesser General Public License may also be found at 19 * http://www.gnu.org/licenses/lgpl.txt 20 */ 21 package org.synchronoss.cpo.jdbc; 22 23 import org.slf4j.*; 24 import org.synchronoss.cpo.*; 25 import org.synchronoss.cpo.cache.CpoAdapterCache; 26 import org.synchronoss.cpo.helper.ExceptionHelper; 27 import org.synchronoss.cpo.jdbc.meta.JdbcCpoMetaDescriptor; 28 import org.synchronoss.cpo.meta.CpoMetaDescriptor; 29 import org.synchronoss.cpo.meta.domain.*; 30 31 import javax.naming.*; 32 import javax.sql.DataSource; 33 import java.sql.*; 34 import java.util.*; 35 36 /** 37 * JdbcCpoAdapter is an interface for a set of routines that are responsible for managing value objects from a 38 * datasource. 39 * 40 * @author david berry 41 */ 42 public class JdbcCpoAdapter extends CpoAdapterCache implements CpoAdapter { 43 44 /** 45 * Version Id for this class. 46 */ 47 private static final long serialVersionUID = 1L; 48 /** 49 * DOCUMENT ME! 50 */ 51 private static final Logger logger = LoggerFactory.getLogger(JdbcCpoAdapter.class); 52 /** 53 * DOCUMENT ME! 54 */ 55 private static final String[] GROUP_IDS = { 56 "CREATE", "UPDATE", "DELETE", "RETRIEVE", "LIST", "PERSIST", "EXIST", "EXECUTE" 57 }; 58 // Function Group Name Constants 59 /** 60 * DOCUMENT ME! 61 */ 62 private static final String CREATE_GROUP = GROUP_IDS[CpoAdapter.CREATE]; 63 /** 64 * DOCUMENT ME! 65 */ 66 private static final String UPDATE_GROUP = GROUP_IDS[CpoAdapter.UPDATE]; 67 /** 68 * DOCUMENT ME! 69 */ 70 private static final String DELETE_GROUP = GROUP_IDS[CpoAdapter.DELETE]; 71 /** 72 * DOCUMENT ME! 73 */ 74 private static final String RETRIEVE_GROUP = GROUP_IDS[CpoAdapter.RETRIEVE]; 75 /** 76 * DOCUMENT ME! 77 */ 78 private static final String LIST_GROUP = GROUP_IDS[CpoAdapter.LIST]; 79 /** 80 * DOCUMENT ME! 81 */ 82 private static final String PERSIST_GROUP = GROUP_IDS[CpoAdapter.PERSIST]; 83 /** 84 * DOCUMENT ME! 85 */ 86 private static final String EXIST_GROUP = GROUP_IDS[CpoAdapter.EXIST]; 87 /** 88 * DOCUMENT ME! 89 */ 90 private static final String EXECUTE_GROUP = GROUP_IDS[CpoAdapter.EXECUTE]; 91 /** 92 * DOCUMENT ME! 93 */ 94 private Context context_ = null; 95 96 // DataSource Information 97 98 /** 99 * DOCUMENT ME! 100 */ 101 private DataSource readDataSource_ = null; 102 /** 103 * DOCUMENT ME! 104 */ 105 private DataSource writeDataSource_ = null; 106 /** 107 * DOCUMENT ME! 108 */ 109 private String dataSourceName_ = null; 110 /** 111 * DOCUMENT ME! 112 */ 113 private boolean invalidReadConnection_ = false; 114 private boolean batchUpdatesSupported_ = false; 115 /** 116 * CpoMetaDescriptor allows you to get the meta data for a class. 117 */ 118 private JdbcCpoMetaDescriptor metaDescriptor = null; 119 120 protected JdbcCpoAdapter() { 121 } 122 123 /** 124 * Creates a JdbcCpoAdapter. 125 * 126 * @param metaDescriptor This datasource that identifies the cpo metadata datasource 127 * @param jdsiTrx The datasoruce that identifies the transaction database. 128 * @throws org.synchronoss.cpo.CpoException exception 129 */ 130 protected JdbcCpoAdapter(JdbcCpoMetaDescriptor metaDescriptor, DataSourceInfo jdsiTrx) throws CpoException { 131 132 this.metaDescriptor = metaDescriptor; 133 writeDataSource_ = jdsiTrx.getDataSource(); 134 readDataSource_ = writeDataSource_; 135 dataSourceName_ = jdsiTrx.getDataSourceName(); 136 processDatabaseMetaData(); 137 } 138 139 /** 140 * Creates a JdbcCpoAdapter. 141 * 142 * @param metaDescriptor This datasource that identifies the cpo metadata datasource 143 * @param jdsiWrite The datasource that identifies the transaction database for write transactions. 144 * @param jdsiRead The datasource that identifies the transaction database for read-only transactions. 145 * @throws org.synchronoss.cpo.CpoException exception 146 */ 147 protected JdbcCpoAdapter(JdbcCpoMetaDescriptor metaDescriptor, DataSourceInfo jdsiWrite, DataSourceInfo jdsiRead) throws CpoException { 148 this.metaDescriptor = metaDescriptor; 149 writeDataSource_ = jdsiWrite.getDataSource(); 150 readDataSource_ = jdsiRead.getDataSource(); 151 dataSourceName_ = jdsiWrite.getDataSourceName(); 152 processDatabaseMetaData(); 153 } 154 155 /** 156 * This constructor is used specifically to create a JdbcCpoTrxAdapter. 157 * 158 * @param metaDescriptor 159 * @param batchSupported 160 * @param dataSourceName 161 * @throws CpoException 162 */ 163 protected JdbcCpoAdapter(JdbcCpoMetaDescriptor metaDescriptor, boolean batchSupported, String dataSourceName) throws CpoException { 164 this.metaDescriptor = metaDescriptor; 165 batchUpdatesSupported_ = batchSupported; 166 dataSourceName_ = dataSourceName; 167 } 168 169 private void processDatabaseMetaData() throws CpoException { 170 Connection c = null; 171 try { 172 c = getWriteConnection(); 173 DatabaseMetaData dmd = c.getMetaData(); 174 175 // do all the tests here 176 batchUpdatesSupported_ = dmd.supportsBatchUpdates(); 177 178 this.closeConnection(c); 179 } catch (Throwable t) { 180 logger.error(ExceptionHelper.getLocalizedMessage(t), t); 181 throw new CpoException("Could Not Retrieve Database Meta Data", t); 182 } finally { 183 closeConnection(c); 184 } 185 } 186 187 public static JdbcCpoAdapter getInstance(JdbcCpoMetaDescriptor metaDescriptor, DataSourceInfo jdsiTrx) throws CpoException { 188 String adapterKey = metaDescriptor + ":" + jdsiTrx.getDataSourceName(); 189 JdbcCpoAdapter adapter = (JdbcCpoAdapter)findCpoAdapter(adapterKey); 190 if (adapter == null) { 191 adapter = new JdbcCpoAdapter(metaDescriptor, jdsiTrx); 192 addCpoAdapter(adapterKey, adapter); 193 } 194 return adapter; 195 } 196 197 /** 198 * Creates a JdbcCpoAdapter. 199 * 200 * @param metaDescriptor This datasource that identifies the cpo metadata datasource 201 * @param jdsiWrite The datasource that identifies the transaction database for write transactions. 202 * @param jdsiRead The datasource that identifies the transaction database for read-only transactions. 203 * @throws org.synchronoss.cpo.CpoException exception 204 */ 205 public static JdbcCpoAdapter getInstance(JdbcCpoMetaDescriptor metaDescriptor, DataSourceInfo jdsiWrite, DataSourceInfo jdsiRead) throws CpoException { 206 String adapterKey = metaDescriptor + ":" + jdsiWrite.getDataSourceName() + ":" + jdsiRead.getDataSourceName(); 207 JdbcCpoAdapter adapter = (JdbcCpoAdapter)findCpoAdapter(adapterKey); 208 if (adapter == null) { 209 adapter = new JdbcCpoAdapter(metaDescriptor, jdsiWrite); 210 addCpoAdapter(adapterKey, adapter); 211 } 212 return adapter; 213 } 214 215 /** 216 * Creates the Object in the datasource. The assumption is that the object does not exist in the datasource. This 217 * method creates and stores the object in the datasource. 218 * 219 * <pre>Example: 220 * <code> 221 * 222 * class SomeObject so = new SomeObject(); 223 * class CpoAdapter cpo = null; 224 * 225 * try { 226 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 227 * } catch (CpoException ce) { 228 * // Handle the error 229 * cpo = null; 230 * } 231 * 232 * if (cpo!=null) { 233 * so.setId(1); 234 * so.setName("SomeName"); 235 * try{ 236 * cpo.insertObject(so); 237 * } catch (CpoException ce) { 238 * // Handle the error 239 * 240 * } 241 * } 242 * </code> 243 * </pre> 244 * 245 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 246 * defined an exception will be thrown. 247 * @return The number of objects created in the datasource 248 * @throws CpoException Thrown if there are errors accessing the datasource 249 */ 250 @Override 251 public <T> long insertObject(T obj) throws CpoException { 252 return processUpdateGroup(obj, JdbcCpoAdapter.CREATE_GROUP, null, null, null, null); 253 } 254 255 /** 256 * Creates the Object in the datasource. The assumption is that the object does not exist in the datasource. This 257 * method creates and stores the object in the datasource 258 * 259 * <pre>Example: 260 * <code> 261 * 262 * class SomeObject so = new SomeObject(); 263 * class CpoAdapter cpo = null; 264 * 265 * try { 266 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 267 * } catch (CpoException ce) { 268 * // Handle the error 269 * cpo = null; 270 * } 271 * 272 * if (cpo!=null) { 273 * so.setId(1); 274 * so.setName("SomeName"); 275 * try{ 276 * cpo.insertObject("IDNameInsert",so); 277 * } catch (CpoException ce) { 278 * // Handle the error 279 * } 280 * } 281 * </code> 282 * </pre> 283 * 284 * @param name The String name of the CREATE Function Group that will be used to create the object in the datasource. 285 * null signifies that the default rules will be used which is equivalent to insertObject(Object obj); 286 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 287 * defined an exception will be thrown. 288 * @return The number of objects created in the datasource 289 * @throws CpoException Thrown if there are errors accessing the datasource 290 */ 291 @Override 292 public <T> long insertObject(String name, T obj) throws CpoException { 293 return processUpdateGroup(obj, JdbcCpoAdapter.CREATE_GROUP, name, null, null, null); 294 } 295 296 /** 297 * Creates the Object in the datasource. The assumption is that the object does not exist in the datasource. This 298 * method creates and stores the object in the datasource 299 * 300 * <pre>Example: 301 * <code> 302 * 303 * class SomeObject so = new SomeObject(); 304 * class CpoAdapter cpo = null; 305 * 306 * try { 307 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 308 * } catch (CpoException ce) { 309 * // Handle the error 310 * cpo = null; 311 * } 312 * 313 * if (cpo!=null) { 314 * so.setId(1); 315 * so.setName("SomeName"); 316 * try{ 317 * cpo.insertObject("IDNameInsert",so); 318 * } catch (CpoException ce) { 319 * // Handle the error 320 * } 321 * } 322 * </code> 323 * </pre> 324 * 325 * @param name The String name of the CREATE Function Group that will be used to create the object in the datasource. 326 * null signifies that the default rules will be used which is equivalent to insertObject(Object obj); 327 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 328 * defined an exception will be thrown. 329 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 330 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 331 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 332 * text will be embedded at run-time 333 * @return The number of objects created in the datasource 334 * @throws CpoException Thrown if there are errors accessing the datasource 335 */ 336 @Override 337 public <T> long insertObject(String name, T obj, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 338 return processUpdateGroup(obj, JdbcCpoAdapter.CREATE_GROUP, name, wheres, orderBy, nativeExpressions); 339 } 340 341 /** 342 * Iterates through a collection of Objects, creates and stores them in the datasource. The assumption is that the 343 * objects contained in the collection do not exist in the datasource. 344 * 345 * This method creates and stores the objects in the datasource. The objects in the collection will be treated as one 346 * transaction, assuming the datasource supports transactions. 347 * 348 * This means that if one of the objects fail being created in the datasource then the CpoAdapter will stop processing 349 * the remainder of the collection and rollback all the objects created thus far. Rollback is on the underlying 350 * datasource's support of rollback. 351 * 352 * <pre>Example: 353 * <code> 354 * 355 * class SomeObject so = null; 356 * class CpoAdapter cpo = null; 357 * 358 * try { 359 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 360 * } catch (CpoException ce) { 361 * // Handle the error 362 * cpo = null; 363 * } 364 * 365 * if (cpo!=null) { 366 * ArrayList al = new ArrayList(); 367 * for (int i=0; i<3; i++){ 368 * so = new SomeObject(); 369 * so.setId(1); 370 * so.setName("SomeName"); 371 * al.add(so); 372 * } 373 * try{ 374 * cpo.insertObjects(al); 375 * } catch (CpoException ce) { 376 * // Handle the error 377 * } 378 * } 379 * </code> 380 * </pre> 381 * 382 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 383 * class is not defined an exception will be thrown. 384 * @return The number of objects created in the datasource 385 * @throws CpoException Thrown if there are errors accessing the datasource 386 */ 387 @Override 388 public <T> long insertObjects(Collection<T> coll) throws CpoException { 389 return processUpdateGroup(coll, JdbcCpoAdapter.CREATE_GROUP, null, null, null, null); 390 } 391 392 /** 393 * Iterates through a collection of Objects, creates and stores them in the datasource. The assumption is that the 394 * objects contained in the collection do not exist in the datasource. 395 * 396 * This method creates and stores the objects in the datasource. The objects in the collection will be treated as one 397 * transaction, assuming the datasource supports transactions. 398 * 399 * This means that if one of the objects fail being created in the datasource then the CpoAdapter should stop 400 * processing the remainder of the collection, and if supported, rollback all the objects created thus far. 401 * 402 * <pre>Example: 403 * <code> 404 * 405 * class SomeObject so = null; 406 * class CpoAdapter cpo = null; 407 * 408 * try { 409 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 410 * } catch (CpoException ce) { 411 * // Handle the error 412 * cpo = null; 413 * } 414 * if (cpo!=null) { 415 * ArrayList al = new ArrayList(); 416 * for (int i=0; i<3; i++){ 417 * so = new SomeObject(); 418 * so.setId(1); 419 * so.setName("SomeName"); 420 * al.add(so); 421 * } 422 * try{ 423 * cpo.insertObjects("IdNameInsert",al); 424 * } catch (CpoException ce) { 425 * // Handle the error 426 * } 427 * } 428 * </code> 429 * </pre> 430 * 431 * @param name The String name of the CREATE Function Group that will be used to create the object in the datasource. 432 * null signifies that the default rules will be used. 433 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 434 * class is not defined an exception will be thrown. 435 * @return The number of objects created in the datasource 436 * @throws CpoException Thrown if there are errors accessing the datasource 437 */ 438 @Override 439 public <T> long insertObjects(String name, Collection<T> coll) throws CpoException { 440 return processUpdateGroup(coll, JdbcCpoAdapter.CREATE_GROUP, name, null, null, null); 441 } 442 443 /** 444 * Iterates through a collection of Objects, creates and stores them in the datasource. The assumption is that the 445 * objects contained in the collection do not exist in the datasource. 446 * 447 * This method creates and stores the objects in the datasource. The objects in the collection will be treated as one 448 * transaction, assuming the datasource supports transactions. 449 * 450 * This means that if one of the objects fail being created in the datasource then the CpoAdapter should stop 451 * processing the remainder of the collection, and if supported, rollback all the objects created thus far. 452 * 453 * <pre>Example: 454 * <code> 455 * 456 * class SomeObject so = null; 457 * class CpoAdapter cpo = null; 458 * 459 * try { 460 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 461 * } catch (CpoException ce) { 462 * // Handle the error 463 * cpo = null; 464 * } 465 * if (cpo!=null) { 466 * ArrayList al = new ArrayList(); 467 * for (int i=0; i<3; i++){ 468 * so = new SomeObject(); 469 * so.setId(1); 470 * so.setName("SomeName"); 471 * al.add(so); 472 * } 473 * try{ 474 * cpo.insertObjects("IdNameInsert",al); 475 * } catch (CpoException ce) { 476 * // Handle the error 477 * } 478 * } 479 * </code> 480 * </pre> 481 * 482 * @param name The String name of the CREATE Function Group that will be used to create the object in the datasource. 483 * null signifies that the default rules will be used. 484 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 485 * class is not defined an exception will be thrown. 486 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 487 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 488 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 489 * text will be embedded at run-time 490 * @return The number of objects created in the datasource 491 * @throws CpoException Thrown if there are errors accessing the datasource 492 */ 493 @Override 494 public <T> long insertObjects(String name, Collection<T> coll, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 495 return processUpdateGroup(coll, JdbcCpoAdapter.CREATE_GROUP, name, wheres, orderBy, nativeExpressions); 496 } 497 498 /** 499 * Removes the Object from the datasource. The assumption is that the object exists in the datasource. This method 500 * stores the object in the datasource 501 * 502 * <pre>Example: 503 * <code> 504 * 505 * class SomeObject so = new SomeObject(); 506 * class CpoAdapter cpo = null; 507 * 508 * try { 509 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 510 * } catch (CpoException ce) { 511 * // Handle the error 512 * cpo = null; 513 * } 514 * 515 * if (cpo!=null) { 516 * so.setId(1); 517 * so.setName("SomeName"); 518 * try{ 519 * cpo.deleteObject(so); 520 * } catch (CpoException ce) { 521 * // Handle the error 522 * } 523 * } 524 * </code> 525 * </pre> 526 * 527 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 528 * defined an exception will be thrown. If the object does not exist in the datasource an exception will be thrown. 529 * @return The number of objects deleted from the datasource 530 * @throws CpoException Thrown if there are errors accessing the datasource 531 */ 532 @Override 533 public <T> long deleteObject(T obj) throws CpoException { 534 return processUpdateGroup(obj, JdbcCpoAdapter.DELETE_GROUP, null, null, null, null); 535 } 536 537 /** 538 * Removes the Object from the datasource. The assumption is that the object exists in the datasource. This method 539 * stores the object in the datasource 540 * 541 * <pre>Example: 542 * <code> 543 * 544 * class SomeObject so = new SomeObject(); 545 * class CpoAdapter cpo = null; 546 * 547 * try { 548 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 549 * } catch (CpoException ce) { 550 * // Handle the error 551 * cpo = null; 552 * } 553 * 554 * if (cpo!=null) { 555 * so.setId(1); 556 * so.setName("SomeName"); 557 * try{ 558 * cpo.deleteObject("DeleteById",so); 559 * } catch (CpoException ce) { 560 * // Handle the error 561 * } 562 * } 563 * </code> 564 * </pre> 565 * 566 * @param name The String name of the DELETE Function Group that will be used to create the object in the datasource. 567 * null signifies that the default rules will be used. 568 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 569 * defined an exception will be thrown. If the object does not exist in the datasource an exception will be thrown. 570 * @return The number of objects deleted from the datasource 571 * @throws CpoException Thrown if there are errors accessing the datasource 572 */ 573 @Override 574 public <T> long deleteObject(String name, T obj) throws CpoException { 575 return processUpdateGroup(obj, JdbcCpoAdapter.DELETE_GROUP, name, null, null, null); 576 } 577 578 /** 579 * Removes the Object from the datasource. The assumption is that the object exists in the datasource. This method 580 * stores the object in the datasource 581 * 582 * <pre>Example: 583 * <code> 584 * 585 * class SomeObject so = new SomeObject(); 586 * class CpoAdapter cpo = null; 587 * 588 * try { 589 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 590 * } catch (CpoException ce) { 591 * // Handle the error 592 * cpo = null; 593 * } 594 * 595 * if (cpo!=null) { 596 * so.setId(1); 597 * so.setName("SomeName"); 598 * try{ 599 * cpo.deleteObject("DeleteById",so); 600 * } catch (CpoException ce) { 601 * // Handle the error 602 * } 603 * } 604 * </code> 605 * </pre> 606 * 607 * @param name The String name of the DELETE Function Group that will be used to create the object in the datasource. 608 * null signifies that the default rules will be used. 609 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 610 * defined an exception will be thrown. If the object does not exist in the datasource an exception will be thrown. 611 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 612 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 613 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 614 * text will be embedded at run-time 615 * @return The number of objects deleted from the datasource 616 * @throws CpoException Thrown if there are errors accessing the datasource 617 */ 618 @Override 619 public <T> long deleteObject(String name, T obj, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 620 return processUpdateGroup(obj, JdbcCpoAdapter.DELETE_GROUP, name, wheres, orderBy, nativeExpressions); 621 } 622 623 /** 624 * Removes the Objects contained in the collection from the datasource. The assumption is that the object exists in 625 * the datasource. This method stores the objects contained in the collection in the datasource. The objects in the 626 * collection will be treated as one transaction, assuming the datasource supports transactions. 627 * 628 * This means that if one of the objects fail being deleted in the datasource then the CpoAdapter should stop 629 * processing the remainder of the collection, and if supported, rollback all the objects deleted thus far. 630 * 631 * <pre>Example: 632 * <code> 633 * 634 * class SomeObject so = null; 635 * class CpoAdapter cpo = null; 636 * 637 * try { 638 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 639 * } catch (CpoException ce) { 640 * // Handle the error 641 * cpo = null; 642 * } 643 * 644 * if (cpo!=null) { 645 * ArrayList al = new ArrayList(); 646 * for (int i=0; i<3; i++){ 647 * so = new SomeObject(); 648 * so.setId(1); 649 * so.setName("SomeName"); 650 * al.add(so); 651 * } 652 * try{ 653 * cpo.deleteObjects(al); 654 * } catch (CpoException ce) { 655 * // Handle the error 656 * } 657 * } 658 * </code> 659 * </pre> 660 * 661 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 662 * class is not defined an exception will be thrown. 663 * @return The number of objects deleted from the datasource 664 * @throws CpoException Thrown if there are errors accessing the datasource 665 */ 666 @Override 667 public <T> long deleteObjects(Collection<T> coll) throws CpoException { 668 return processUpdateGroup(coll, JdbcCpoAdapter.DELETE_GROUP, null, null, null, null); 669 } 670 671 /** 672 * Removes the Objects contained in the collection from the datasource. The assumption is that the object exists in 673 * the datasource. This method stores the objects contained in the collection in the datasource. The objects in the 674 * collection will be treated as one transaction, assuming the datasource supports transactions. 675 * 676 * This means that if one of the objects fail being deleted in the datasource then the CpoAdapter should stop 677 * processing the remainder of the collection, and if supported, rollback all the objects deleted thus far. 678 * 679 * <pre>Example: 680 * <code> 681 * 682 * class SomeObject so = null; 683 * class CpoAdapter cpo = null; 684 * 685 * try { 686 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 687 * } catch (CpoException ce) { 688 * // Handle the error 689 * cpo = null; 690 * } 691 * 692 * if (cpo!=null) { 693 * ArrayList al = new ArrayList(); 694 * for (int i=0; i<3; i++){ 695 * so = new SomeObject(); 696 * so.setId(1); 697 * so.setName("SomeName"); 698 * al.add(so); 699 * } 700 * 701 * try{ 702 * cpo.deleteObjects("IdNameDelete",al); 703 * } catch (CpoException ce) { 704 * // Handle the error 705 * } 706 * } 707 * </code> 708 * </pre> 709 * 710 * @param name The String name of the DELETE Function Group that will be used to create the object in the datasource. 711 * null signifies that the default rules will be used. 712 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 713 * class is not defined an exception will be thrown. 714 * @return The number of objects deleted from the datasource 715 * @throws CpoException Thrown if there are errors accessing the datasource 716 */ 717 @Override 718 public <T> long deleteObjects(String name, Collection<T> coll) throws CpoException { 719 return processUpdateGroup(coll, JdbcCpoAdapter.DELETE_GROUP, name, null, null, null); 720 } 721 722 /** 723 * Removes the Objects contained in the collection from the datasource. The assumption is that the object exists in 724 * the datasource. This method stores the objects contained in the collection in the datasource. The objects in the 725 * collection will be treated as one transaction, assuming the datasource supports transactions. 726 * 727 * This means that if one of the objects fail being deleted in the datasource then the CpoAdapter should stop 728 * processing the remainder of the collection, and if supported, rollback all the objects deleted thus far. 729 * 730 * <pre>Example: 731 * <code> 732 * 733 * class SomeObject so = null; 734 * class CpoAdapter cpo = null; 735 * 736 * try { 737 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 738 * } catch (CpoException ce) { 739 * // Handle the error 740 * cpo = null; 741 * } 742 * 743 * if (cpo!=null) { 744 * ArrayList al = new ArrayList(); 745 * for (int i=0; i<3; i++){ 746 * so = new SomeObject(); 747 * so.setId(1); 748 * so.setName("SomeName"); 749 * al.add(so); 750 * } 751 * 752 * try{ 753 * cpo.deleteObjects("IdNameDelete",al); 754 * } catch (CpoException ce) { 755 * // Handle the error 756 * } 757 * } 758 * </code> 759 * </pre> 760 * 761 * @param name The String name of the DELETE Function Group that will be used to create the object in the datasource. 762 * null signifies that the default rules will be used. 763 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 764 * class is not defined an exception will be thrown. 765 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 766 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 767 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 768 * text will be embedded at run-time 769 * @return The number of objects deleted from the datasource 770 * @throws CpoException Thrown if there are errors accessing the datasource 771 */ 772 @Override 773 public <T> long deleteObjects(String name, Collection<T> coll, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 774 return processUpdateGroup(coll, JdbcCpoAdapter.DELETE_GROUP, name, wheres, orderBy, nativeExpressions); 775 } 776 777 /** 778 * Executes an Object whose metadata will call an executable within the datasource. It is assumed that the executable 779 * object exists in the metadatasource. If the executable does not exist, an exception will be thrown. 780 * 781 * <pre>Example: 782 * <code> 783 * 784 * class SomeObject so = new SomeObject(); 785 * class CpoAdapter cpo = null; 786 * 787 * try { 788 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 789 * } catch (CpoException ce) { 790 * // Handle the error 791 * cpo = null; 792 * } 793 * 794 * if (cpo!=null) { 795 * so.setId(1); 796 * so.setName("SomeName"); 797 * try{ 798 * cpo.executeObject(so); 799 * } catch (CpoException ce) { 800 * // Handle the error 801 * } 802 * } 803 * </code> 804 * </pre> 805 * 806 * @param object This is an Object that has been defined within the metadata of the datasource. If the class is not 807 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 808 * This object is used to populate the IN arguments used to executed the datasource object. 809 * 810 * An object of this type will be created and filled with the returned data from the value_object. This newly created 811 * object will be returned from this method. 812 * @return An object populated with the OUT arguments returned from the executable object 813 * @throws CpoException Thrown if there are errors accessing the datasource 814 */ 815 @Override 816 public <T> T executeObject(T object) throws CpoException { 817 return processExecuteGroup(null, object, object); 818 } 819 820 /** 821 * Executes an Object whose metadata will call an executable within the datasource. It is assumed that the executable 822 * object exists in the metadatasource. If the executable does not exist, an exception will be thrown. 823 * 824 * <pre>Example: 825 * <code> 826 * 827 * class SomeObject so = new SomeObject(); 828 * class CpoAdapter cpo = null; 829 * 830 * try { 831 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 832 * } catch (CpoException ce) { 833 * // Handle the error 834 * cpo = null; 835 * } 836 * 837 * if (cpo!=null) { 838 * so.setId(1); 839 * so.setName("SomeName"); 840 * try{ 841 * cpo.executeObject("execNotifyProc",so); 842 * } catch (CpoException ce) { 843 * // Handle the error 844 * } 845 * } 846 * </code> 847 * </pre> 848 * 849 * @param name The filter name which tells the datasource which objects should be returned. The name also signifies 850 * what data in the object will be populated. 851 * @param object This is an object that has been defined within the metadata of the datasource. If the class is not 852 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 853 * This object is used to populate the IN arguments used to retrieve the collection of objects. This object defines 854 * the object type that will be returned in the collection and contain the result set data or the OUT Parameters. 855 * @return A result object populate with the OUT arguments 856 * @throws CpoException if there are errors accessing the datasource 857 */ 858 @Override 859 public <T> T executeObject(String name, T object) throws CpoException { 860 return processExecuteGroup(name, object, object); 861 } 862 863 /** 864 * Executes an Object that represents an executable object within the datasource. It is assumed that the object exists 865 * in the datasource. If the object does not exist, an exception will be thrown 866 * 867 * <pre>Example: 868 * <code> 869 * 870 * class SomeObject so = new SomeObject(); 871 * class SomeResult sr = new SomeResult(); 872 * class CpoAdapter cpo = null; 873 * 874 * try { 875 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 876 * } catch (CpoException ce) { 877 * // Handle the error 878 * cpo = null; 879 * } 880 * 881 * if (cpo!=null) { 882 * so.setId(1); 883 * so.setName("SomeName"); 884 * try{ 885 * sr = (SomeResult)cpo.executeObject("execNotifyProc",so, sr); 886 * } catch (CpoException ce) { 887 * // Handle the error 888 * } 889 * } 890 * </code> 891 * </pre> 892 * 893 * @param name The String name of the EXECUTE Function Group that will be used to create the object in the datasource. 894 * null signifies that the default rules will be used. 895 * @param criteria This is an object that has been defined within the metadata of the datasource. If the class is not 896 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 897 * This object is used to populate the IN arguments used to retrieve the collection of objects. 898 * @param result This is an object that has been defined within the metadata of the datasource. If the class is not 899 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 900 * This object defines the object type that will be created, filled with the return data and returned from this 901 * method. 902 * @return An object populated with the out arguments 903 * @throws CpoException Thrown if there are errors accessing the datasource 904 */ 905 @Override 906 public <T, C> T executeObject(String name, C criteria, T result) throws CpoException { 907 return processExecuteGroup(name, criteria, result); 908 } 909 910 /** 911 * The CpoAdapter will check to see if this object exists in the datasource. 912 * 913 * <pre>Example: 914 * <code> 915 * 916 * class SomeObject so = new SomeObject(); 917 * long count = 0; 918 * class CpoAdapter cpo = null; 919 * 920 * try { 921 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 922 * } catch (CpoException ce) { 923 * // Handle the error 924 * cpo = null; 925 * } 926 * 927 * if (cpo!=null) { 928 * so.setId(1); 929 * so.setName("SomeName"); 930 * try{ 931 * count = cpo.existsObject(so); 932 * if (count>0) { 933 * // object exists 934 * } else { 935 * // object does not exist 936 * } 937 * } catch (CpoException ce) { 938 * // Handle the error 939 * } 940 * } 941 * </code> 942 * </pre> 943 * 944 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 945 * defined an exception will be thrown. This object will be searched for inside the datasource. 946 * @return The number of objects that exist in the datasource that match the specified object 947 * @throws CpoException Thrown if there are errors accessing the datasource 948 */ 949 @Override 950 public <T> long existsObject(T obj) throws CpoException { 951 return this.existsObject(null, obj); 952 } 953 954 /** 955 * The CpoAdapter will check to see if this object exists in the datasource. 956 * 957 * <pre>Example: 958 * <code> 959 * 960 * class SomeObject so = new SomeObject(); 961 * long count = 0; 962 * class CpoAdapter cpo = null; 963 * 964 * try { 965 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 966 * } catch (CpoException ce) { 967 * // Handle the error 968 * cpo = null; 969 * } 970 * 971 * if (cpo!=null) { 972 * so.setId(1); 973 * so.setName("SomeName"); 974 * try{ 975 * count = cpo.existsObject("SomeExistCheck",so); 976 * if (count>0) { 977 * // object exists 978 * } else { 979 * // object does not exist 980 * } 981 * } catch (CpoException ce) { 982 * // Handle the error 983 * } 984 * } 985 * </code> 986 * </pre> 987 * 988 * @param name The String name of the EXISTS Function Group that will be used to create the object in the datasource. 989 * null signifies that the default rules will be used. 990 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 991 * defined an exception will be thrown. This object will be searched for inside the datasource. 992 * @return The number of objects that exist in the datasource that match the specified object 993 * @throws CpoException Thrown if there are errors accessing the datasource 994 */ 995 @Override 996 public <T> long existsObject(String name, T obj) throws CpoException { 997 return this.existsObject(name, obj, null); 998 } 999 1000 /** 1001 * The CpoAdapter will check to see if this object exists in the datasource. 1002 * 1003 * <pre>Example: 1004 * <code> 1005 * 1006 * class SomeObject so = new SomeObject(); 1007 * long count = 0; 1008 * class CpoAdapter cpo = null; 1009 * 1010 * 1011 * try { 1012 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1013 * } catch (CpoException ce) { 1014 * // Handle the error 1015 * cpo = null; 1016 * } 1017 * 1018 * if (cpo!=null) { 1019 * so.setId(1); 1020 * so.setName("SomeName"); 1021 * try{ 1022 * CpoWhere where = cpo.newCpoWhere(CpoWhere.LOGIC_NONE, id, CpoWhere.COMP_EQ); 1023 * count = cpo.existsObject("SomeExistCheck",so, where); 1024 * if (count>0) { 1025 * // object exists 1026 * } else { 1027 * // object does not exist 1028 * } 1029 * } catch (CpoException ce) { 1030 * // Handle the error 1031 * } 1032 * } 1033 * </code> 1034 * </pre> 1035 * 1036 * @param name The String name of the EXISTS Function Group that will be used to create the object in the datasource. 1037 * null signifies that the default rules will be used. 1038 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1039 * defined an exception will be thrown. This object will be searched for inside the datasource. 1040 * @param wheres A CpoWhere object that passes in run-time constraints to the function that performs the the exist 1041 * @return The number of objects that exist in the datasource that match the specified object 1042 * @throws CpoException Thrown if there are errors accessing the datasource 1043 */ 1044 @Override 1045 public <T> long existsObject(String name, T obj, Collection<CpoWhere> wheres) throws CpoException { 1046 Connection c = null; 1047 long objCount = -1; 1048 1049 try { 1050 c = getReadConnection(); 1051 1052 objCount = existsObject(name, obj, c, wheres); 1053 } catch (Exception e) { 1054 throw new CpoException("existsObjects(String, Object) failed", e); 1055 } finally { 1056 closeConnection(c); 1057 } 1058 1059 return objCount; 1060 } 1061 1062 /** 1063 * The CpoAdapter will check to see if this object exists in the datasource. 1064 * 1065 * @param name The name which identifies which EXISTS, INSERT, and UPDATE Function Groups to execute to persist the 1066 * object. 1067 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1068 * defined an exception will be thrown. 1069 * @param con The datasource Connection with which to check if the object exists 1070 * @return The int value of the first column returned in the record set 1071 * @throws CpoException exception will be thrown if the Function Group has a function count != 1 1072 */ 1073 protected <T> long existsObject(String name, T obj, Connection con, Collection<CpoWhere> wheres) throws CpoException { 1074 PreparedStatement ps = null; 1075 ResultSet rs = null; 1076 ResultSetMetaData rsmd; 1077 CpoClass cpoClass; 1078 long objCount = 0; 1079 Logger localLogger = logger; 1080 1081 if (obj == null) { 1082 throw new CpoException("NULL Object passed into existsObject"); 1083 } 1084 1085 try { 1086 cpoClass = metaDescriptor.getMetaClass(obj); 1087 List<CpoFunction> cpoFunctions = cpoClass.getFunctionGroup(JdbcCpoAdapter.EXIST_GROUP, name).getFunctions(); 1088 localLogger = LoggerFactory.getLogger(cpoClass.getMetaClass()); 1089 1090 for (CpoFunction cpoFunction : cpoFunctions) { 1091 localLogger.info(cpoFunction.getExpression()); 1092 JdbcPreparedStatementFactory jpsf = new JdbcPreparedStatementFactory(con, this, cpoClass, cpoFunction, obj, wheres, null, null); 1093 ps = jpsf.getPreparedStatement(); 1094 1095 long qCount = 0; // set the results for this function to 0 1096 1097 rs = ps.executeQuery(); 1098 jpsf.release(); 1099 rsmd = rs.getMetaData(); 1100 1101 // see if they are using the count(*) logic 1102 if (rsmd.getColumnCount() == 1) { 1103 if (rs.next()) { 1104 try { 1105 qCount = rs.getLong(1); // get the number of objects 1106 // that exist 1107 } catch (Exception e) { 1108 // Exists result not an int so bail to record counter 1109 qCount = 1; 1110 } 1111 if (rs.next()) { 1112 // EXIST function has more than one record so not a count(*) 1113 qCount = 2; 1114 } 1115 } 1116 } 1117 1118 while (rs.next()) { 1119 qCount++; 1120 } 1121 1122 objCount += qCount; 1123 1124 rs.close(); 1125 ps.close(); 1126 rs = null; 1127 ps = null; 1128 } 1129 } catch (SQLException e) { 1130 String msg = "existsObject(name, obj, con) failed:"; 1131 localLogger.error(msg, e); 1132 throw new CpoException(msg, e); 1133 } finally { 1134 resultSetClose(rs); 1135 statementClose(ps); 1136 } 1137 1138 return objCount; 1139 } 1140 1141 /** 1142 * newOrderBy allows you to dynamically change the order of the objects in the resulting collection. This allows you 1143 * to apply user input in determining the order of the collection 1144 * 1145 * @param attribute The name of the attribute from the pojo that will be sorted. 1146 * @param ascending If true, sort ascending. If false sort descending. 1147 * @return A CpoOrderBy object to be passed into retrieveBeans. 1148 * @throws CpoException Thrown if there are errors accessing the datasource 1149 */ 1150 @Override 1151 public CpoOrderBy newOrderBy(String attribute, boolean ascending) throws CpoException { 1152 return new JdbcCpoOrderBy(attribute, ascending); 1153 } 1154 1155 /** 1156 * newOrderBy allows you to dynamically change the order of the objects in the resulting collection. This allows you 1157 * to apply user input in determining the order of the collection 1158 * 1159 * @param marker the marker that will be replaced in the expression with the string representation of this orderBy 1160 * @param attribute The name of the attribute from the pojo that will be sorted. 1161 * @param ascending If true, sort ascending. If false sort descending. 1162 * @return A CpoOrderBy object to be passed into retrieveBeans. 1163 * @throws CpoException Thrown if there are errors accessing the datasource 1164 */ 1165 @Override 1166 public CpoOrderBy newOrderBy(String marker, String attribute, boolean ascending) throws CpoException { 1167 return new JdbcCpoOrderBy(marker, attribute, ascending); 1168 } 1169 1170 /** 1171 * newOrderBy allows you to dynamically change the order of the objects in the resulting collection. This allows you 1172 * to apply user input in determining the order of the collection 1173 * 1174 * @param attribute The name of the attribute from the pojo that will be sorted. 1175 * @param ascending If true, sort ascending. If false sort descending. 1176 * @param function A string which represents a datasource function that will be called on the attribute. must be 1177 * contained in the function string. The attribute name will be replaced at run-time with its datasource counterpart 1178 * @return A CpoOrderBy object to be passed into retrieveBeans. 1179 * @throws CpoException Thrown if there are errors accessing the datasource 1180 */ 1181 @Override 1182 public CpoOrderBy newOrderBy(String attribute, boolean ascending, String function) throws CpoException { 1183 return new JdbcCpoOrderBy(attribute, ascending, function); 1184 } 1185 1186 /** 1187 * newOrderBy allows you to dynamically change the order of the objects in the resulting collection. This allows you 1188 * to apply user input in determining the order of the collection 1189 * 1190 * @param marker the marker that will be replaced in the expression with the string representation of this orderBy 1191 * @param attribute The name of the attribute from the pojo that will be sorted. 1192 * @param ascending If true, sort ascending. If false sort descending. 1193 * @param function A string which represents a datasource function that will be called on the attribute. must be 1194 * contained in the function string. The attribute name will be replaced at run-time with its datasource counterpart 1195 * @return A CpoOrderBy object to be passed into retrieveBeans. 1196 * @throws CpoException Thrown if there are errors accessing the datasource 1197 */ 1198 @Override 1199 public CpoOrderBy newOrderBy(String marker, String attribute, boolean ascending, String function) throws CpoException { 1200 return new JdbcCpoOrderBy(marker, attribute, ascending, function); 1201 } 1202 1203 /** 1204 * DOCUMENT ME! 1205 * 1206 * @return DOCUMENT ME! 1207 * @throws CpoException DOCUMENT ME! 1208 */ 1209 @Override 1210 public CpoWhere newWhere() throws CpoException { 1211 return new JdbcCpoWhere(); 1212 } 1213 1214 /** 1215 * DOCUMENT ME! 1216 * 1217 * @param logical DOCUMENT ME! 1218 * @param attr DOCUMENT ME! 1219 * @param comp DOCUMENT ME! 1220 * @param value DOCUMENT ME! 1221 * @return DOCUMENT ME! 1222 * @throws CpoException DOCUMENT ME! 1223 */ 1224 @Override 1225 public <T> CpoWhere newWhere(int logical, String attr, int comp, T value) throws CpoException { 1226 return new JdbcCpoWhere(logical, attr, comp, value); 1227 } 1228 1229 /** 1230 * DOCUMENT ME! 1231 * 1232 * @param logical DOCUMENT ME! 1233 * @param attr DOCUMENT ME! 1234 * @param comp DOCUMENT ME! 1235 * @param value DOCUMENT ME! 1236 * @param not DOCUMENT ME! 1237 * @return DOCUMENT ME! 1238 * @throws CpoException DOCUMENT ME! 1239 */ 1240 @Override 1241 public <T> CpoWhere newWhere(int logical, String attr, int comp, T value, boolean not) throws CpoException { 1242 return new JdbcCpoWhere(logical, attr, comp, value, not); 1243 } 1244 1245 /** 1246 * Persists the Object into the datasource. The CpoAdapter will check to see if this object exists in the datasource. 1247 * If it exists, the object is updated in the datasource If the object does not exist, then it is created in the 1248 * datasource. This method stores the object in the datasource. This method uses the default EXISTS, CREATE, and 1249 * UPDATE Function Groups specified for this object. 1250 * 1251 * <pre>Example: 1252 * <code> 1253 * 1254 * class SomeObject so = new SomeObject(); 1255 * class CpoAdapter cpo = null; 1256 * 1257 * try { 1258 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1259 * } catch (CpoException ce) { 1260 * // Handle the error 1261 * cpo = null; 1262 * } 1263 * 1264 * if (cpo!=null) { 1265 * so.setId(1); 1266 * so.setName("SomeName"); 1267 * try{ 1268 * cpo.persistObject(so); 1269 * } catch (CpoException ce) { 1270 * // Handle the error 1271 * } 1272 * } 1273 * </code> 1274 * </pre> 1275 * 1276 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1277 * defined an exception will be thrown. 1278 * @return A count of the number of objects persisted 1279 * @throws CpoException Thrown if there are errors accessing the datasource 1280 * @see #existsObject 1281 * @see #insertObject 1282 * @see #updateObject 1283 */ 1284 @Override 1285 public <T> long persistObject(T obj) throws CpoException { 1286 return processUpdateGroup(obj, JdbcCpoAdapter.PERSIST_GROUP, null, null, null, null); 1287 } 1288 1289 /** 1290 * Persists the Object into the datasource. The CpoAdapter will check to see if this object exists in the datasource. 1291 * If it exists, the object is updated in the datasource If the object does not exist, then it is created in the 1292 * datasource. This method stores the object in the datasource. 1293 * 1294 * <pre>Example: 1295 * <code> 1296 * 1297 * class SomeObject so = new SomeObject(); 1298 * class CpoAdapter cpo = null; 1299 * 1300 * try { 1301 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1302 * } catch (CpoException ce) { 1303 * // Handle the error 1304 * cpo = null; 1305 * } 1306 * 1307 * if (cpo!=null) { 1308 * so.setId(1); 1309 * so.setName("SomeName"); 1310 * try{ 1311 * cpo.persistObject("persistSomeObject",so); 1312 * } catch (CpoException ce) { 1313 * // Handle the error 1314 * } 1315 * } 1316 * </code> 1317 * </pre> 1318 * 1319 * @param name The name which identifies which EXISTS, INSERT, and UPDATE Function Groups to execute to persist the 1320 * object. 1321 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1322 * defined an exception will be thrown. 1323 * @return A count of the number of objects persisted 1324 * @throws CpoException Thrown if there are errors accessing the datasource 1325 * @see #existsObject 1326 * @see #insertObject 1327 * @see #updateObject 1328 */ 1329 @Override 1330 public <T> long persistObject(String name, T obj) throws CpoException { 1331 return processUpdateGroup(obj, JdbcCpoAdapter.PERSIST_GROUP, name, null, null, null); 1332 } 1333 1334 /** 1335 * Persists a collection of Objects into the datasource. The CpoAdapter will check to see if this object exists in the 1336 * datasource. If it exists, the object is updated in the datasource If the object does not exist, then it is created 1337 * in the datasource. This method stores the object in the datasource. The objects in the collection will be treated 1338 * as one transaction, meaning that if one of the objects fail being inserted or updated in the datasource then the 1339 * entire collection will be rolled back. 1340 * 1341 * <pre>Example: 1342 * <code> 1343 * 1344 * class SomeObject so = null; 1345 * class CpoAdapter cpo = null; 1346 * 1347 * try { 1348 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1349 * } catch (CpoException ce) { 1350 * // Handle the error 1351 * cpo = null; 1352 * } 1353 * 1354 * if (cpo!=null) { 1355 * ArrayList al = new ArrayList(); 1356 * for (int i=0; i<3; i++){ 1357 * so = new SomeObject(); 1358 * so.setId(1); 1359 * so.setName("SomeName"); 1360 * al.add(so); 1361 * } 1362 * try{ 1363 * cpo.persistObjects(al); 1364 * } catch (CpoException ce) { 1365 * // Handle the error 1366 * } 1367 * } 1368 * </code> 1369 * </pre> 1370 * 1371 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 1372 * class is not defined an exception will be thrown. 1373 * @return DOCUMENT ME! 1374 * @throws CpoException Thrown if there are errors accessing the datasource 1375 * @see #existsObject 1376 * @see #insertObject 1377 * @see #updateObject 1378 */ 1379 @Override 1380 public <T> long persistObjects(Collection<T> coll) throws CpoException { 1381 return processUpdateGroup(coll, JdbcCpoAdapter.PERSIST_GROUP, null, null, null, null); 1382 } 1383 1384 /** 1385 * Persists a collection of Objects into the datasource. The CpoAdapter will check to see if this object exists in the 1386 * datasource. If it exists, the object is updated in the datasource If the object does not exist, then it is created 1387 * in the datasource. This method stores the object in the datasource. The objects in the collection will be treated 1388 * as one transaction, meaning that if one of the objects fail being inserted or updated in the datasource then the 1389 * entire collection will be rolled back. 1390 * 1391 * <pre>Example: 1392 * <code> 1393 * 1394 * class SomeObject so = null; 1395 * class CpoAdapter cpo = null; 1396 * 1397 * try { 1398 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1399 * } catch (CpoException ce) { 1400 * // Handle the error 1401 * cpo = null; 1402 * } 1403 * 1404 * if (cpo!=null) { 1405 * ArrayList al = new ArrayList(); 1406 * for (int i=0; i<3; i++){ 1407 * so = new SomeObject(); 1408 * so.setId(1); 1409 * so.setName("SomeName"); 1410 * al.add(so); 1411 * } 1412 * try{ 1413 * cpo.persistObjects("myPersist",al); 1414 * } catch (CpoException ce) { 1415 * // Handle the error 1416 * } 1417 * } 1418 * </code> 1419 * </pre> 1420 * 1421 * @param name The name which identifies which EXISTS, INSERT, and UPDATE Function Groups to execute to persist the 1422 * object. 1423 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 1424 * class is not defined an exception will be thrown. 1425 * @return DOCUMENT ME! 1426 * @throws CpoException Thrown if there are errors accessing the datasource 1427 * @see #existsObject 1428 * @see #insertObject 1429 * @see #updateObject 1430 */ 1431 @Override 1432 public <T> long persistObjects(String name, Collection<T> coll) throws CpoException { 1433 return processUpdateGroup(coll, JdbcCpoAdapter.PERSIST_GROUP, name, null, null, null); 1434 } 1435 1436 /** 1437 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. If the retrieve 1438 * function defined for this beans returns more than one row, an exception will be thrown. 1439 * 1440 * @param bean This is an bean that has been defined within the metadata of the datasource. If the class is not 1441 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. The 1442 * input bean is used to specify the search criteria, the output bean is populated with the results of the function. 1443 * @return An bean of the same type as the result argument that is filled in as specified the metadata for the 1444 * retireve. 1445 * @throws CpoException Thrown if there are errors accessing the datasource 1446 */ 1447 @Override 1448 public <T> T retrieveBean(T bean) throws CpoException { 1449 T o = processSelectGroup(bean, null, null, null, null); 1450 1451 return (o); 1452 } 1453 1454 /** 1455 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. If the retrieve 1456 * function defined for this beans returns more than one row, an exception will be thrown. 1457 * 1458 * @param name DOCUMENT ME! 1459 * @param bean This is an bean that has been defined within the metadata of the datasource. If the class is not 1460 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. The 1461 * input bean is used to specify the search criteria, the output bean is populated with the results of the function. 1462 * @return An bean of the same type as the result argument that is filled in as specified the metadata for the 1463 * retireve. 1464 * @throws CpoException Thrown if there are errors accessing the datasource 1465 */ 1466 @Override 1467 public <T> T retrieveBean(String name, T bean) throws CpoException { 1468 T o = processSelectGroup(bean, name, null, null, null); 1469 1470 return (o); 1471 } 1472 1473 /** 1474 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. If the retrieve 1475 * function defined for this beans returns more than one row, an exception will be thrown. 1476 * 1477 * @param name DOCUMENT ME! 1478 * @param bean This is an bean that has been defined within the metadata of the datasource. If the class is not 1479 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. The 1480 * input bean is used to specify the search criteria, the output bean is populated with the results of the function. 1481 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1482 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1483 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 1484 * text will be embedded at run-time 1485 * @return An bean of the same type as the result argument that is filled in as specified the metadata for the 1486 * retireve. 1487 * @throws CpoException Thrown if there are errors accessing the datasource 1488 */ 1489 @Override 1490 public <T> T retrieveBean(String name, T bean, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 1491 T o = processSelectGroup(bean, name, wheres, orderBy, nativeExpressions); 1492 1493 return (o); 1494 } 1495 1496 /** 1497 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. If the retrieve 1498 * function defined for this beans returns more than one row, an exception will be thrown. 1499 * 1500 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1501 * data in the bean will be populated. 1502 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1503 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1504 * This bean is used to specify the arguments used to retrieve the collection of beans. 1505 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1506 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1507 * This bean is used to specify the bean type that will be returned in the collection. 1508 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1509 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1510 * @return An bean of the same type as the result argument that is filled in as specified the metadata for the 1511 * retireve. 1512 * @throws CpoException Thrown if there are errors accessing the datasource 1513 */ 1514 @Override 1515 public <T, C> T retrieveBean(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy) throws CpoException { 1516 return retrieveBean(name, criteria, result, wheres, orderBy, null); 1517 } 1518 1519 /** 1520 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. If the retrieve 1521 * function defined for this beans returns more than one row, an exception will be thrown. 1522 * 1523 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1524 * data in the bean will be populated. 1525 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1526 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1527 * This bean is used to specify the arguments used to retrieve the collection of beans. 1528 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1529 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1530 * This bean is used to specify the bean type that will be returned in the collection. 1531 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1532 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1533 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 1534 * text will be embedded at run-time 1535 * @return An bean of the same type as the result argument that is filled in as specified the metadata for the 1536 * retireve. 1537 * @throws CpoException Thrown if there are errors accessing the datasource 1538 */ 1539 @Override 1540 public <T, C> T retrieveBean(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 1541 Iterator<T> it = processSelectGroup(name, criteria, result, wheres, orderBy, nativeExpressions, true).iterator(); 1542 if (it.hasNext()) { 1543 return it.next(); 1544 } else { 1545 return null; 1546 } 1547 } 1548 1549 /** 1550 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1551 * 1552 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1553 * data in the bean will be populated. 1554 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1555 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1556 * This bean is used to specify the arguments used to retrieve the collection of beans. 1557 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1558 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1559 * @throws CpoException Thrown if there are errors accessing the datasource 1560 */ 1561 @Override 1562 public <C> List<C> retrieveBeans(String name, C criteria) throws CpoException { 1563 return processSelectGroup(name, criteria, criteria, null, null, null, false); 1564 } 1565 1566 /** 1567 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1568 * 1569 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1570 * data in the bean will be populated. 1571 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1572 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1573 * This bean is used to specify the arguments used to retrieve the collection of beans. 1574 * @param where A CpoWhere bean that defines the constraints that should be used when retrieving beans 1575 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1576 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1577 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1578 * @throws CpoException Thrown if there are errors accessing the datasource 1579 */ 1580 @Override 1581 public <C> List<C> retrieveBeans(String name, C criteria, CpoWhere where, Collection<CpoOrderBy> orderBy) throws CpoException { 1582 ArrayList<CpoWhere> wheres = null; 1583 if (where != null) { 1584 wheres = new ArrayList<CpoWhere>(); 1585 wheres.add(where); 1586 } 1587 return processSelectGroup(name, criteria, criteria, wheres, orderBy, null, false); 1588 } 1589 1590 /** 1591 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1592 * 1593 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1594 * data in the bean will be populated. 1595 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1596 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1597 * This bean is used to specify the arguments used to retrieve the collection of beans. 1598 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1599 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1600 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1601 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1602 * @throws CpoException Thrown if there are errors accessing the datasource 1603 */ 1604 @Override 1605 public <C> List<C> retrieveBeans(String name, C criteria, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy) throws CpoException { 1606 return processSelectGroup(name, criteria, criteria, wheres, orderBy, null, false); 1607 } 1608 1609 /** 1610 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1611 * 1612 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1613 * data in the bean will be populated. 1614 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1615 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1616 * This bean is used to specify the arguments used to retrieve the collection of beans. 1617 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1618 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1619 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1620 * @throws CpoException Thrown if there are errors accessing the datasource 1621 */ 1622 @Override 1623 public <C> List<C> retrieveBeans(String name, C criteria, Collection<CpoOrderBy> orderBy) throws CpoException { 1624 return processSelectGroup(name, criteria, criteria, null, orderBy, null, false); 1625 } 1626 1627 /** 1628 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1629 * 1630 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1631 * data in the bean will be populated. 1632 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1633 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1634 * This bean is used to specify the arguments used to retrieve the collection of beans. 1635 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1636 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1637 * This bean is used to specify the bean type that will be returned in the collection. 1638 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1639 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1640 * @throws CpoException Thrown if there are errors accessing the datasource 1641 */ 1642 @Override 1643 public <T, C> List<T> retrieveBeans(String name, C criteria, T result) throws CpoException { 1644 return processSelectGroup(name, criteria, result, null, null, null, false); 1645 } 1646 1647 /** 1648 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1649 * 1650 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1651 * data in the bean will be populated. 1652 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1653 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1654 * This bean is used to specify the arguments used to retrieve the collection of beans. 1655 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1656 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1657 * This bean is used to specify the bean type that will be returned in the collection. 1658 * @param where A CpoWhere bean that defines the constraints that should be used when retrieving beans 1659 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1660 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1661 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1662 * @throws CpoException Thrown if there are errors accessing the datasource 1663 */ 1664 @Override 1665 public <T, C> List<T> retrieveBeans(String name, C criteria, T result, CpoWhere where, Collection<CpoOrderBy> orderBy) throws CpoException { 1666 ArrayList<CpoWhere> wheres = null; 1667 if (where != null) { 1668 wheres = new ArrayList<CpoWhere>(); 1669 wheres.add(where); 1670 } 1671 return processSelectGroup(name, criteria, result, wheres, orderBy, null, false); 1672 } 1673 1674 /** 1675 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1676 * 1677 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1678 * data in the bean will be populated. 1679 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1680 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1681 * This bean is used to specify the arguments used to retrieve the collection of beans. 1682 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1683 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1684 * This bean is used to specify the bean type that will be returned in the collection. 1685 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1686 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1687 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1688 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1689 * @throws CpoException Thrown if there are errors accessing the datasource 1690 */ 1691 @Override 1692 public <T, C> List<T> retrieveBeans(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy) throws CpoException { 1693 return processSelectGroup(name, criteria, result, wheres, orderBy, null, false); 1694 } 1695 1696 /** 1697 * Retrieves the bean from the datasource. The assumption is that the bean exists in the datasource. 1698 * 1699 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1700 * data in the bean will be populated. 1701 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1702 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1703 * This bean is used to specify the arguments used to retrieve the collection of beans. 1704 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1705 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1706 * This bean is used to specify the bean type that will be returned in the collection. 1707 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1708 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1709 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 1710 * text will be embedded at run-time 1711 * @return A collection of beans will be returned that meet the criteria specified by obj. The beans will be of the 1712 * same type as the bean that was passed in. If no beans match the criteria, an empty collection will be returned 1713 * @throws CpoException Thrown if there are errors accessing the datasource 1714 */ 1715 @Override 1716 public <T, C> List<T> retrieveBeans(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 1717 return processSelectGroup(name, criteria, result, wheres, orderBy, nativeExpressions, false); 1718 } 1719 1720 /** 1721 * Retrieves the bean from the datasource. This method returns an Iterator immediately. The iterator will get filled 1722 * asynchronously by the cpo framework. The framework will stop supplying the iterator with beans if the 1723 * beanBufferSize is reached. 1724 * 1725 * If the consumer of the iterator is processing records faster than the framework is filling it, then the iterator 1726 * will wait until it has data to provide. 1727 * 1728 * @param name The filter name which tells the datasource which beans should be returned. The name also signifies what 1729 * data in the bean will be populated. 1730 * @param criteria This is an bean that has been defined within the metadata of the datasource. If the class is not 1731 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1732 * This bean is used to specify the arguments used to retrieve the collection of beans. 1733 * @param result This is an bean that has been defined within the metadata of the datasource. If the class is not 1734 * defined an exception will be thrown. If the bean does not exist in the datasource, an exception will be thrown. 1735 * This bean is used to specify the bean type that will be returned in the collection. 1736 * @param wheres A collection of CpoWhere beans that define the constraints that should be used when retrieving beans 1737 * @param orderBy The CpoOrderBy bean that defines the order in which beans should be returned 1738 * @param nativeExpressions Native expression that will be used to augment the expression stored in the meta data. This 1739 * text will be embedded at run-time 1740 * @param queueSize the maximum number of beans that the Iterator is allowed to cache. Once reached, the CPO 1741 * framework will halt processing records from the datasource. 1742 * @return An iterator that will be fed beans from the CPO framework. 1743 * @throws CpoException Thrown if there are errors accessing the datasource 1744 */ 1745 @Override 1746 public <T, C> CpoResultSet<T> retrieveBeans(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, int queueSize) throws CpoException { 1747 CpoBlockingResultSet<T> resultSet = new CpoBlockingResultSet<T>(queueSize); 1748 RetrieverThread<T, C> retrieverThread = new RetrieverThread<T, C>(name, criteria, result, wheres, orderBy, nativeExpressions, false, resultSet); 1749 1750 retrieverThread.start(); 1751 return resultSet; 1752 } 1753 1754 /** 1755 * Update the Object in the datasource. The CpoAdapter will check to see if the object exists in the datasource. If it 1756 * exists then the object will be updated. If it does not exist, an exception will be thrown 1757 * 1758 * <pre>Example: 1759 * <code> 1760 * 1761 * class SomeObject so = new SomeObject(); 1762 * class CpoAdapter cpo = null; 1763 * 1764 * try { 1765 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1766 * } catch (CpoException ce) { 1767 * // Handle the error 1768 * cpo = null; 1769 * } 1770 * 1771 * if (cpo!=null) { 1772 * so.setId(1); 1773 * so.setName("SomeName"); 1774 * try{ 1775 * cpo.updateObject(so); 1776 * } catch (CpoException ce) { 1777 * // Handle the error 1778 * } 1779 * } 1780 * </code> 1781 * </pre> 1782 * 1783 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1784 * defined an exception will be thrown. 1785 * @return The number of objects updated in the datasource 1786 * @throws CpoException Thrown if there are errors accessing the datasource 1787 */ 1788 @Override 1789 public <T> long updateObject(T obj) throws CpoException { 1790 return processUpdateGroup(obj, JdbcCpoAdapter.UPDATE_GROUP, null, null, null, null); 1791 } 1792 1793 /** 1794 * Update the Object in the datasource. The CpoAdapter will check to see if the object exists in the datasource. If it 1795 * exists then the object will be updated. If it does not exist, an exception will be thrown 1796 * 1797 * <pre>Example: 1798 * <code> 1799 * 1800 * class SomeObject so = new SomeObject(); 1801 * class CpoAdapter cpo = null; 1802 * 1803 * try { 1804 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1805 * } catch (CpoException ce) { 1806 * // Handle the error 1807 * cpo = null; 1808 * } 1809 * 1810 * if (cpo!=null) { 1811 * so.setId(1); 1812 * so.setName("SomeName"); 1813 * try{ 1814 * cpo.updateObject("updateSomeObject",so); 1815 * } catch (CpoException ce) { 1816 * // Handle the error 1817 * } 1818 * } 1819 * </code> 1820 * </pre> 1821 * 1822 * @param name The String name of the UPDATE Function Group that will be used to create the object in the datasource. 1823 * null signifies that the default rules will be used. 1824 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1825 * defined an exception will be thrown. 1826 * @return The number of objects updated in the datasource 1827 * @throws CpoException Thrown if there are errors accessing the datasource 1828 */ 1829 @Override 1830 public <T> long updateObject(String name, T obj) throws CpoException { 1831 return processUpdateGroup(obj, JdbcCpoAdapter.UPDATE_GROUP, name, null, null, null); 1832 } 1833 1834 /** 1835 * Update the Object in the datasource. The CpoAdapter will check to see if the object exists in the datasource. If it 1836 * exists then the object will be updated. If it does not exist, an exception will be thrown 1837 * 1838 * <pre>Example: 1839 * <code> 1840 * 1841 * class SomeObject so = new SomeObject(); 1842 * class CpoAdapter cpo = null; 1843 * 1844 * try { 1845 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1846 * } catch (CpoException ce) { 1847 * // Handle the error 1848 * cpo = null; 1849 * } 1850 * 1851 * if (cpo!=null) { 1852 * so.setId(1); 1853 * so.setName("SomeName"); 1854 * try{ 1855 * cpo.updateObject("updateSomeObject",so); 1856 * } catch (CpoException ce) { 1857 * // Handle the error 1858 * } 1859 * } 1860 * </code> 1861 * </pre> 1862 * 1863 * @param name The String name of the UPDATE Function Group that will be used to create the object in the datasource. 1864 * null signifies that the default rules will be used. 1865 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 1866 * defined an exception will be thrown. 1867 * @param wheres A collection of CpoWhere objects to be used by the function 1868 * @param orderBy A collection of CpoOrderBy objects to be used by the function 1869 * @param nativeExpressions A collection of CpoNativeFunction objects to be used by the function 1870 * @return The number of objects updated in the datasource 1871 * @throws CpoException Thrown if there are errors accessing the datasource 1872 */ 1873 @Override 1874 public <T> long updateObject(String name, T obj, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 1875 return processUpdateGroup(obj, JdbcCpoAdapter.UPDATE_GROUP, name, wheres, orderBy, nativeExpressions); 1876 } 1877 1878 /** 1879 * Updates a collection of Objects in the datasource. The assumption is that the objects contained in the collection 1880 * exist in the datasource. This method stores the object in the datasource. The objects in the collection will be 1881 * treated as one transaction, meaning that if one of the objects fail being updated in the datasource then the entire 1882 * collection will be rolled back, if supported by the datasource. 1883 * 1884 * <pre>Example: 1885 * <code> 1886 * 1887 * class SomeObject so = null; 1888 * class CpoAdapter cpo = null; 1889 * 1890 * try { 1891 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1892 * } catch (CpoException ce) { 1893 * // Handle the error 1894 * cpo = null; 1895 * } 1896 * 1897 * if (cpo!=null) { 1898 * ArrayList al = new ArrayList(); 1899 * for (int i=0; i<3; i++){ 1900 * so = new SomeObject(); 1901 * so.setId(1); 1902 * so.setName("SomeName"); 1903 * al.add(so); 1904 * } 1905 * try{ 1906 * cpo.updateObjects(al); 1907 * } catch (CpoException ce) { 1908 * // Handle the error 1909 * } 1910 * } 1911 * </code> 1912 * </pre> 1913 * 1914 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 1915 * class is not defined an exception will be thrown. 1916 * @return The number of objects updated in the datasource 1917 * @throws CpoException Thrown if there are errors accessing the datasource 1918 */ 1919 @Override 1920 public <T> long updateObjects(Collection<T> coll) throws CpoException { 1921 return processUpdateGroup(coll, JdbcCpoAdapter.UPDATE_GROUP, null, null, null, null); 1922 } 1923 1924 /** 1925 * Updates a collection of Objects in the datasource. The assumption is that the objects contained in the collection 1926 * exist in the datasource. This method stores the object in the datasource. The objects in the collection will be 1927 * treated as one transaction, meaning that if one of the objects fail being updated in the datasource then the entire 1928 * collection will be rolled back, if supported by the datasource. 1929 * 1930 * <pre>Example: 1931 * <code> 1932 * 1933 * class SomeObject so = null; 1934 * class CpoAdapter cpo = null; 1935 * 1936 * try { 1937 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1938 * } catch (CpoException ce) { 1939 * // Handle the error 1940 * cpo = null; 1941 * } 1942 * 1943 * if (cpo!=null) { 1944 * ArrayList al = new ArrayList(); 1945 * for (int i=0; i<3; i++){ 1946 * so = new SomeObject(); 1947 * so.setId(1); 1948 * so.setName("SomeName"); 1949 * al.add(so); 1950 * } 1951 * try{ 1952 * cpo.updateObjects("myUpdate",al); 1953 * } catch (CpoException ce) { 1954 * // Handle the error 1955 * } 1956 * } 1957 * </code> 1958 * </pre> 1959 * 1960 * @param name The String name of the UPDATE Function Group that will be used to create the object in the datasource. 1961 * null signifies that the default rules will be used. 1962 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 1963 * class is not defined an exception will be thrown. 1964 * @return The number of objects updated in the datasource 1965 * @throws CpoException Thrown if there are errors accessing the datasource 1966 */ 1967 @Override 1968 public <T> long updateObjects(String name, Collection<T> coll) throws CpoException { 1969 return processUpdateGroup(coll, JdbcCpoAdapter.UPDATE_GROUP, name, null, null, null); 1970 } 1971 1972 /** 1973 * Updates a collection of Objects in the datasource. The assumption is that the objects contained in the collection 1974 * exist in the datasource. This method stores the object in the datasource. The objects in the collection will be 1975 * treated as one transaction, meaning that if one of the objects fail being updated in the datasource then the entire 1976 * collection will be rolled back, if supported by the datasource. 1977 * 1978 * <pre>Example: 1979 * <code> 1980 * 1981 * class SomeObject so = null; 1982 * class CpoAdapter cpo = null; 1983 * 1984 * try { 1985 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 1986 * } catch (CpoException ce) { 1987 * // Handle the error 1988 * cpo = null; 1989 * } 1990 * 1991 * if (cpo!=null) { 1992 * ArrayList al = new ArrayList(); 1993 * for (int i=0; i<3; i++){ 1994 * so = new SomeObject(); 1995 * so.setId(1); 1996 * so.setName("SomeName"); 1997 * al.add(so); 1998 * } 1999 * try{ 2000 * cpo.updateObjects("myUpdate",al); 2001 * } catch (CpoException ce) { 2002 * // Handle the error 2003 * } 2004 * } 2005 * </code> 2006 * </pre> 2007 * 2008 * @param name The String name of the UPDATE Function Group that will be used to create the object in the datasource. 2009 * null signifies that the default rules will be used. 2010 * @param coll This is a collection of objects that have been defined within the metadata of the datasource. If the 2011 * class is not defined an exception will be thrown. 2012 * @param wheres A collection of CpoWhere objects to be used by the function 2013 * @param orderBy A collection of CpoOrderBy objects to be used by the function 2014 * @param nativeExpressions A collection of CpoNativeFunction objects to be used by the function 2015 * @return The number of objects updated in the datasource 2016 * @throws CpoException Thrown if there are errors accessing the datasource 2017 */ 2018 @Override 2019 public <T> long updateObjects(String name, Collection<T> coll, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 2020 return processUpdateGroup(coll, JdbcCpoAdapter.UPDATE_GROUP, name, wheres, orderBy, nativeExpressions); 2021 } 2022 2023 /** 2024 * DOCUMENT ME! 2025 * 2026 * @param context DOCUMENT ME! 2027 * @throws CpoException DOCUMENT ME! 2028 */ 2029 protected void setContext(Context context) throws CpoException { 2030 try { 2031 if (context == null) { 2032 context_ = new InitialContext(); 2033 } else { 2034 context_ = context; 2035 } 2036 } catch (NamingException e) { 2037 throw new CpoException("Error setting Context", e); 2038 } 2039 } 2040 2041 /** 2042 * DOCUMENT ME! 2043 * 2044 * @return DOCUMENT ME! 2045 */ 2046 protected Context getContext() { 2047 return context_; 2048 } 2049 2050 /** 2051 * DOCUMENT ME! 2052 * 2053 * @param obj DOCUMENT ME! 2054 * @param type DOCUMENT ME! 2055 * @param name DOCUMENT ME! 2056 * @param c DOCUMENT ME! 2057 * @return DOCUMENT ME! 2058 * @throws CpoException DOCUMENT ME! 2059 */ 2060 protected <T> String getGroupType(T obj, String type, String name, Connection c) throws CpoException { 2061 String retType = type; 2062 long objCount; 2063 2064 if (JdbcCpoAdapter.PERSIST_GROUP.equals(retType)) { 2065 objCount = existsObject(name, obj, c, null); 2066 2067 if (objCount == 0) { 2068 retType = JdbcCpoAdapter.CREATE_GROUP; 2069 } else if (objCount == 1) { 2070 retType = JdbcCpoAdapter.UPDATE_GROUP; 2071 } else { 2072 throw new CpoException("Persist can only UPDATE one record. Your EXISTS function returned 2 or more."); 2073 } 2074 } 2075 2076 return retType; 2077 } 2078 2079 /** 2080 * DOCUMENT ME! 2081 * 2082 * @return DOCUMENT ME! 2083 * @throws CpoException DOCUMENT ME! 2084 */ 2085 protected Connection getReadConnection() throws CpoException { 2086 Connection connection = getStaticConnection(); 2087 2088 if (connection == null) { 2089 try { 2090 if (!(invalidReadConnection_)) { 2091 connection = getReadDataSource().getConnection(); 2092 } else { 2093 connection = getWriteDataSource().getConnection(); 2094 } 2095 connection.setAutoCommit(false); 2096 } catch (Exception e) { 2097 invalidReadConnection_ = true; 2098 2099 String msg = "getReadConnection(): failed"; 2100 logger.error(msg, e); 2101 2102 try { 2103 connection = getWriteDataSource().getConnection(); 2104 connection.setAutoCommit(false); 2105 } catch (SQLException e2) { 2106 msg = "getWriteConnection(): failed"; 2107 logger.error(msg, e2); 2108 throw new CpoException(msg, e2); 2109 } 2110 } 2111 } 2112 2113 return connection; 2114 } 2115 2116 /** 2117 * DOCUMENT ME! 2118 * 2119 * @return DOCUMENT ME! 2120 */ 2121 protected DataSource getReadDataSource() { 2122 return readDataSource_; 2123 } 2124 2125 /** 2126 * DOCUMENT ME! 2127 * 2128 * @return DOCUMENT ME! 2129 * @throws CpoException DOCUMENT ME! 2130 */ 2131 protected Connection getWriteConnection() throws CpoException { 2132 Connection connection = getStaticConnection(); 2133 2134 if (connection == null) { 2135 try { 2136 connection = getWriteDataSource().getConnection(); 2137 connection.setAutoCommit(false); 2138 } catch (SQLException e) { 2139 String msg = "getWriteConnection(): failed"; 2140 logger.error(msg, e); 2141 throw new CpoException(msg, e); 2142 } 2143 } 2144 2145 return connection; 2146 } 2147 2148 protected Connection getStaticConnection() throws CpoException { 2149 // do nothing for JdbcCpoAdapter 2150 // overridden by JdbcTrxAdapter 2151 return null; 2152 } 2153 2154 protected boolean isStaticConnection(Connection c) { 2155 // do nothing for JdbcCpoAdapter 2156 // overridden by JdbcTrxAdapter 2157 return false; 2158 } 2159 2160 protected void setStaticConnection(Connection c) { 2161 // do nothing for JdbcCpoAdapter 2162 // overridden by JdbcTrxAdapter 2163 } 2164 2165 /** 2166 * DOCUMENT ME! 2167 * 2168 * @return DOCUMENT ME! 2169 */ 2170 protected DataSource getWriteDataSource() { 2171 return writeDataSource_; 2172 } 2173 2174 /** 2175 * DOCUMENT ME! 2176 * 2177 * @param connection DOCUMENT ME! 2178 */ 2179 protected void closeConnection(Connection connection) { 2180 try { 2181 clearConnectionBusy(connection); 2182 if (connection != null && !isStaticConnection(connection) && !connection.isClosed()) { 2183 connection.close(); 2184 } 2185 } catch (SQLException e) { 2186 if (logger.isTraceEnabled()) { 2187 logger.trace(e.getMessage()); 2188 } 2189 } 2190 } 2191 2192 /** 2193 * DOCUMENT ME! 2194 * 2195 * @param connection DOCUMENT ME! 2196 */ 2197 protected void commitConnection(Connection connection) { 2198 try { 2199 if (connection != null && !isStaticConnection(connection)) { 2200 connection.commit(); 2201 } 2202 } catch (SQLException e) { 2203 if (logger.isTraceEnabled()) { 2204 logger.trace(e.getMessage()); 2205 } 2206 } 2207 } 2208 2209 /** 2210 * DOCUMENT ME! 2211 * 2212 * @param connection DOCUMENT ME! 2213 */ 2214 protected void rollbackConnection(Connection connection) { 2215 try { 2216 if (connection != null && !isStaticConnection(connection)) { 2217 connection.rollback(); 2218 } 2219 } catch (SQLException se) { 2220 if (logger.isTraceEnabled()) { 2221 logger.trace(se.getMessage()); 2222 } 2223 } catch (Exception e) { 2224 if (logger.isTraceEnabled()) { 2225 logger.trace(e.getMessage()); 2226 } 2227 } 2228 } 2229 2230 /** 2231 * Executes an Object whose MetaData contains a stored procedure. An assumption is that the object exists in the 2232 * datasource. 2233 * 2234 * @param name The filter name which tells the datasource which objects should be returned. The name also signifies 2235 * what data in the object will be populated. 2236 * @param criteria This is an object that has been defined within the metadata of the datasource. If the class is not 2237 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 2238 * This object is used to populate the IN arguments used to retrieve the collection of objects. 2239 * @param result This is an object that has been defined within the metadata of the datasource. If the class is not 2240 * defined an exception will be thrown. If the object does not exist in the datasource, an exception will be thrown. 2241 * This object defines the object type that will be returned in the 2242 * @return A result object populate with the OUT arguments 2243 * @throws CpoException DOCUMENT ME! 2244 */ 2245 protected <T, C> T processExecuteGroup(String name, C criteria, T result) throws CpoException { 2246 Connection c = null; 2247 T obj = null; 2248 2249 try { 2250 c = getWriteConnection(); 2251 obj = processExecuteGroup(name, criteria, result, c); 2252 commitConnection(c); 2253 } catch (Exception e) { 2254 // Any exception has to try to rollback the work; 2255 rollbackConnection(c); 2256 ExceptionHelper.reThrowCpoException(e, "processExecuteGroup(String name, Object criteria, Object result) failed"); 2257 } finally { 2258 closeConnection(c); 2259 } 2260 2261 return obj; 2262 } 2263 2264 /** 2265 * DOCUMENT ME! 2266 * 2267 * @param name DOCUMENT ME! 2268 * @param criteria DOCUMENT ME! 2269 * @param result DOCUMENT ME! 2270 * @param conn DOCUMENT ME! 2271 * @return DOCUMENT ME! 2272 * @throws CpoException DOCUMENT ME! 2273 */ 2274 protected <T, C> T processExecuteGroup(String name, C criteria, T result, Connection conn) throws CpoException { 2275 CallableStatement cstmt = null; 2276 CpoClass criteriaClass; 2277 T returnObject = null; 2278 Logger localLogger = criteria == null ? logger : LoggerFactory.getLogger(criteria.getClass()); 2279 2280 JdbcCallableStatementFactory jcsf = null; 2281 2282 if (criteria == null || result == null) { 2283 throw new CpoException("NULL Object passed into executeObject"); 2284 } 2285 2286 try { 2287 criteriaClass = metaDescriptor.getMetaClass(criteria); 2288 List<CpoFunction> functions = criteriaClass.getFunctionGroup(JdbcCpoAdapter.EXECUTE_GROUP, name).getFunctions(); 2289 localLogger.info("===================processExecuteGroup (" + name + ") Count<" + functions.size() + ">========================="); 2290 2291 try { 2292 returnObject = (T)result.getClass().newInstance(); 2293 } catch (IllegalAccessException iae) { 2294 throw new CpoException("Unable to access the constructor of the Return Object", iae); 2295 } catch (InstantiationException iae) { 2296 throw new CpoException("Unable to instantiate Return Object", iae); 2297 } 2298 2299 // Loop through the queries and process each one 2300 for (CpoFunction function : functions) { 2301 2302 localLogger.debug("Executing Call:" + criteriaClass.getName() + ":" + name); 2303 2304 jcsf = new JdbcCallableStatementFactory(conn, this, function, criteria); 2305 cstmt = jcsf.getCallableStatement(); 2306 cstmt.execute(); 2307 jcsf.release(); 2308 2309 localLogger.debug("Processing Call:" + criteriaClass.getName() + ":" + name); 2310 2311 // Add Code here to go through the arguments, find record sets, 2312 // and process them 2313 // Process the non-record set out params and make it the first 2314 // object in the collection 2315 2316 // Loop through the OUT Parameters and set them in the result 2317 // object 2318 int j = 1; 2319 for (CpoArgument cpoArgument : jcsf.getOutArguments()) { 2320 JdbcCpoArgument jdbcArgument = (JdbcCpoArgument)cpoArgument; 2321 if (jdbcArgument.isOutParameter()) { 2322 JdbcCpoAttribute jdbcAttribute = jdbcArgument.getAttribute(); 2323 jdbcAttribute.invokeSetter(returnObject, new CallableStatementCpoData(cstmt, jdbcAttribute, j)); 2324 } 2325 j++; 2326 } 2327 2328 cstmt.close(); 2329 } 2330 } catch (Throwable t) { 2331 String msg = "ProcessExecuteGroup(String name, Object criteria, Object result, Connection conn) failed. SQL="; 2332 localLogger.error(msg, t); 2333 throw new CpoException(msg, t); 2334 } finally { 2335 statementClose(cstmt); 2336 if (jcsf != null) { 2337 jcsf.release(); 2338 } 2339 } 2340 2341 return returnObject; 2342 } 2343 2344 /** 2345 * Retrieves the Object from the datasource. 2346 * 2347 * @param obj This is an object that has been defined within the metadata of the datasource. If the class is not 2348 * defined an exception will be thrown. The input object is used to specify the search criteria. 2349 * @param groupName The name which identifies which RETRIEVE Function Group to execute to retrieve the object. 2350 * @param wheres A collection of CpoWhere objects to be used by the function 2351 * @param orderBy A collection of CpoOrderBy objects to be used by the function 2352 * @param nativeExpressions A collection of CpoNativeFunction objects to be used by the function 2353 * @return A populated object of the same type as the Object passed in as a argument. If no objects match the criteria 2354 * a NULL will be returned. 2355 * @throws CpoException the retrieve function defined for this objects returns more than one row, an exception will be 2356 * thrown. 2357 */ 2358 protected <T> T processSelectGroup(T obj, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 2359 Connection c = null; 2360 T result = null; 2361 2362 try { 2363 c = getReadConnection(); 2364 result = processSelectGroup(obj, groupName, wheres, orderBy, nativeExpressions, c); 2365 2366 // The select may have a for update clause on it 2367 // Since the connection is cached we need to get rid of this 2368 commitConnection(c); 2369 } catch (Exception e) { 2370 // Any exception has to try to rollback the work; 2371 rollbackConnection(c); 2372 ExceptionHelper.reThrowCpoException(e, "processSelectGroup(Object obj, String groupName) failed"); 2373 } finally { 2374 closeConnection(c); 2375 } 2376 2377 return result; 2378 } 2379 2380 /** 2381 * DOCUMENT ME! 2382 * 2383 * @param obj DOCUMENT ME! 2384 * @param groupName DOCUMENT ME! 2385 * @param con DOCUMENT ME! 2386 * @return DOCUMENT ME! 2387 * @throws CpoException DOCUMENT ME! 2388 */ 2389 protected <T> T processSelectGroup(T obj, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, Connection con) throws CpoException { 2390 PreparedStatement ps = null; 2391 ResultSet rs = null; 2392 ResultSetMetaData rsmd; 2393 CpoClass cpoClass; 2394 JdbcCpoAttribute attribute; 2395 T criteriaObj = obj; 2396 boolean recordsExist = false; 2397 Logger localLogger = obj == null ? logger : LoggerFactory.getLogger(obj.getClass()); 2398 2399 int recordCount = 0; 2400 int attributesSet = 0; 2401 2402 int k; 2403 T rObj = null; 2404 2405 if (obj == null) { 2406 throw new CpoException("NULL Object passed into retrieveBean"); 2407 } 2408 2409 try { 2410 cpoClass = metaDescriptor.getMetaClass(criteriaObj); 2411 List<CpoFunction> functions = cpoClass.getFunctionGroup(JdbcCpoAdapter.RETRIEVE_GROUP, groupName).getFunctions(); 2412 2413 localLogger.info("=================== Class=<" + criteriaObj.getClass() + "> Type=<" + JdbcCpoAdapter.RETRIEVE_GROUP + "> Name=<" + groupName + "> ========================="); 2414 2415 try { 2416 rObj = (T)obj.getClass().newInstance(); 2417 } catch (IllegalAccessException iae) { 2418 if (obj != null) { 2419 localLogger.error("=================== Could not access default constructor for Class=<" + obj.getClass() + "> =================="); 2420 } else { 2421 localLogger.error("=================== Could not access default constructor for class =================="); 2422 } 2423 2424 throw new CpoException("Unable to access the constructor of the Return Object", iae); 2425 } catch (InstantiationException iae) { 2426 throw new CpoException("Unable to instantiate Return Object", iae); 2427 } 2428 2429 for (CpoFunction cpoFunction : functions) { 2430 2431 JdbcPreparedStatementFactory jpsf = new JdbcPreparedStatementFactory(con, this, cpoClass, cpoFunction, criteriaObj, wheres, orderBy, nativeExpressions); 2432 ps = jpsf.getPreparedStatement(); 2433 2434 // insertions on 2435 // selectgroup 2436 rs = ps.executeQuery(); 2437 jpsf.release(); 2438 2439 if (rs.isBeforeFirst()) { 2440 rsmd = rs.getMetaData(); 2441 2442 if ((rsmd.getColumnCount() == 2) && "CPO_ATTRIBUTE".equalsIgnoreCase(rsmd.getColumnLabel(1)) && "CPO_VALUE".equalsIgnoreCase(rsmd.getColumnLabel(2))) { 2443 while (rs.next()) { 2444 recordsExist = true; 2445 recordCount++; 2446 attribute = (JdbcCpoAttribute)cpoClass.getAttributeData(rs.getString(1)); 2447 2448 if (attribute != null) { 2449 attribute.invokeSetter(rObj, new ResultSetCpoData(rs, attribute, 2)); 2450 attributesSet++; 2451 } 2452 } 2453 } else if (rs.next()) { 2454 recordsExist = true; 2455 recordCount++; 2456 for (k = 1; k <= rsmd.getColumnCount(); k++) { 2457 attribute = (JdbcCpoAttribute)cpoClass.getAttributeData(rsmd.getColumnLabel(k)); 2458 2459 if (attribute != null) { 2460 attribute.invokeSetter(rObj, new ResultSetCpoData(rs, attribute, k)); 2461 attributesSet++; 2462 } 2463 } 2464 2465 if (rs.next()) { 2466 String msg = "ProcessSelectGroup(Object, String) failed: Multiple Records Returned"; 2467 localLogger.error(msg); 2468 throw new CpoException(msg); 2469 } 2470 } 2471 criteriaObj = rObj; 2472 } 2473 2474 rs.close(); 2475 rs = null; 2476 ps.close(); 2477 ps = null; 2478 } 2479 2480 if (!recordsExist) { 2481 rObj = null; 2482 localLogger.info("=================== 0 Records - 0 Attributes - Class=<" + criteriaObj.getClass() + "> Type=<" + JdbcCpoAdapter.RETRIEVE_GROUP + "> Name=<" + groupName + "> ========================="); 2483 } else { 2484 localLogger.info("=================== " + recordCount + " Records - " + attributesSet + " Attributes - Class=<" + criteriaObj.getClass() + "> Type=<" + JdbcCpoAdapter.RETRIEVE_GROUP + "> Name=<" + groupName + "> ========================="); 2485 } 2486 } catch (Throwable t) { 2487 String msg = "ProcessSeclectGroup(Object) failed: " + ExceptionHelper.getLocalizedMessage(t); 2488 localLogger.error(msg, t); 2489 rObj = null; 2490 throw new CpoException(msg, t); 2491 } finally { 2492 resultSetClose(rs); 2493 statementClose(ps); 2494 } 2495 2496 return rObj; 2497 } 2498 2499 /** 2500 * DOCUMENT ME! 2501 * 2502 * @param name DOCUMENT ME! 2503 * @param criteria DOCUMENT ME! 2504 * @param result DOCUMENT ME! 2505 * @param wheres DOCUMENT ME! 2506 * @param orderBy DOCUMENT ME! 2507 * @param useRetrieve DOCUMENT ME! 2508 * @return DOCUMENT ME! 2509 * @throws CpoException DOCUMENT ME! 2510 */ 2511 protected <T, C> List<T> processSelectGroup(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, boolean useRetrieve) throws CpoException { 2512 Connection con = null; 2513 CpoArrayResultSet<T> resultSet = new CpoArrayResultSet<T>(); 2514 2515 try { 2516 con = getReadConnection(); 2517 processSelectGroup(name, criteria, result, wheres, orderBy, nativeExpressions, con, useRetrieve, resultSet); 2518 // The select may have a for update clause on it 2519 // Since the connection is cached we need to get rid of this 2520 commitConnection(con); 2521 } catch (Exception e) { 2522 // Any exception has to try to rollback the work; 2523 rollbackConnection(con); 2524 ExceptionHelper.reThrowCpoException(e, "processSelectGroup(String name, Object criteria, Object result,CpoWhere where, Collection orderBy, boolean useRetrieve) failed"); 2525 } finally { 2526 closeConnection(con); 2527 } 2528 2529 return resultSet; 2530 } 2531 2532 protected <T, C> void processSelectGroup(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, boolean useRetrieve, CpoResultSet<T> resultSet) throws CpoException { 2533 Connection con = null; 2534 2535 try { 2536 con = getReadConnection(); 2537 processSelectGroup(name, criteria, result, wheres, orderBy, nativeExpressions, con, useRetrieve, resultSet); 2538 // The select may have a for update clause on it 2539 // Since the connection is cached we need to get rid of this 2540 commitConnection(con); 2541 } catch (Exception e) { 2542 // Any exception has to try to rollback the work; 2543 rollbackConnection(con); 2544 ExceptionHelper.reThrowCpoException(e, "processSelectGroup(String name, Object criteria, Object result,CpoWhere where, Collection orderBy, boolean useRetrieve) failed"); 2545 } finally { 2546 closeConnection(con); 2547 } 2548 } 2549 2550 /** 2551 * DOCUMENT ME! 2552 * 2553 * @param name DOCUMENT ME! 2554 * @param criteria DOCUMENT ME! 2555 * @param result DOCUMENT ME! 2556 * @param wheres DOCUMENT ME! 2557 * @param orderBy DOCUMENT ME! 2558 * @param con DOCUMENT ME! 2559 * @param useRetrieve DOCUMENT ME! 2560 * @throws CpoException DOCUMENT ME! 2561 */ 2562 protected <T, C> void processSelectGroup(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, Connection con, boolean useRetrieve, CpoResultSet<T> resultSet) throws CpoException { 2563 Logger localLogger = criteria == null ? logger : LoggerFactory.getLogger(criteria.getClass()); 2564 PreparedStatement ps = null; 2565 List<CpoFunction> cpoFunctions; 2566 CpoClass criteriaClass; 2567 CpoClass resultClass; 2568 ResultSet rs = null; 2569 ResultSetMetaData rsmd; 2570 int columnCount; 2571 int k; 2572 T obj; 2573 JdbcCpoAttribute[] attributes; 2574 JdbcPreparedStatementFactory jpsf; 2575 int i; 2576 2577 if (criteria == null || result == null) { 2578 throw new CpoException("NULL Object passed into retrieveBean or retrieveBeans"); 2579 } 2580 2581 try { 2582 criteriaClass = metaDescriptor.getMetaClass(criteria); 2583 resultClass = metaDescriptor.getMetaClass(result); 2584 if (useRetrieve) { 2585 localLogger.info("=================== Class=<" + criteria.getClass() + "> Type=<" + JdbcCpoAdapter.RETRIEVE_GROUP + "> Name=<" + name + "> ========================="); 2586 cpoFunctions = criteriaClass.getFunctionGroup(JdbcCpoAdapter.RETRIEVE_GROUP, name).getFunctions(); 2587 } else { 2588 localLogger.info("=================== Class=<" + criteria.getClass() + "> Type=<" + JdbcCpoAdapter.LIST_GROUP + "> Name=<" + name + "> ========================="); 2589 cpoFunctions = criteriaClass.getFunctionGroup(JdbcCpoAdapter.LIST_GROUP, name).getFunctions(); 2590 } 2591 2592 for (CpoFunction cpoFunction : cpoFunctions) { 2593 jpsf = new JdbcPreparedStatementFactory(con, this, criteriaClass, cpoFunction, criteria, wheres, orderBy, nativeExpressions); 2594 ps = jpsf.getPreparedStatement(); 2595 if (resultSet.getFetchSize() != -1) { 2596 ps.setFetchSize(resultSet.getFetchSize()); 2597 } 2598 2599 localLogger.debug("Retrieving Records"); 2600 2601 rs = ps.executeQuery(); 2602 jpsf.release(); 2603 2604 localLogger.debug("Processing Records"); 2605 2606 rsmd = rs.getMetaData(); 2607 2608 columnCount = rsmd.getColumnCount(); 2609 2610 attributes = new JdbcCpoAttribute[columnCount + 1]; 2611 2612 for (k = 1; k <= columnCount; k++) { 2613 attributes[k] = (JdbcCpoAttribute)resultClass.getAttributeData(rsmd.getColumnLabel(k)); 2614 } 2615 2616 while (rs.next()) { 2617 try { 2618 obj = (T)result.getClass().newInstance(); 2619 } catch (IllegalAccessException iae) { 2620 if (result != null) { 2621 localLogger.error("=================== Could not access default constructor for Class=<" + result.getClass() + "> =================="); 2622 } else { 2623 localLogger.error("=================== Could not access default constructor for class =================="); 2624 } 2625 2626 throw new CpoException("Unable to access the constructor of the Return Object", iae); 2627 } catch (InstantiationException iae) { 2628 throw new CpoException("Unable to instantiate Return Object", iae); 2629 } 2630 2631 for (k = 1; k <= columnCount; k++) { 2632 if (attributes[k] != null) { 2633 attributes[k].invokeSetter(obj, new ResultSetCpoData(rs, attributes[k], k)); 2634 } 2635 } 2636 2637 try { 2638 resultSet.put(obj); 2639 } catch (InterruptedException e) { 2640 localLogger.error("Retriever Thread was interrupted", e); 2641 break; 2642 } 2643 } 2644 2645 resultSetClose(rs); 2646 statementClose(ps); 2647 2648 localLogger.info("=================== " + resultSet.size() + " Records - Class=<" + criteria.getClass() + "> Type=<" + JdbcCpoAdapter.LIST_GROUP + "> Name=<" + name + "> Result=<" + result.getClass() + "> ===================="); 2649 } 2650 } catch (Throwable t) { 2651 String msg = "ProcessSelectGroup(String name, Object criteria, Object result, CpoWhere where, Collection orderBy, Connection con) failed. Error:"; 2652 localLogger.error(msg, t); 2653 throw new CpoException(msg, t); 2654 } finally { 2655 resultSetClose(rs); 2656 statementClose(ps); 2657 } 2658 } 2659 2660 /** 2661 * DOCUMENT ME! 2662 * 2663 * @param obj DOCUMENT ME! 2664 * @param groupType DOCUMENT ME! 2665 * @param groupName DOCUMENT ME! 2666 * @return DOCUMENT ME! 2667 * @throws CpoException DOCUMENT ME! 2668 */ 2669 protected <T> long processUpdateGroup(T obj, String groupType, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 2670 Connection c = null; 2671 long updateCount = 0; 2672 2673 try { 2674 c = getWriteConnection(); 2675 updateCount = processUpdateGroup(obj, groupType, groupName, wheres, orderBy, nativeExpressions, c); 2676 commitConnection(c); 2677 } catch (Exception e) { 2678 // Any exception has to try to rollback the work; 2679 rollbackConnection(c); 2680 ExceptionHelper.reThrowCpoException(e, "processUdateGroup(Object obj, String groupType, String groupName) failed"); 2681 } finally { 2682 closeConnection(c); 2683 } 2684 2685 return updateCount; 2686 } 2687 2688 /** 2689 * DOCUMENT ME! 2690 * 2691 * @param obj DOCUMENT ME! 2692 * @param groupType DOCUMENT ME! 2693 * @param groupName DOCUMENT ME! 2694 * @param con DOCUMENT ME! 2695 * @return DOCUMENT ME! 2696 * @throws CpoException DOCUMENT ME! 2697 */ 2698 protected <T> long processUpdateGroup(T obj, String groupType, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, Connection con) throws CpoException { 2699 Logger localLogger = obj == null ? logger : LoggerFactory.getLogger(obj.getClass()); 2700 CpoClass cpoClass; 2701 PreparedStatement ps = null; 2702 2703 JdbcPreparedStatementFactory jpsf = null; 2704 long updateCount = 0; 2705 2706 if (obj == null) { 2707 throw new CpoException("NULL Object passed into insertObject, deleteObject, updateObject, or persistObject"); 2708 } 2709 2710 try { 2711 cpoClass = metaDescriptor.getMetaClass(obj); 2712 List<CpoFunction> cpoFunctions = cpoClass.getFunctionGroup(getGroupType(obj, groupType, groupName, con), groupName).getFunctions(); 2713 localLogger.info("=================== Class=<" + obj.getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2714 2715 int numRows = 0; 2716 2717 for (CpoFunction cpoFunction : cpoFunctions) { 2718 jpsf = new JdbcPreparedStatementFactory(con, this, cpoClass, cpoFunction, obj, wheres, orderBy, nativeExpressions); 2719 ps = jpsf.getPreparedStatement(); 2720 numRows += ps.executeUpdate(); 2721 jpsf.release(); 2722 ps.close(); 2723 } 2724 localLogger.info("=================== " + numRows + " Updates - Class=<" + obj.getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2725 2726 if (numRows > 0) { 2727 updateCount++; 2728 } 2729 } catch (Throwable t) { 2730 String msg = "ProcessUpdateGroup failed:" + groupType + "," + groupName + "," + obj.getClass().getName(); 2731 // TODO FIX THIS 2732 // localLogger.error("bound values:" + this.parameterToString(jq)); 2733 localLogger.error(msg, t); 2734 throw new CpoException(msg, t); 2735 } finally { 2736 statementClose(ps); 2737 if (jpsf != null) { 2738 jpsf.release(); 2739 } 2740 } 2741 2742 return updateCount; 2743 } 2744 2745 /** 2746 * DOCUMENT ME! 2747 * 2748 * @param arr DOCUMENT ME! 2749 * @param groupType DOCUMENT ME! 2750 * @param groupName DOCUMENT ME! 2751 * @param con DOCUMENT ME! 2752 * @return DOCUMENT ME! 2753 * @throws CpoException DOCUMENT ME! 2754 */ 2755 protected <T> long processBatchUpdateGroup(T[] arr, String groupType, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, Connection con) throws CpoException { 2756 CpoClass jmc; 2757 List<CpoFunction> cpoFunctions; 2758 PreparedStatement ps = null; 2759 CpoFunction cpoFunction; 2760 JdbcPreparedStatementFactory jpsf = null; 2761 long updateCount = 0; 2762 int[] updates; 2763 Logger localLogger = logger; 2764 2765 try { 2766 jmc = metaDescriptor.getMetaClass(arr[0]); 2767 cpoFunctions = jmc.getFunctionGroup(getGroupType(arr[0], groupType, groupName, con), groupName).getFunctions(); 2768 localLogger = LoggerFactory.getLogger(jmc.getMetaClass()); 2769 2770 int numRows = 0; 2771 2772 // Only Batch if there is only one function 2773 if (cpoFunctions.size() == 1) { 2774 localLogger.info("=================== BATCH - Class=<" + arr[0].getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2775 cpoFunction = cpoFunctions.get(0); 2776 jpsf = new JdbcPreparedStatementFactory(con, this, jmc, cpoFunction, arr[0], wheres, orderBy, nativeExpressions); 2777 ps = jpsf.getPreparedStatement(); 2778 ps.addBatch(); 2779 for (int j = 1; j < arr.length; j++) { 2780 // jpsf.bindParameters(arr[j]); 2781 jpsf.setBindValues(jpsf.getBindValues(cpoFunction, arr[j])); 2782 ps.addBatch(); 2783 } 2784 updates = ps.executeBatch(); 2785 jpsf.release(); 2786 ps.close(); 2787 for (int update : updates) { 2788 if (update < 0 && update == PreparedStatement.SUCCESS_NO_INFO) { 2789 // something updated but we do not know what or how many so default to one. 2790 numRows++; 2791 } else { 2792 numRows += update; 2793 } 2794 } 2795 localLogger.info("=================== BATCH - " + numRows + " Updates - Class=<" + arr[0].getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2796 } else { 2797 localLogger.info("=================== Class=<" + arr[0].getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2798 for (T obj : arr) { 2799 for (CpoFunction function : cpoFunctions) { 2800 jpsf = new JdbcPreparedStatementFactory(con, this, jmc, function, obj, wheres, orderBy, nativeExpressions); 2801 ps = jpsf.getPreparedStatement(); 2802 numRows += ps.executeUpdate(); 2803 jpsf.release(); 2804 ps.close(); 2805 } 2806 } 2807 localLogger.info("=================== " + numRows + " Updates - Class=<" + arr[0].getClass() + "> Type=<" + groupType + "> Name=<" + groupName + "> ========================="); 2808 } 2809 2810 if (numRows > 0) { 2811 updateCount = numRows; 2812 } 2813 } catch (Throwable t) { 2814 String msg = "ProcessUpdateGroup failed:" + groupType + "," + groupName + "," + arr[0].getClass().getName(); 2815 // TODO FIX This 2816 // localLogger.error("bound values:" + this.parameterToString(jq)); 2817 localLogger.error(msg, t); 2818 throw new CpoException(msg, t); 2819 } finally { 2820 statementClose(ps); 2821 if (jpsf != null) { 2822 jpsf.release(); 2823 } 2824 } 2825 2826 return updateCount; 2827 } 2828 2829 /** 2830 * DOCUMENT ME! 2831 * 2832 * @param coll DOCUMENT ME! 2833 * @param groupType DOCUMENT ME! 2834 * @param groupName DOCUMENT ME! 2835 * @return DOCUMENT ME! 2836 * @throws CpoException DOCUMENT ME! 2837 */ 2838 protected <T> long processUpdateGroup(Collection<T> coll, String groupType, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions) throws CpoException { 2839 Connection c = null; 2840 long updateCount = 0; 2841 2842 try { 2843 c = getWriteConnection(); 2844 2845 updateCount = processUpdateGroup(coll, groupType, groupName, wheres, orderBy, nativeExpressions, c); 2846 commitConnection(c); 2847 } catch (Exception e) { 2848 // Any exception has to try to rollback the work; 2849 rollbackConnection(c); 2850 ExceptionHelper.reThrowCpoException(e, "processUpdateGroup(Collection coll, String groupType, String groupName) failed"); 2851 } finally { 2852 closeConnection(c); 2853 } 2854 2855 return updateCount; 2856 } 2857 2858 /** 2859 * DOCUMENT ME! 2860 * 2861 * @param coll DOCUMENT ME! 2862 * @param groupType DOCUMENT ME! 2863 * @param groupName DOCUMENT ME! 2864 * @param wheres DOCUMENT ME! 2865 * @param orderBy DOCUMENT ME! 2866 * @param nativeExpressions DOCUMENT ME! 2867 * @param con DOCUMENT ME! 2868 * @return DOCUMENT ME! 2869 * @throws CpoException DOCUMENT ME! 2870 */ 2871 protected <T> long processUpdateGroup(Collection<T> coll, String groupType, String groupName, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, Connection con) throws CpoException { 2872 long updateCount = 0; 2873 2874 if (!coll.isEmpty()) { 2875 T[] arr = (T[])coll.toArray(); 2876 2877 T obj1 = arr[0]; 2878 boolean allEqual = true; 2879 for (int i = 1; i < arr.length; i++) { 2880 if (!obj1.getClass().getName().equals(arr[i].getClass().getName())) { 2881 allEqual = false; 2882 break; 2883 } 2884 } 2885 2886 if (allEqual && batchUpdatesSupported_ && !JdbcCpoAdapter.PERSIST_GROUP.equals(groupType)) { 2887 updateCount = processBatchUpdateGroup(arr, groupType, groupName, wheres, orderBy, nativeExpressions, con); 2888 } else { 2889 for (T obj : arr) { 2890 updateCount += processUpdateGroup(obj, groupType, groupName, wheres, orderBy, nativeExpressions, con); 2891 } 2892 } 2893 } 2894 2895 return updateCount; 2896 } 2897 2898 /** 2899 * Provides a mechanism for the user to obtain a CpoTrxAdapter object. This object allows the to control when commits 2900 * and rollbacks occur on CPO. 2901 * 2902 * 2903 * <pre>Example: 2904 * <code> 2905 * 2906 * class SomeObject so = null; 2907 * class CpoAdapter cpo = null; 2908 * class CpoTrxAdapter cpoTrx = null; 2909 * 2910 * try { 2911 * cpo = new JdbcCpoAdapter(new JdbcDataSourceInfo(driver, url, user, password,1,1,false)); 2912 * cpoTrx = cpo.getCpoTrxAdapter(); 2913 * } catch (CpoException ce) { 2914 * // Handle the error 2915 * cpo = null; 2916 * } 2917 * 2918 * if (cpo!=null) { 2919 * try{ 2920 * for (int i=0; i<3; i++){ 2921 * so = new SomeObject(); 2922 * so.setId(1); 2923 * so.setName("SomeName"); 2924 * cpo.updateObject("myUpdate",so); 2925 * } 2926 * cpoTrx.commit(); 2927 * } catch (CpoException ce) { 2928 * // Handle the error 2929 * cpoTrx.rollback(); 2930 * } 2931 * } 2932 * </code> 2933 * </pre> 2934 * 2935 * @return A CpoTrxAdapter to manage the transactionality of CPO 2936 * @throws CpoException Thrown if there are errors accessing the datasource 2937 * @see CpoTrxAdapter 2938 */ 2939 @Override 2940 public CpoTrxAdapter getCpoTrxAdapter() throws CpoException { 2941 return new JdbcCpoTrxAdapter(metaDescriptor, getWriteConnection(), batchUpdatesSupported_, getDataSourceName()); 2942 } 2943 2944 protected boolean isConnectionBusy(Connection c) { 2945 // do nothing for JdbcCpoAdapter 2946 // overridden by JdbcTrxAdapter 2947 return false; 2948 } 2949 2950 protected void setConnectionBusy(Connection c) { 2951 // do nothing for JdbcCpoAdapter 2952 // overridden by JdbcTrxAdapter 2953 } 2954 2955 protected void clearConnectionBusy(Connection c) { 2956 // do nothing for JdbcCpoAdapter 2957 // overridden by JdbcTrxAdapter 2958 } 2959 2960 private void statementClose(Statement s) { 2961 if (s != null) { 2962 try { 2963 s.close(); 2964 } catch (Exception e) { 2965 if (logger.isTraceEnabled()) { 2966 logger.trace(e.getMessage()); 2967 } 2968 } 2969 } 2970 } 2971 2972 private void resultSetClose(ResultSet rs) { 2973 if (rs != null) { 2974 try { 2975 rs.close(); 2976 } catch (Exception e) { 2977 if (logger.isTraceEnabled()) { 2978 logger.trace(e.getMessage()); 2979 } 2980 } 2981 } 2982 } 2983 2984 @Override 2985 public CpoMetaDescriptor getCpoMetaDescriptor() { 2986 return metaDescriptor; 2987 } 2988 2989 @Override 2990 public String getDataSourceName() { 2991 return dataSourceName_; 2992 } 2993 2994 @Override 2995 public List<CpoAttribute> getCpoAttributes(String expression) throws CpoException { 2996 List<CpoAttribute> attributes = new ArrayList<CpoAttribute>(); 2997 2998 if (expression != null && !expression.isEmpty()) { 2999 Connection c = null; 3000 PreparedStatement ps = null; 3001 ResultSet rs = null; 3002 try { 3003 c = getWriteConnection(); 3004 ps = c.prepareStatement(expression); 3005 rs = ps.executeQuery(); 3006 ResultSetMetaData rsmd = rs.getMetaData(); 3007 for (int i = 1; i <= rsmd.getColumnCount(); i++) { 3008 JdbcCpoAttribute attribute = new JdbcCpoAttribute(); 3009 attribute.setDataName(rsmd.getColumnLabel(i)); 3010 attribute.setDbColumn(rsmd.getColumnName(i)); 3011 try { 3012 attribute.setDbTable(rsmd.getTableName(i)); 3013 } catch (Exception e) { 3014 // do nothing if this call is not supported 3015 } 3016 3017 JavaSqlType<?> javaSqlType = metaDescriptor.getJavaSqlType(rsmd.getColumnType(i)); 3018 attribute.setDataType(javaSqlType.getJavaSqlTypeName()); 3019 attribute.setJavaSqlType(javaSqlType.getJavaSqlType()); 3020 attribute.setJavaType(javaSqlType.getJavaClass().getName()); 3021 attribute.setJavaName(javaSqlType.makeJavaName(rsmd.getColumnLabel(i))); 3022 3023 attributes.add(attribute); 3024 } 3025 } catch (Throwable t) { 3026 logger.error(ExceptionHelper.getLocalizedMessage(t), t); 3027 throw new CpoException("Error Generating Attributes", t); 3028 } finally { 3029 resultSetClose(rs); 3030 statementClose(ps); 3031 closeConnection(c); 3032 } 3033 } 3034 return attributes; 3035 } 3036 3037 private class RetrieverThread<T, C> extends Thread { 3038 3039 String name; 3040 C criteria; 3041 T result; 3042 Collection<CpoWhere> wheres; 3043 Collection<CpoOrderBy> orderBy; 3044 Collection<CpoNativeFunction> nativeExpressions; 3045 boolean useRetrieve; 3046 CpoBlockingResultSet<T> resultSet; 3047 Thread callingThread = null; 3048 3049 public RetrieverThread(String name, C criteria, T result, Collection<CpoWhere> wheres, Collection<CpoOrderBy> orderBy, Collection<CpoNativeFunction> nativeExpressions, boolean useRetrieve, CpoBlockingResultSet<T> resultSet) { 3050 this.name = name; 3051 this.criteria = criteria; 3052 this.result = result; 3053 this.wheres = wheres; 3054 this.orderBy = orderBy; 3055 this.useRetrieve = useRetrieve; 3056 this.resultSet = resultSet; 3057 this.nativeExpressions = nativeExpressions; 3058 callingThread = Thread.currentThread(); 3059 } 3060 3061 @Override 3062 public void run() { 3063 try { 3064 processSelectGroup(name, criteria, result, wheres, orderBy, nativeExpressions, false, resultSet); 3065 } catch (CpoException e) { 3066 logger.error(ExceptionHelper.getLocalizedMessage(e)); 3067 } finally { 3068 //wait until the calling thread is finished processing the records 3069 while (resultSet.size() > 0) { 3070 Thread.yield(); 3071 } 3072 //Tell the calling thread that it should not wait on the blocking queue any longer. 3073 callingThread.interrupt(); 3074 } 3075 } 3076 } 3077 }