66
77package com .ibm .fhir .persistence .jdbc .dao .impl ;
88
9+ import static com .ibm .fhir .persistence .jdbc .JDBCConstants .*;
10+
911import java .sql .CallableStatement ;
1012import java .sql .Connection ;
1113import java .sql .PreparedStatement ;
@@ -90,6 +92,8 @@ public class ResourceDAOImpl extends FHIRDbDAOImpl implements ResourceDAO {
9092 "FROM %s_RESOURCES R, %s_LOGICAL_RESOURCES LR WHERE R.LOGICAL_RESOURCE_ID = LR.LOGICAL_RESOURCE_ID AND " +
9193 "R.RESOURCE_ID IN " ;
9294
95+ private static final String SQL_ORDER_BY_IDS = "ORDER BY CASE R.RESOURCE_ID " ;
96+
9397 private static final String DERBY_PAGINATION_PARMS = "OFFSET ? ROWS FETCH NEXT ? ROWS ONLY" ;
9498
9599 private static final String DB2_PAGINATION_PARMS = "LIMIT ? OFFSET ?" ;
@@ -418,64 +422,7 @@ public List<Long> searchForIds(SqlQueryData queryData) throws FHIRPersistenceDat
418422 return resourceIds ;
419423 }
420424
421- @ Override
422- public List <Resource > searchByIds (String resourceType , List <Long > resourceIds ) throws FHIRPersistenceDataAccessException , FHIRPersistenceDBConnectException {
423- final String METHODNAME = "searchByIds" ;
424- log .entering (CLASSNAME , METHODNAME );
425-
426- if (resourceIds .isEmpty ()) {
427- return Collections .emptyList ();
428- }
429-
430- Connection connection = null ;
431- PreparedStatement stmt = null ;
432- ResultSet resultSet = null ;
433- String errMsg ;
434- StringBuilder idQuery = new StringBuilder ();
435- List <Resource > resources = new ArrayList <>();
436- String stmtString = null ;
437- long dbCallStartTime ;
438- double dbCallDuration ;
439-
440- try {
441- stmtString = String .format (this .getSearchByIdsSql (resourceType ));
442- idQuery .append (stmtString );
443- idQuery .append ("(" );
444- for (int i = 0 ; i < resourceIds .size (); i ++) {
445- if (i > 0 ) {
446- idQuery .append ("," );
447- }
448- idQuery .append (resourceIds .get (i ));
449- }
450- idQuery .append (")" );
451-
452- connection = this .getConnection ();
453- stmt = connection .prepareStatement (idQuery .toString ());
454- dbCallStartTime = System .nanoTime ();
455- resultSet = stmt .executeQuery ();
456- dbCallDuration = (System .nanoTime ()-dbCallStartTime )/1e6 ;
457- if (log .isLoggable (Level .FINE )) {
458- log .fine ("DB search by ids complete. SQL=[" + idQuery + "] executionTime=" + dbCallDuration + "ms" );
459- }
460- resources = this .createDTOs (resultSet );
461- } catch (FHIRPersistenceException e ) {
462- throw e ;
463- } catch (Throwable e ) {
464- FHIRPersistenceDataAccessException fx = new FHIRPersistenceDataAccessException ("Failure retrieving FHIR Resources" );
465- errMsg = "Failure retrieving FHIR Resources. SQL=[" + idQuery + "]" ;
466- throw severe (log , fx , errMsg , e );
467- } finally {
468- this .cleanup (resultSet , stmt , connection );
469- log .exiting (CLASSNAME , METHODNAME );
470- }
471- return resources ;
472- }
473-
474- protected String getSearchByIdsSql (String resourceType ) {
475- String stmtString ;
476- stmtString = String .format (SQL_SEARCH_BY_IDS , resourceType , resourceType );
477- return stmtString ;
478- }
425+
479426
480427 /**
481428 * Adds a resource type/ resource id pair to a candidate collection for population into the ResourceTypesCache.
@@ -734,78 +681,55 @@ public List<Resource> search(String sqlSelect) throws FHIRPersistenceDataAccessE
734681 }
735682
736683 @ Override
737- public List <Long > searchForIds (String sqlSelect ) throws FHIRPersistenceDataAccessException , FHIRPersistenceDBConnectException {
738- final String METHODNAME = "searchForIds" ;
739- log .entering (CLASSNAME , METHODNAME );
740-
741- List <Long > resourceIds = new ArrayList <>();
742- Connection connection = null ;
743- PreparedStatement stmt = null ;
744- ResultSet resultSet = null ;
745- String errMsg ;
746-
747- try {
748- connection = this .getConnection ();
749- stmt = connection .prepareStatement (sqlSelect );
750- resultSet = stmt .executeQuery ();
751- while (resultSet .next ()) {
752- resourceIds .add (resultSet .getLong (1 ));
753- }
754- } catch (FHIRPersistenceException e ) {
755- throw e ;
756- } catch (Throwable e ) {
757- // Log the SQL but don't expose it in the exception
758- FHIRPersistenceDataAccessException fx = new FHIRPersistenceDataAccessException ("Failure retrieving FHIR Resource Ids." );
759- errMsg = "Failure retrieving FHIR Resource Ids. SQL=" + sqlSelect ;
760- throw severe (log , fx , errMsg , e );
761- } finally {
762- this .cleanup (resultSet , stmt , connection );
763- log .exiting (CLASSNAME , METHODNAME );
764- }
765- return resourceIds ;
766- }
767-
768- @ Override
769- public List <Resource > searchByIds (List <Long > resourceIds ) throws FHIRPersistenceDataAccessException , FHIRPersistenceDBConnectException {
684+ public List <Resource > searchByIds (String resourceType , List <Long > resourceIds ) throws FHIRPersistenceDataAccessException , FHIRPersistenceDBConnectException {
770685 final String METHODNAME = "searchByIds" ;
771686 log .entering (CLASSNAME , METHODNAME );
772687
773688 if (resourceIds .isEmpty ()) {
774689 return Collections .emptyList ();
775690 }
776-
691+
777692 Connection connection = null ;
778693 PreparedStatement stmt = null ;
779694 ResultSet resultSet = null ;
780695 String errMsg ;
781696 StringBuilder idQuery = new StringBuilder ();
782697 List <Resource > resources = new ArrayList <>();
783-
698+ String stmtString = null ;
699+ long dbCallStartTime ;
700+ double dbCallDuration ;
701+
784702 try {
785- idQuery .append (SQL_SEARCH_BY_IDS );
703+ stmtString = getSearchByIdsSql (resourceType );
704+ idQuery .append (stmtString );
786705 idQuery .append ("(" );
706+ // resourceIds should have a max length of 1000 (the max page size)
707+ StringBuilder caseStmts = new StringBuilder ();
787708 for (int i = 0 ; i < resourceIds .size (); i ++) {
788709 if (i > 0 ) {
789710 idQuery .append ("," );
790711 }
791- idQuery .append ("?" );
712+ idQuery .append (resourceIds .get (i ));
713+
714+ // build up the caseStmts here so we only need to iterate the list once
715+ caseStmts .append (WHEN + resourceIds .get (i ) + THEN + i );
792716 }
793- idQuery .append (")" );
794-
717+ idQuery .append (") " + SQL_ORDER_BY_IDS + caseStmts + END );
718+
795719 connection = this .getConnection ();
796720 stmt = connection .prepareStatement (idQuery .toString ());
797- // Inject IDs into the prepared stmt.
798- for (int i = 0 ; i < resourceIds .size (); i ++) {
799- stmt .setObject (i +1 , resourceIds .get (i ));
800- }
721+ dbCallStartTime = System .nanoTime ();
801722 resultSet = stmt .executeQuery ();
723+ dbCallDuration = (System .nanoTime ()-dbCallStartTime )/1e6 ;
724+ if (log .isLoggable (Level .FINE )) {
725+ log .fine ("DB search by ids complete. SQL=[" + idQuery + "] executionTime=" + dbCallDuration + "ms" );
726+ }
802727 resources = this .createDTOs (resultSet );
803728 } catch (FHIRPersistenceException e ) {
804729 throw e ;
805730 } catch (Throwable e ) {
806- // Log the SQL but don't expose it in the exception
807- FHIRPersistenceDataAccessException fx = new FHIRPersistenceDataAccessException ("Failure retrieving FHIR Resources." );
808- errMsg = "Failure retrieving FHIR Resources. SQL=" + idQuery ;
731+ FHIRPersistenceDataAccessException fx = new FHIRPersistenceDataAccessException ("Failure retrieving FHIR Resources" );
732+ errMsg = "Failure retrieving FHIR Resources. SQL=[" + idQuery + "]" ;
809733 throw severe (log , fx , errMsg , e );
810734 } finally {
811735 this .cleanup (resultSet , stmt , connection );
@@ -814,6 +738,10 @@ public List<Resource> searchByIds(List<Long> resourceIds) throws FHIRPersistence
814738 return resources ;
815739 }
816740
741+ protected String getSearchByIdsSql (String resourceType ) {
742+ return String .format (SQL_SEARCH_BY_IDS , resourceType , resourceType );
743+ }
744+
817745 @ Override
818746 public int searchCount (String sqlSelectCount ) throws FHIRPersistenceDataAccessException , FHIRPersistenceDBConnectException {
819747 final String METHODNAME = "searchCount" ;
0 commit comments