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 }