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