1 56 57 package org.objectstyle.cayenne.access.util; 58 59 import java.sql.Types ; 60 import java.util.Collections ; 61 import java.util.HashMap ; 62 import java.util.Iterator ; 63 import java.util.List ; 64 import java.util.Map ; 65 66 import org.apache.commons.collections.Factory; 67 import org.objectstyle.cayenne.CayenneRuntimeException; 68 import org.objectstyle.cayenne.DataObject; 69 import org.objectstyle.cayenne.DataRow; 70 import org.objectstyle.cayenne.ObjectId; 71 import org.objectstyle.cayenne.access.DataContext; 72 import org.objectstyle.cayenne.map.DbAttribute; 73 import org.objectstyle.cayenne.map.DbJoin; 74 import org.objectstyle.cayenne.map.DbRelationship; 75 import org.objectstyle.cayenne.map.Entity; 76 import org.objectstyle.cayenne.map.ObjAttribute; 77 import org.objectstyle.cayenne.map.ObjEntity; 78 import org.objectstyle.cayenne.map.ObjRelationship; 79 import org.objectstyle.cayenne.query.BatchQuery; 80 import org.objectstyle.cayenne.query.InsertBatchQuery; 81 import org.objectstyle.cayenne.query.UpdateBatchQuery; 82 import org.objectstyle.cayenne.util.Util; 83 84 89 public class BatchQueryUtils { 90 91 private BatchQueryUtils() { 92 } 93 94 98 public static boolean updatesLOBColumns(BatchQuery query) { 99 boolean isInsert = query instanceof InsertBatchQuery; 100 boolean isUpdate = query instanceof UpdateBatchQuery; 101 102 if (!isInsert && !isUpdate) { 103 return false; 104 } 105 106 List updatedAttributes = (isInsert) 107 ? query.getDbAttributes() 108 : ((UpdateBatchQuery) query).getUpdatedAttributes(); 109 110 Iterator it = updatedAttributes.iterator(); 111 while (it.hasNext()) { 112 int type = ((DbAttribute) it.next()).getType(); 113 if (type == Types.CLOB || type == Types.BLOB) { 114 return true; 115 } 116 } 117 118 return false; 119 } 120 121 public static Map buildSnapshotForUpdate(DataObject o) { 122 DataContext context = o.getDataContext(); 123 Map committedSnapshot = context.getObjectStore().getSnapshot( 124 o.getObjectId(), 125 context); 126 Map currentSnapshot = o.getDataContext().currentSnapshot(o); 127 Map snapshot = null; 128 129 if (committedSnapshot == null || committedSnapshot.isEmpty()) { 130 snapshot = Collections.unmodifiableMap(currentSnapshot); 131 return snapshot; 132 } 133 else 134 snapshot = new HashMap (currentSnapshot.size()); 135 136 Iterator it = currentSnapshot.entrySet().iterator(); 137 while (it.hasNext()) { 138 Map.Entry entry = (Map.Entry ) it.next(); 139 String attrName = (String ) entry.getKey(); 140 Object newValue = entry.getValue(); 141 Object oldValue = committedSnapshot.get(attrName); 144 if (!Util.nullSafeEquals(oldValue, newValue)) 145 snapshot.put(attrName, newValue); 146 } 147 148 Iterator origit = committedSnapshot.entrySet().iterator(); 151 while (origit.hasNext()) { 152 Map.Entry entry = (Map.Entry ) origit.next(); 153 String attrName = (String ) entry.getKey(); 154 Object oldValue = entry.getValue(); 155 if (oldValue == null || currentSnapshot.containsKey(attrName)) 156 continue; 157 snapshot.put(attrName, null); 158 } 159 160 return Collections.unmodifiableMap(snapshot); 161 } 162 163 168 public static Map buildSnapshotForInsert( 169 ObjEntity entity, 170 DataObject o, 171 DbRelationship masterDependentRel) { 172 return buildSnapshotForInsert(entity, o, masterDependentRel, false); 173 } 174 175 182 public static Map buildSnapshotForInsert( 183 ObjEntity entity, 184 DataObject o, 185 DbRelationship masterDependentRel, 186 boolean supportsGeneratedKeys) { 187 188 boolean isMasterDbEntity = (masterDependentRel == null); 189 Map map = new HashMap (); 190 191 Map attrMap = entity.getAttributeMap(); 193 Iterator attributes = attrMap.entrySet().iterator(); 194 while (attributes.hasNext()) { 195 Map.Entry entry = (Map.Entry ) attributes.next(); 196 String attrName = (String ) entry.getKey(); 197 ObjAttribute objAttr = (ObjAttribute) entry.getValue(); 198 199 if (isMasterDbEntity && !objAttr.isCompound()) { 200 map.put(objAttr.getDbAttributePath(), o.readPropertyDirectly(attrName)); 201 } 202 else if (!isMasterDbEntity && objAttr.isCompound()) { 203 DbAttribute dbAttr = objAttr.getDbAttribute(); 204 if (dbAttr.getEntity() == masterDependentRel.getTargetEntity()) 205 map.put(dbAttr.getName(), o.readPropertyDirectly(attrName)); 206 } 207 } 208 209 Map relMap = entity.getRelationshipMap(); 211 Iterator relationships = relMap.entrySet().iterator(); 212 while (relationships.hasNext()) { 213 214 Map.Entry entry = (Map.Entry ) relationships.next(); 215 String relName = (String ) entry.getKey(); 216 ObjRelationship rel = (ObjRelationship) entry.getValue(); 217 218 if (rel.isSourceIndependentFromTargetChange()) { 219 continue; 220 } 221 222 DataObject target = (DataObject) o.readPropertyDirectly(relName); 223 if (target == null) { 224 continue; 225 } 226 227 Map targetKeyMap = target.getObjectId().getIdSnapshot(); 228 229 if (targetKeyMap == null) { 231 continue; 232 } 233 234 DbRelationship dbRel; 235 if (isMasterDbEntity) { 236 dbRel = (DbRelationship) rel.getDbRelationships().get(0); 237 } 238 else { 239 dbRel = (DbRelationship) rel.getDbRelationships().get(1); 240 if (dbRel.getSourceEntity() != masterDependentRel.getTargetEntity()) { 241 continue; 242 } 243 } 244 245 Iterator joins = dbRel.getJoins().iterator(); 248 while (joins.hasNext()) { 249 DbJoin join = (DbJoin) joins.next(); 250 Object value = targetKeyMap.get(join.getTargetName()); 251 if (value == null) { 252 if (supportsGeneratedKeys && join.getTarget().isGenerated()) { 253 value = new PropagatedValueFactory(target.getObjectId(), join 255 .getTargetName()); 256 } 257 else { 258 throw new CayenneRuntimeException( 259 "Some parts of FK are missing in snapshot, join: " + join); 260 } 261 } 262 263 map.put(join.getSourceName(), value); 264 } 265 } 266 267 Map thisIdParts = o.getObjectId().getIdSnapshot(); 272 if (thisIdParts != null) { 273 if (!isMasterDbEntity) { 274 thisIdParts = masterDependentRel 275 .targetPkSnapshotWithSrcSnapshot(thisIdParts); 276 } 277 Iterator itm = thisIdParts.keySet().iterator(); 279 while (itm.hasNext()) { 280 Object nextKey = itm.next(); 281 if (!map.containsKey(nextKey)) 282 map.put(nextKey, thisIdParts.get(nextKey)); 283 } 284 } 285 return map; 286 } 287 288 private static String getTargetDbAttributeName( 289 String srcDbAttributeName, 290 DbRelationship masterDependentRel) { 291 for (Iterator i = masterDependentRel.getJoins().iterator(); i.hasNext();) { 292 DbJoin join = (DbJoin) i.next(); 293 if (srcDbAttributeName.equals(join.getSourceName())) 294 return join.getTargetName(); 295 } 296 return null; 297 } 298 299 302 public static Map buildSnapshotForUpdate( 303 ObjEntity entity, 304 DataObject o, 305 DbRelationship masterDependentRel) { 306 307 boolean isRootDbEntity = (masterDependentRel == null); 308 DataContext context = o.getDataContext(); 309 DataRow committedSnapshot = context.getObjectStore().getSnapshot( 310 o.getObjectId(), 311 context); 312 DataRow currentSnapshot = o.getDataContext().currentSnapshot(o); 313 Map snapshot = new HashMap (currentSnapshot.size()); 314 315 if (committedSnapshot == null || committedSnapshot.isEmpty()) { 317 Iterator i = currentSnapshot.entrySet().iterator(); 318 while (i.hasNext()) { 319 Map.Entry entry = (Map.Entry ) i.next(); 320 String dbAttrPath = (String ) entry.getKey(); 321 boolean compoundDbAttr = dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0; 322 Object newValue = entry.getValue(); 323 if (isRootDbEntity && !compoundDbAttr) { 324 snapshot.put(dbAttrPath, newValue); 325 } 326 else if (!isRootDbEntity && compoundDbAttr) { 327 Iterator pathIterator = entity.getDbEntity().resolvePathComponents( 328 dbAttrPath); 329 if (pathIterator.hasNext() 330 && masterDependentRel.equals(pathIterator.next())) { 331 DbAttribute dbAttr = (DbAttribute) pathIterator.next(); 332 snapshot.put(dbAttr.getName(), newValue); 333 } 334 } 335 else if (!isRootDbEntity && !compoundDbAttr) { 336 String pkAttrName = getTargetDbAttributeName( 337 dbAttrPath, 338 masterDependentRel); 339 if (pkAttrName != null) 340 snapshot.put(pkAttrName, newValue); 341 } 342 } 343 return Collections.unmodifiableMap(snapshot); 344 } 345 346 Iterator it = currentSnapshot.entrySet().iterator(); 347 while (it.hasNext()) { 348 Map.Entry entry = (Map.Entry ) it.next(); 349 String dbAttrPath = (String ) entry.getKey(); 350 boolean compoundDbAttr = dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0; 351 Object newValue = entry.getValue(); 352 353 356 Object oldValue = committedSnapshot.get(dbAttrPath); 359 if (!Util.nullSafeEquals(oldValue, newValue)) { 360 361 if (!isRootDbEntity) { 362 if (compoundDbAttr) { 363 Iterator pathIterator = entity 364 .getDbEntity() 365 .resolvePathComponents(dbAttrPath); 366 if (pathIterator.hasNext() 367 && masterDependentRel.equals(pathIterator.next())) { 368 DbAttribute dbAttr = (DbAttribute) pathIterator.next(); 369 snapshot.put(dbAttr.getName(), newValue); 370 } 371 } 372 else { 373 String pkAttrName = getTargetDbAttributeName( 374 dbAttrPath, 375 masterDependentRel); 376 if (pkAttrName != null) 377 snapshot.put(pkAttrName, newValue); 378 } 379 } 380 else if (!compoundDbAttr) { 381 snapshot.put(dbAttrPath, newValue); 382 } 383 } 384 } 385 386 Iterator origit = committedSnapshot.entrySet().iterator(); 389 while (origit.hasNext()) { 390 Map.Entry entry = (Map.Entry ) origit.next(); 391 String dbAttrPath = (String ) entry.getKey(); 392 if (entry.getValue() == null || currentSnapshot.containsKey(dbAttrPath)) { 393 continue; 394 } 395 396 boolean compoundDbAttr = dbAttrPath.indexOf(Entity.PATH_SEPARATOR) > 0; 397 398 if (isRootDbEntity && !compoundDbAttr) { 399 snapshot.put(dbAttrPath, null); 400 } 401 else if (!isRootDbEntity && compoundDbAttr) { 402 Iterator pathIterator = entity.getDbEntity().resolvePathComponents( 403 dbAttrPath); 404 if (pathIterator.hasNext() 405 && masterDependentRel.equals(pathIterator.next())) { 406 DbAttribute dbAttr = (DbAttribute) pathIterator.next(); 407 snapshot.put(dbAttr.getName(), null); 408 } 409 } 410 else if (!isRootDbEntity && !compoundDbAttr) { 411 String pkAttrName = getTargetDbAttributeName( 412 dbAttrPath, 413 masterDependentRel); 414 if (pkAttrName != null) 415 snapshot.put(pkAttrName, null); 416 } 417 } 418 return Collections.unmodifiableMap(snapshot); 419 } 420 421 final static class PropagatedValueFactory implements Factory { 422 423 ObjectId masterID; 424 String masterKey; 425 426 PropagatedValueFactory(ObjectId masterID, String masterKey) { 427 this.masterID = masterID; 428 this.masterKey = masterKey; 429 } 430 431 public Object create() { 432 if (!masterID.isReplacementIdAttached()) { 433 throw new CayenneRuntimeException("Deferred propagated key (" 434 + masterKey 435 + ") wasn't generated for object with ID " 436 + masterID); 437 } 438 439 Map replacementId = masterID.getReplacementIdMap(); 440 Object value = replacementId.get(masterKey); 441 if (value == null) { 442 throw new CayenneRuntimeException("Deferred propagated key (" 443 + masterKey 444 + ") wasn't generated for object with ID " 445 + masterID); 446 } 447 448 return value; 449 } 450 } 451 } | Popular Tags |