/tests/com/google/appengine/datanucleus/jdo/JDOBatchDeleteTest.java
Java | 390 lines | 321 code | 42 blank | 27 comment | 5 complexity | bc190a5e0fe078cf0c4762a23811e8d4 MD5 | raw file
1/********************************************************************** 2Copyright (c) 2009 Google Inc. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15**********************************************************************/ 16package com.google.appengine.datanucleus.jdo; 17 18import com.google.appengine.api.datastore.DatastoreServiceConfig; 19import com.google.appengine.api.datastore.Entity; 20import com.google.appengine.api.datastore.Key; 21import com.google.appengine.api.datastore.KeyFactory; 22import com.google.appengine.datanucleus.Utils; 23import com.google.appengine.datanucleus.test.jdo.BidirectionalChildListJDO; 24import com.google.appengine.datanucleus.test.jdo.Flight; 25import com.google.appengine.datanucleus.test.jdo.HasKeyAncestorKeyPkJDO; 26import com.google.appengine.datanucleus.test.jdo.HasOneToManyListJDO; 27import com.google.appengine.datanucleus.test.jdo.HasOneToOneJDO; 28 29import java.lang.reflect.Method; 30 31import javax.jdo.JDOUserException; 32 33/** 34 * @author Max Ross <maxr@google.com> 35 */ 36public class JDOBatchDeleteTest extends JDOBatchTestCase { 37 38 private static Entity newFlightEntity() { 39 return Flight.newFlightEntity("Harold", "BOS", "MIA", 4, 2); 40 } 41 42 private static Entity newFlightEntity(Key parent, int childIndex) { 43 Entity e = Flight.newFlightEntity(parent, null, "Harold", "BOS", "MIA", 4, 2, 23); 44 e.setProperty("flights_INTEGER_IDX", childIndex); 45 return e; 46 } 47 48 private static Entity newBidirChildEntity(Key parent, int childIndex) { 49 Entity e = new Entity(BidirectionalChildListJDO.class.getSimpleName(), parent); 50 e.setProperty("bidirChildren_INTEGER_IDX", childIndex); 51 return e; 52 } 53 54 BatchRecorder newBatchRecorder() { 55 DatastoreServiceConfig config = getStoreManager().getDefaultDatastoreServiceConfigForReads(); 56 return new BatchRecorder(config) { 57 boolean isBatchMethod(Method method) { 58 return method.getName().equals("delete") && 59 (method.getParameterTypes().length == 1 && Iterable.class.isAssignableFrom(method.getParameterTypes()[0])) || 60 (method.getParameterTypes().length == 2 && Iterable.class.isAssignableFrom(method.getParameterTypes()[1])); 61 } 62 }; 63 } 64 65 public void testDeletePersistentAll_NoTxn() { 66 switchDatasource(PersistenceManagerFactoryName.nontransactional); 67 Key k1 = ds.put(newFlightEntity()); 68 Key k2 = ds.put(newFlightEntity()); 69 Flight f1 = pm.getObjectById(Flight.class, k1); 70 Flight f2 = pm.getObjectById(Flight.class, k2); 71 pm.deletePersistentAll(f1, f2); 72 assertEquals(0, countForClass(Flight.class)); 73 assertEquals(1, batchRecorder.batchOps); 74 75 Key k3 = ds.put(newFlightEntity()); 76 Key k4 = ds.put(newFlightEntity()); 77 Flight f3 = pm.getObjectById(Flight.class, k3); 78 Flight f4 = pm.getObjectById(Flight.class, k4); 79 pm.deletePersistentAll(Utils.newArrayList(f3, f4)); 80 assertEquals(0, countForClass(Flight.class)); 81 assertEquals(2, batchRecorder.batchOps); 82 } 83 84 public void testDeletePersistentAll_OneEntity_NoTxn() { 85 switchDatasource(PersistenceManagerFactoryName.nontransactional); 86 Key k1 = ds.put(newFlightEntity()); 87 Flight f1 = pm.getObjectById(Flight.class, k1); 88 pm.deletePersistentAll(f1); 89 assertEquals(0, countForClass(Flight.class)); 90 assertEquals(0, batchRecorder.batchOps); 91 92 Key k2 = ds.put(newFlightEntity()); 93 Flight f2 = pm.getObjectById(Flight.class, k2); 94 pm.deletePersistentAll(Utils.newArrayList(f2)); 95 assertEquals(0, countForClass(Flight.class)); 96 assertEquals(0, batchRecorder.batchOps); 97 } 98 99 public void testDeletePersistentAll_Txn_MultipleEntityGroups() { 100 switchDatasource(PersistenceManagerFactoryName.transactional); 101 Key k1 = ds.put(newFlightEntity()); 102 Key k2 = ds.put(newFlightEntity()); 103 beginTxn(); 104 Flight f1 = pm.getObjectById(Flight.class, k1); 105 commitTxn(); 106 beginTxn(); 107 Flight f2 = pm.getObjectById(Flight.class, k2); 108 commitTxn(); 109 beginTxn(); 110 try { 111 pm.deletePersistentAll(f1, f2); 112 fail("expected exception"); 113 } catch (JDOUserException e) { 114 // good 115 } 116 rollbackTxn(); 117 assertEquals(2, countForClass(Flight.class)); 118 // We don't get to the batch delete because we blow up 119 // before we get there. 120 assertEquals(0, batchRecorder.batchOps); 121 122 Key k3 = ds.put(newFlightEntity()); 123 Key k4 = ds.put(newFlightEntity()); 124 beginTxn(); 125 Flight f3 = pm.getObjectById(Flight.class, k3); 126 commitTxn(); 127 beginTxn(); 128 Flight f4 = pm.getObjectById(Flight.class, k4); 129 commitTxn(); 130 beginTxn(); 131 try { 132 pm.deletePersistentAll(Utils.newArrayList(f3, f4)); 133 fail("expected exception"); 134 } catch (JDOUserException e) { 135 // good 136 } 137 rollbackTxn(); 138 assertEquals(4, countForClass(Flight.class)); 139 assertEquals(0, batchRecorder.batchOps); 140 // cleanup outside tx 141 pm.deletePersistentAll(Utils.newArrayList(f1, f2, f3, f4)); 142 } 143 144 public void testDeletePersistentAll_Txn_OneEntityGroup() { 145 switchDatasource(PersistenceManagerFactoryName.transactional); 146 Key parentKey = KeyFactory.createKey("yar", 24); 147 Key k1 = ds.put(new Entity(HasKeyAncestorKeyPkJDO.class.getSimpleName(), parentKey)); 148 Key k2 = ds.put(new Entity(HasKeyAncestorKeyPkJDO.class.getSimpleName(), parentKey)); 149 beginTxn(); 150 HasKeyAncestorKeyPkJDO child1 = pm.getObjectById(HasKeyAncestorKeyPkJDO.class, k1); 151 HasKeyAncestorKeyPkJDO child2 = pm.getObjectById(HasKeyAncestorKeyPkJDO.class, k2); 152 pm.deletePersistentAll(child1, child2); 153 commitTxn(); 154 assertEquals(0, countForClass(HasKeyAncestorKeyPkJDO.class)); 155 assertEquals(1, batchRecorder.batchOps); 156 } 157 158 public void testDeletePersistentAll_OneEntity_Txn() { 159 switchDatasource(PersistenceManagerFactoryName.transactional); 160 Key k1 = ds.put(newFlightEntity()); 161 beginTxn(); 162 Flight f1 = pm.getObjectById(Flight.class, k1); 163 pm.deletePersistentAll(f1); 164 commitTxn(); 165 assertEquals(0, countForClass(Flight.class)); 166 assertEquals(0, batchRecorder.batchOps); 167 168 Key k2 = ds.put(newFlightEntity()); 169 beginTxn(); 170 Flight f2 = pm.getObjectById(Flight.class, k2); 171 pm.deletePersistentAll(Utils.newArrayList(f2)); 172 commitTxn(); 173 assertEquals(0, countForClass(Flight.class)); 174 assertEquals(0, batchRecorder.batchOps); 175 } 176 177 public void testDeletePersistentAll_CascadeDelete_OneToOne_NoTxn() { 178 switchDatasource(PersistenceManagerFactoryName.nontransactional); 179 Key k1 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName())); 180 Key k2 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName())); 181 ds.put(newFlightEntity(k1, 1)); 182 ds.put(newFlightEntity(k2, 1)); 183 HasOneToOneJDO parent1 = pm.getObjectById(HasOneToOneJDO.class, k1); 184 HasOneToOneJDO parent2 = pm.getObjectById(HasOneToOneJDO.class, k2); 185 pm.deletePersistentAll(parent1, parent2); 186 assertEquals(0, countForClass(HasOneToOneJDO.class)); 187 assertEquals(0, countForClass(Flight.class)); 188 assertEquals(1, batchRecorder.batchOps); 189 } 190 191 192 public void testDeletePersistentAll_CascadeDelete_OneToOne_MultipleEntityGroups_Txn() { 193 switchDatasource(PersistenceManagerFactoryName.transactional); 194 Key k1 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName())); 195 Key k2 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName())); 196 ds.put(newFlightEntity(k1, 1)); 197 ds.put(newFlightEntity(k2, 1)); 198 beginTxn(); 199 HasOneToOneJDO parent1 = pm.getObjectById(HasOneToOneJDO.class, k1); 200 commitTxn(); 201 beginTxn(); 202 HasOneToOneJDO parent2 = pm.getObjectById(HasOneToOneJDO.class, k2); 203 commitTxn(); 204 beginTxn(); 205 try { 206 pm.deletePersistentAll(parent1, parent2); 207 fail("expected exception"); 208 } catch (JDOUserException e) { 209 // good 210 } 211 rollbackTxn(); 212 assertEquals(2, countForClass(HasOneToOneJDO.class)); 213 assertEquals(2, countForClass(Flight.class)); 214 assertEquals(1, batchRecorder.batchOps); 215 // cleanup outside tx 216 pm.deletePersistentAll(parent1, parent2); 217 } 218 219 public void testDeletePersistentAll_CascadeDelete_OneToOne_OneEntityGroup_Txn() { 220 switchDatasource(PersistenceManagerFactoryName.transactional); 221 222 Key k1 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName(), KeyFactory.createKey("Yar", 43))); 223 Key k2 = ds.put(new Entity(HasOneToOneJDO.class.getSimpleName(), KeyFactory.createKey("Yar", 43))); 224 ds.put(newFlightEntity(k1, 1)); 225 ds.put(newFlightEntity(k2, 1)); 226 beginTxn(); 227 HasOneToOneJDO parent1 = pm.getObjectById(HasOneToOneJDO.class, k1); 228 HasOneToOneJDO parent2 = pm.getObjectById(HasOneToOneJDO.class, k2); 229 pm.deletePersistentAll(parent1, parent2); 230 commitTxn(); 231 assertEquals(0, countForClass(HasOneToOneJDO.class)); 232 assertEquals(0, countForClass(Flight.class)); 233 assertEquals(1, batchRecorder.batchOps); 234 } 235 236 public void testDeletePersistentAll_CascadeDelete_OneToMany_NoTxn() { 237 switchDatasource(PersistenceManagerFactoryName.nontransactional); 238 239 Entity owner1Entity = new Entity(HasOneToManyListJDO.class.getSimpleName()); 240 Key k1 = ds.put(owner1Entity); 241 Entity owner2Entity = new Entity(HasOneToManyListJDO.class.getSimpleName()); 242 Key k2 = ds.put(owner2Entity); 243 244 Entity fl1 = newFlightEntity(k1, 1); 245 Entity fl2 = newFlightEntity(k1, 2); 246 Entity fl3 = newFlightEntity(k2, 1); 247 Entity fl4 = newFlightEntity(k2, 2); 248 ds.put(fl1); 249 ds.put(fl2); 250 ds.put(fl3); 251 ds.put(fl4); 252 253 Entity bi1 = newBidirChildEntity(k1, 1); 254 Entity bi2 = newBidirChildEntity(k1, 2); 255 Entity bi3 = newBidirChildEntity(k2, 1); 256 Entity bi4 = newBidirChildEntity(k2, 2); 257 ds.put(bi1); 258 ds.put(bi2); 259 ds.put(bi3); 260 ds.put(bi4); 261 262 owner1Entity.setProperty("flights", Utils.newArrayList(fl1.getKey(), fl2.getKey())); 263 owner1Entity.setProperty("bidirChildren", Utils.newArrayList(bi1.getKey(), bi2.getKey())); 264 ds.put(owner1Entity); 265 266 owner2Entity.setProperty("flights", Utils.newArrayList(fl3.getKey(), fl4.getKey())); 267 owner2Entity.setProperty("bidirChildren", Utils.newArrayList(bi3.getKey(), bi4.getKey())); 268 ds.put(owner2Entity); 269 270 HasOneToManyListJDO parent1 = pm.getObjectById(HasOneToManyListJDO.class, k1); 271 assertEquals(2, parent1.getFlights().size()); 272 assertEquals(2, parent1.getBidirChildren().size()); 273 HasOneToManyListJDO parent2 = pm.getObjectById(HasOneToManyListJDO.class, k2); 274 assertEquals(2, parent2.getFlights().size()); 275 assertEquals(2, parent2.getBidirChildren().size()); 276 pm.deletePersistentAll(parent1, parent2); 277 assertEquals(0, countForClass(HasOneToManyListJDO.class)); 278 assertEquals(0, countForClass(Flight.class)); 279 assertEquals(0, countForClass(BidirectionalChildListJDO.class)); 280 assertEquals(1, batchRecorder.batchOps); 281 } 282 283 public void testDeletePersistentAll_CascadeDelete_OneToMany_MultipleEntityGroups_Txn() { 284 switchDatasource(PersistenceManagerFactoryName.transactional); 285 Entity owner1Entity = new Entity(HasOneToManyListJDO.class.getSimpleName()); 286 Key k1 = ds.put(owner1Entity); 287 Entity owner2Entity = new Entity(HasOneToManyListJDO.class.getSimpleName()); 288 Key k2 = ds.put(owner2Entity); 289 290 Entity fl1 = newFlightEntity(k1, 1); 291 Entity fl2 = newFlightEntity(k1, 2); 292 Entity fl3 = newFlightEntity(k2, 1); 293 Entity fl4 = newFlightEntity(k2, 2); 294 ds.put(fl1); 295 ds.put(fl2); 296 ds.put(fl3); 297 ds.put(fl4); 298 299 Entity bi1 = newBidirChildEntity(k1, 1); 300 Entity bi2 = newBidirChildEntity(k1, 2); 301 Entity bi3 = newBidirChildEntity(k2, 1); 302 Entity bi4 = newBidirChildEntity(k2, 2); 303 ds.put(bi1); 304 ds.put(bi2); 305 ds.put(bi3); 306 ds.put(bi4); 307 308 owner1Entity.setProperty("flights", Utils.newArrayList(fl1.getKey(), fl2.getKey())); 309 owner1Entity.setProperty("bidirChildren", Utils.newArrayList(bi1.getKey(), bi2.getKey())); 310 ds.put(owner1Entity); 311 312 owner2Entity.setProperty("flights", Utils.newArrayList(fl3.getKey(), fl4.getKey())); 313 owner2Entity.setProperty("bidirChildren", Utils.newArrayList(bi3.getKey(), bi4.getKey())); 314 ds.put(owner2Entity); 315 316 beginTxn(); 317 HasOneToManyListJDO parent1 = pm.getObjectById(HasOneToManyListJDO.class, k1); 318 assertEquals(2, parent1.getFlights().size()); 319 assertEquals(2, parent1.getBidirChildren().size()); 320 commitTxn(); 321 beginTxn(); 322 HasOneToManyListJDO parent2 = pm.getObjectById(HasOneToManyListJDO.class, k2); 323 assertEquals(2, parent2.getFlights().size()); 324 assertEquals(2, parent2.getBidirChildren().size()); 325 commitTxn(); 326 beginTxn(); 327 try { 328 pm.deletePersistentAll(parent1, parent2); 329 fail("expected exception"); 330 } catch (JDOUserException e) { 331 // good 332 } 333 rollbackTxn(); 334 assertEquals(2, countForClass(HasOneToManyListJDO.class)); 335 assertEquals(4, countForClass(Flight.class)); 336 assertEquals(4, countForClass(BidirectionalChildListJDO.class)); 337 assertEquals(1, batchRecorder.batchOps); 338 // cleanup outside tx 339 pm.deletePersistentAll(parent1, parent2); 340 } 341 342 public void testDeletePersistentAll_CascadeDelete_OneToMany_OneEntityGroup_Txn() { 343 switchDatasource(PersistenceManagerFactoryName.transactional); 344 Entity owner1Entity = new Entity(HasOneToManyListJDO.class.getSimpleName(), KeyFactory.createKey("yar", 43)); 345 Entity owner2Entity = new Entity(HasOneToManyListJDO.class.getSimpleName(), KeyFactory.createKey("yar", 43)); 346 Key k1 = ds.put(owner1Entity); 347 Key k2 = ds.put(owner2Entity); 348 349 Entity fl1 = newFlightEntity(k1, 1); 350 Entity fl2 = newFlightEntity(k1, 2); 351 Entity fl3 = newFlightEntity(k2, 1); 352 Entity fl4 = newFlightEntity(k2, 2); 353 ds.put(fl1); 354 ds.put(fl2); 355 ds.put(fl3); 356 ds.put(fl4); 357 358 Entity bi1 = newBidirChildEntity(k1, 1); 359 Entity bi2 = newBidirChildEntity(k1, 2); 360 Entity bi3 = newBidirChildEntity(k2, 1); 361 Entity bi4 = newBidirChildEntity(k2, 2); 362 ds.put(bi1); 363 ds.put(bi2); 364 ds.put(bi3); 365 ds.put(bi4); 366 367 owner1Entity.setProperty("flights", Utils.newArrayList(fl1.getKey(), fl2.getKey())); 368 owner1Entity.setProperty("bidirChildren", Utils.newArrayList(bi1.getKey(), bi2.getKey())); 369 ds.put(owner1Entity); 370 371 owner2Entity.setProperty("flights", Utils.newArrayList(fl3.getKey(), fl4.getKey())); 372 owner2Entity.setProperty("bidirChildren", Utils.newArrayList(bi3.getKey(), bi4.getKey())); 373 ds.put(owner2Entity); 374 375 beginTxn(); 376 HasOneToManyListJDO parent1 = pm.getObjectById(HasOneToManyListJDO.class, k1); 377 assertEquals(2, parent1.getFlights().size()); 378 assertEquals(2, parent1.getBidirChildren().size()); 379 HasOneToManyListJDO parent2 = pm.getObjectById(HasOneToManyListJDO.class, k2); 380 assertEquals(2, parent2.getFlights().size()); 381 assertEquals(2, parent2.getBidirChildren().size()); 382 pm.deletePersistentAll(parent1, parent2); 383 commitTxn(); 384 385 assertEquals(0, countForClass(HasOneToManyListJDO.class)); 386 assertEquals(0, countForClass(Flight.class)); 387 assertEquals(0, countForClass(BidirectionalChildListJDO.class)); 388 assertEquals(1, batchRecorder.batchOps); 389 } 390}