| 1 21 22 package org.opensubsystems.core.persist.db.hsqldb; 23 24 import java.sql.CallableStatement ; 25 import java.sql.Connection ; 26 import java.sql.PreparedStatement ; 27 import java.sql.ResultSet ; 28 import java.sql.SQLException ; 29 30 import org.opensubsystems.core.data.BasicDataObject; 31 import org.opensubsystems.core.data.DataObject; 32 import org.opensubsystems.core.data.ModifiableDataObject; 33 import org.opensubsystems.core.error.OSSDataCreateException; 34 import org.opensubsystems.core.error.OSSDataSaveException; 35 import org.opensubsystems.core.error.OSSDatabaseAccessException; 36 import org.opensubsystems.core.error.OSSException; 37 import org.opensubsystems.core.error.OSSInconsistentDataException; 38 import org.opensubsystems.core.persist.db.DatabaseDataUtils; 39 import org.opensubsystems.core.util.DatabaseUtils; 40 41 50 public final class HsqlDBDataUtils 51 { 52 58 public static class CachedInsertStatements 59 { 60 63 private boolean m_bIsInDomain; 64 65 68 private CallableStatement m_call; 69 70 73 private PreparedStatement m_select; 74 75 80 public CachedInsertStatements( 81 boolean bIsInDomain, 82 CallableStatement call, 83 PreparedStatement select 84 ) 85 { 86 super(); 87 88 m_bIsInDomain = bIsInDomain; 89 m_call = call; 90 m_select = select; 91 } 92 93 96 private CallableStatement getCall() 97 { 98 return m_call; 99 } 100 101 104 private PreparedStatement getSelect() 105 { 106 return m_select; 107 } 108 109 112 public boolean isInDomain() 113 { 114 return m_bIsInDomain; 115 } 116 117 } 118 119 125 public static class CachedUpdateStatements 126 { 127 130 private boolean m_bIsInDomain; 131 132 135 private PreparedStatement m_select; 136 137 141 public CachedUpdateStatements( 142 boolean bIsInDomain, 143 PreparedStatement select 144 ) 145 { 146 super(); 147 148 m_bIsInDomain = bIsInDomain; 149 m_select = select; 150 } 151 152 155 public PreparedStatement getSelect() 156 { 157 return m_select; 158 } 159 160 163 public boolean isInDomain() 164 { 165 return m_bIsInDomain; 166 } 167 168 } 169 170 172 175 private HsqlDBDataUtils( 176 ) 177 { 178 } 180 181 183 198 public static void insertAndFetchGeneratedValues( 199 Connection dbConnection, 200 PreparedStatement insertStatement, 201 boolean bIsInDomain, 202 String strTableName, 203 BasicDataObject data 204 ) throws SQLException , 205 OSSException 206 { 207 CachedInsertStatements cache = null; 208 209 try 210 { 211 cache = cacheStatementsForInsert( 212 dbConnection, bIsInDomain, strTableName, 213 data instanceof ModifiableDataObject); 214 insertAndFetchGeneratedValues(insertStatement, cache, data); 215 } 216 finally 217 { 218 closeStatements(cache); 219 } 220 } 221 222 235 public static void insertAndFetchGeneratedValues( 236 PreparedStatement insertStatement, 237 CachedInsertStatements cache, 238 BasicDataObject data 239 ) throws OSSException, 240 SQLException  241 { 242 ResultSet rsResults = null; 243 int iGeneratedKey = DataObject.NEW_ID; 244 245 insertStatement.executeUpdate(); 246 247 try 248 { 249 try 252 { 253 rsResults = cache.getCall().executeQuery(); 254 if (rsResults.next()) 255 { 256 iGeneratedKey = rsResults.getInt(1); 257 } 258 else 259 { 260 throw new OSSDataCreateException( 261 "Cannot read the generated ID from the database."); 262 } 263 } 264 finally 265 { 266 DatabaseUtils.closeResultSet(rsResults); 267 } 268 269 if (iGeneratedKey != DataObject.NEW_ID) 270 { 271 PreparedStatement selectStatement = null; 272 273 try 274 { 275 276 selectStatement = cache.getSelect(); 277 selectStatement.clearParameters(); 278 selectStatement.setInt(1, iGeneratedKey); 279 if (cache.isInDomain()) 280 { 281 selectStatement.setInt(2, data.getDomainId()); 282 } 283 rsResults = selectStatement.executeQuery(); 284 if (rsResults.next()) 285 { 286 data.setId(iGeneratedKey); 287 data.setCreationTimestamp(rsResults.getTimestamp(1)); 288 if (data instanceof ModifiableDataObject) 289 { 290 ((ModifiableDataObject)data).setModificationTimestamp( 291 rsResults.getTimestamp(2)); 292 } 293 } 294 else 295 { 296 throw new OSSDataCreateException( 297 "Cannot read the generated creation and modification " + 298 "time from the database."); 299 } 300 } 301 finally 302 { 303 DatabaseUtils.closeResultSet(rsResults); 304 } 305 } 306 } 307 catch (SQLException eExc) 308 { 309 throw new OSSDataCreateException( 310 "Cannot read the generated creation and modification time" + 311 " from the database.", eExc); 312 } 313 } 314 315 327 public static CachedInsertStatements cacheStatementsForInsert( 328 Connection dbConnection, 329 boolean bIsInDomain, 330 String strTableName, 331 boolean bModifiable 332 ) throws OSSException 333 { 334 StringBuffer sbQuery = new StringBuffer (); 335 CachedInsertStatements cache; 336 337 sbQuery.append("select CREATION_DATE"); 338 if (bModifiable) 339 { 340 sbQuery.append(", MODIFICATION_DATE"); 341 } 342 sbQuery.append(" from "); 343 sbQuery.append(strTableName); 344 sbQuery.append(" where ID = ?"); 345 if (bIsInDomain) 346 { 347 sbQuery.append(" and DOMAIN_ID = ?"); 348 } 349 350 try 351 { 352 cache = new CachedInsertStatements( 353 bIsInDomain, 354 dbConnection.prepareCall("call identity()"), 355 dbConnection.prepareStatement(sbQuery.toString())); 356 } 357 catch (SQLException eExc) 358 { 359 throw new OSSDatabaseAccessException( 360 "Cannot create jdbc statements to access the database.", 361 eExc); 362 } 363 364 return cache; 365 } 366 367 372 public static void closeStatements( 373 CachedInsertStatements cache 374 ) 375 { 376 if (cache != null) 377 { 378 DatabaseUtils.closeStatement(cache.getCall()); 379 DatabaseUtils.closeStatement(cache.getSelect()); 380 } 381 } 382 383 399 public static void updatedAndFetchGeneratedValues( 400 String strDataName, 401 Connection dbConnection, 402 PreparedStatement updateStatement, 403 boolean bIsInDomain, 404 String strTableName, 405 ModifiableDataObject data 406 ) throws SQLException , 407 OSSException 408 { 409 CachedUpdateStatements cache = null; 410 411 try 412 { 413 int iUpdateCount; 414 415 iUpdateCount = updateStatement.executeUpdate(); 416 if (iUpdateCount == 0) 417 { 418 DatabaseDataUtils.checkUpdateError(dbConnection, strDataName, 419 strTableName, data.getId(), data.getModificationTimestamp()); 420 } 421 else if (iUpdateCount > 1) 422 { 423 throw new OSSInconsistentDataException( 424 "Inconsistent database contains multiple (" 425 + iUpdateCount + ") records with the same ID" 426 + " and modified at the same time"); 427 } 428 429 cache = HsqlDBDataUtils.cacheStatementsForUpdate(dbConnection, bIsInDomain, 430 strTableName); 431 HsqlDBDataUtils.fetchModifiedTimestamps(cache, data); 432 } 433 finally 434 { 435 HsqlDBDataUtils.closeStatements(cache); 436 } 437 } 438 439 447 public static void fetchModifiedTimestamps( 448 CachedUpdateStatements cache, 449 ModifiableDataObject data 450 ) throws OSSException 451 { 452 ResultSet rsResults = null; 453 PreparedStatement selectStatement = null; 454 455 try 456 { 457 selectStatement = cache.getSelect(); 458 selectStatement.setInt(1, data.getId()); 459 if (cache.isInDomain()) 460 { 461 selectStatement.setInt(2, data.getDomainId()); 462 } 463 rsResults = selectStatement.executeQuery(); 464 if (rsResults.next()) 465 { 466 data.setModificationTimestamp(rsResults.getTimestamp(1)); 467 } 468 else 469 { 470 throw new OSSDataSaveException("Cannot read the generated modification " + 471 "time from the database."); 472 473 } 474 } 475 catch (SQLException eExc) 476 { 477 throw new OSSDataSaveException( 478 "Cannot read the generated modification time" + 479 " from the database.", 480 eExc); 481 } 482 finally 483 { 484 DatabaseUtils.closeResultSet(rsResults); 485 } 486 } 487 488 499 public static CachedUpdateStatements cacheStatementsForUpdate( 500 Connection dbConnection, 501 boolean bIsInDomain, 502 String strTableName 503 ) throws OSSException 504 { 505 StringBuffer sbQuery = new StringBuffer (); 506 CachedUpdateStatements cache; 507 508 sbQuery.append("select MODIFICATION_DATE from "); 509 sbQuery.append(strTableName); 510 sbQuery.append(" where ID = ?"); 511 if (bIsInDomain) 512 { 513 sbQuery.append(" and DOMAIN_ID = ?"); 514 } 515 516 try 517 { 518 cache = new CachedUpdateStatements( 519 bIsInDomain, 520 dbConnection.prepareStatement(sbQuery.toString())); 521 } 522 catch (SQLException eExc) 523 { 524 throw new OSSDatabaseAccessException( 525 "Cannot create jdbc statements to access the database.", 526 eExc); 527 } 528 529 return cache; 530 } 531 532 537 public static void closeStatements( 538 CachedUpdateStatements cache 539 ) 540 { 541 if (cache != null) 542 { 543 DatabaseUtils.closeStatement(cache.getSelect()); 544 } 545 } 546 } 547 | Popular Tags |