/tests/com/google/appengine/datanucleus/jpa/JPAOneToManyTestCase.java
Java | 1008 lines | 815 code | 156 blank | 37 comment | 1 complexity | 85cf41979ee4d3bffbdbf190acc7de17 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.jpa; 17 18import com.google.appengine.api.datastore.DatastoreService; 19import com.google.appengine.api.datastore.DatastoreServiceConfig; 20import com.google.appengine.api.datastore.Entity; 21import com.google.appengine.api.datastore.EntityNotFoundException; 22import com.google.appengine.api.datastore.Key; 23import com.google.appengine.api.datastore.KeyFactory; 24import com.google.appengine.api.datastore.Transaction; 25import com.google.appengine.api.datastore.TransactionOptions; 26import com.google.appengine.datanucleus.DatastoreServiceFactoryInternal; 27import com.google.appengine.datanucleus.DatastoreServiceInterceptor; 28import com.google.appengine.datanucleus.Utils; 29import com.google.appengine.datanucleus.test.jpa.BidirectionalChildJPA; 30import com.google.appengine.datanucleus.test.jpa.BidirectionalChildLongPkJPA; 31import com.google.appengine.datanucleus.test.jpa.BidirectionalChildUnencodedStringPkJPA; 32import com.google.appengine.datanucleus.test.jpa.Book; 33import com.google.appengine.datanucleus.test.jpa.HasKeyPkJPA; 34import com.google.appengine.datanucleus.test.jpa.HasOneToManyJPA; 35import com.google.appengine.datanucleus.test.jpa.HasOneToManyKeyPkJPA; 36import com.google.appengine.datanucleus.test.jpa.HasOneToManyLongPkJPA; 37import com.google.appengine.datanucleus.test.jpa.HasOneToManyUnencodedStringPkJPA; 38import com.google.appengine.datanucleus.test.jpa.HasOneToManyWithOrderByJPA; 39 40import org.easymock.EasyMock; 41 42import java.lang.reflect.Method; 43import java.util.Collections; 44import java.util.List; 45 46import javax.persistence.PersistenceException; 47 48import static com.google.appengine.datanucleus.TestUtils.assertKeyParentEquals; 49 50/** 51 * @author Max Ross <maxr@google.com> 52 */ 53abstract class JPAOneToManyTestCase extends JPATestCase { 54 55 void testInsert_NewParentAndChild(BidirectionalChildJPA bidirChild, HasOneToManyJPA parent, 56 StartEnd startEnd) 57 throws Exception { 58 bidirChild.setChildVal("yam"); 59 60 Book b = newBook(); 61 62 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 63 hasKeyPk.setStr("yag"); 64 65 parent.getBidirChildren().add(bidirChild); 66 bidirChild.setParent(parent); 67 parent.getBooks().add(b); 68 parent.getHasKeyPks().add(hasKeyPk); 69 parent.setVal("yar"); 70 71 startEnd.start(); 72 em.persist(parent); 73 startEnd.end(); 74 75 assertNotNull(bidirChild.getId()); 76 assertNotNull(b.getId()); 77 assertNotNull(hasKeyPk.getId()); 78 79 Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId())); 80 assertNotNull(bidirChildEntity); 81 assertEquals("yam", bidirChildEntity.getProperty("childVal")); 82 assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey()); 83 assertKeyParentEquals(parent.getId(), bidirChildEntity, bidirChild.getId()); 84 85 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 86 assertNotNull(bookEntity); 87 assertEquals("max", bookEntity.getProperty("author")); 88 assertEquals("22333", bookEntity.getProperty("isbn")); 89 assertEquals("yam", bookEntity.getProperty("title")); 90 assertEquals(KeyFactory.stringToKey(b.getId()), bookEntity.getKey()); 91 assertKeyParentEquals(parent.getId(), bookEntity, b.getId()); 92 93 Entity hasKeyPkEntity = ds.get(hasKeyPk.getId()); 94 assertNotNull(hasKeyPkEntity); 95 assertEquals("yag", hasKeyPkEntity.getProperty("str")); 96 assertEquals(hasKeyPk.getId(), hasKeyPkEntity.getKey()); 97 assertKeyParentEquals(parent.getId(), hasKeyPkEntity, hasKeyPk.getId()); 98 99 Entity parentEntity = ds.get(KeyFactory.stringToKey(parent.getId())); 100 assertNotNull(parentEntity); 101 assertEquals(4, parentEntity.getProperties().size()); 102 assertEquals("yar", parentEntity.getProperty("val")); 103 assertEquals(Collections.singletonList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren")); 104 assertEquals(Collections.singletonList(bookEntity.getKey()), parentEntity.getProperty("books")); 105 assertEquals(Collections.singletonList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks")); 106 107 assertCountsInDatastore(parent.getClass(), bidirChild.getClass(), 1, 1); 108 } 109 110 void testInsert_ExistingParentNewChild(BidirectionalChildJPA bidirChild, HasOneToManyJPA pojo, 111 StartEnd startEnd) throws Exception { 112 pojo.setVal("yar"); 113 114 startEnd.start(); 115 em.persist(pojo); 116 startEnd.end(); 117 assertNotNull(pojo.getId()); 118 assertTrue(pojo.getBooks().isEmpty()); 119 assertTrue(pojo.getHasKeyPks().isEmpty()); 120 assertTrue(pojo.getBidirChildren().isEmpty()); 121 122 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 123 assertNotNull(pojoEntity); 124 assertEquals(4, pojoEntity.getProperties().size()); 125 assertTrue(pojoEntity.hasProperty("bidirChildren")); 126 assertNull(pojoEntity.getProperty("bidirChildren")); 127 assertTrue(pojoEntity.hasProperty("books")); 128 assertNull(pojoEntity.getProperty("books")); 129 assertTrue(pojoEntity.hasProperty("hasKeyPks")); 130 assertNull(pojoEntity.getProperty("hasKeyPks")); 131 132 startEnd.start(); 133 Book b = newBook(); 134 pojo.getBooks().add(b); 135 136 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 137 hasKeyPk.setStr("yag"); 138 pojo.getHasKeyPks().add(hasKeyPk); 139 140 bidirChild.setChildVal("yam"); 141 pojo.getBidirChildren().add(bidirChild); 142 bidirChild.setParent(pojo); 143 144 em.merge(pojo); 145 startEnd.end(); 146 147 assertNotNull(bidirChild.getId()); 148 assertNotNull(bidirChild.getParent()); 149 assertNotNull(b.getId()); 150 assertNotNull(hasKeyPk.getId()); 151 152 Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId())); 153 assertNotNull(bidirChildEntity); 154 assertEquals("yam", bidirChildEntity.getProperty("childVal")); 155 assertEquals(KeyFactory.stringToKey(bidirChild.getId()), bidirChildEntity.getKey()); 156 assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidirChild.getId()); 157 158 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 159 assertNotNull(bookEntity); 160 assertEquals("max", bookEntity.getProperty("author")); 161 assertEquals("22333", bookEntity.getProperty("isbn")); 162 assertEquals("yam", bookEntity.getProperty("title")); 163 assertEquals(KeyFactory.stringToKey(b.getId()), bookEntity.getKey()); 164 assertKeyParentEquals(pojo.getId(), bookEntity, b.getId()); 165 166 Entity hasKeyPkEntity = ds.get(hasKeyPk.getId()); 167 assertNotNull(hasKeyPkEntity); 168 assertEquals("yag", hasKeyPkEntity.getProperty("str")); 169 assertEquals(hasKeyPk.getId(), hasKeyPkEntity.getKey()); 170 assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getId()); 171 172 Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 173 assertNotNull(parentEntity); 174 assertEquals(4, parentEntity.getProperties().size()); 175 assertEquals("yar", parentEntity.getProperty("val")); 176 assertEquals(Collections.singletonList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren")); 177 assertEquals(Collections.singletonList(bookEntity.getKey()), parentEntity.getProperty("books")); 178 assertEquals(Collections.singletonList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks")); 179 180 assertCountsInDatastore(pojo.getClass(), bidirChild.getClass(), 1, 1); 181 } 182 183 void testUpdate_UpdateChildWithMerge(BidirectionalChildJPA bidir, HasOneToManyJPA pojo, 184 StartEnd startEnd) throws Exception { 185 Book b = newBook(); 186 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 187 188 pojo.getBooks().add(b); 189 pojo.getHasKeyPks().add(hasKeyPk); 190 pojo.getBidirChildren().add(bidir); 191 bidir.setParent(pojo); 192 193 startEnd.start(); 194 em.persist(pojo); 195 startEnd.end(); 196 197 assertNotNull(b.getId()); 198 assertNotNull(hasKeyPk.getId()); 199 assertNotNull(bidir.getId()); 200 assertNotNull(pojo.getId()); 201 202 startEnd.start(); 203 b.setIsbn("yam"); 204 hasKeyPk.setStr("yar"); 205 bidir.setChildVal("yap"); 206 em.merge(pojo); 207 startEnd.end(); 208 209 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 210 assertNotNull(bookEntity); 211 assertEquals("yam", bookEntity.getProperty("isbn")); 212 assertKeyParentEquals(pojo.getId(), bookEntity, b.getId()); 213 214 Entity hasKeyPkEntity = ds.get(hasKeyPk.getId()); 215 assertNotNull(hasKeyPkEntity); 216 assertEquals("yar", hasKeyPkEntity.getProperty("str")); 217 assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getId()); 218 219 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId())); 220 assertNotNull(bidirEntity); 221 assertEquals("yap", bidirEntity.getProperty("childVal")); 222 assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId()); 223 224 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1); 225 } 226 227 void testUpdate_UpdateChild(BidirectionalChildJPA bidir, HasOneToManyJPA pojo, 228 StartEnd startEnd) throws Exception { 229 Book b = newBook(); 230 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 231 232 pojo.getBooks().add(b); 233 pojo.getHasKeyPks().add(hasKeyPk); 234 pojo.getBidirChildren().add(bidir); 235 bidir.setParent(pojo); 236 237 startEnd.start(); 238 em.persist(pojo); 239 startEnd.end(); 240 241 assertNotNull(b.getId()); 242 assertNotNull(hasKeyPk.getId()); 243 assertNotNull(bidir.getId()); 244 assertNotNull(pojo.getId()); 245 246 startEnd.start(); 247 pojo = em.find(pojo.getClass(), pojo.getId()); 248 pojo.getBooks().iterator().next().setIsbn("yam"); 249 pojo.getHasKeyPks().iterator().next().setStr("yar"); 250 pojo.getBidirChildren().iterator().next().setChildVal("yap"); 251 startEnd.end(); 252 253 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 254 assertNotNull(bookEntity); 255 assertEquals("yam", bookEntity.getProperty("isbn")); 256 assertKeyParentEquals(pojo.getId(), bookEntity, b.getId()); 257 258 Entity hasKeyPkEntity = ds.get(hasKeyPk.getId()); 259 assertNotNull(hasKeyPkEntity); 260 assertEquals("yar", hasKeyPkEntity.getProperty("str")); 261 assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk.getId()); 262 263 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId())); 264 assertNotNull(bidirEntity); 265 assertEquals("yap", bidirEntity.getProperty("childVal")); 266 assertKeyParentEquals(pojo.getId(), bidirEntity, bidir.getId()); 267 268 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1); 269 } 270 271 void testUpdate_NullOutChildren(BidirectionalChildJPA bidir, HasOneToManyJPA pojo, 272 StartEnd startEnd) throws Exception { 273 Book b = newBook(); 274 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 275 276 pojo.getBooks().add(b); 277 pojo.getHasKeyPks().add(hasKeyPk); 278 pojo.getBidirChildren().add(bidir); 279 bidir.setParent(pojo); 280 281 startEnd.start(); 282 em.persist(pojo); 283 startEnd.end(); 284 285 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1); 286 287 startEnd.start(); 288 pojo.nullBooks(); 289 pojo.nullHasKeyPks(); 290 pojo.nullBidirChildren(); 291 em.merge(pojo); 292 startEnd.end(); 293 294 try { 295 ds.get(KeyFactory.stringToKey(b.getId())); 296 fail("expected enfe"); 297 } catch (EntityNotFoundException enfe) { 298 // good 299 } 300 301 try { 302 ds.get(hasKeyPk.getId()); 303 fail("expected enfe"); 304 } catch (EntityNotFoundException enfe) { 305 // good 306 } 307 308 try { 309 ds.get(KeyFactory.stringToKey(bidir.getId())); 310 fail("expected enfe"); 311 } catch (EntityNotFoundException enfe) { 312 // good 313 } 314 315 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 316 assertEquals(4, pojoEntity.getProperties().size()); 317 assertTrue(pojoEntity.hasProperty("bidirChildren")); 318 assertNull(pojoEntity.getProperty("bidirChildren")); 319 assertTrue(pojoEntity.hasProperty("books")); 320 assertNull(pojoEntity.getProperty("books")); 321 assertTrue(pojoEntity.hasProperty("hasKeyPks")); 322 assertNull(pojoEntity.getProperty("hasKeyPks")); 323 324 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 0); 325 } 326 327 void testUpdate_ClearOutChildren(BidirectionalChildJPA bidir, HasOneToManyJPA pojo, 328 StartEnd startEnd) throws Exception { 329 Book b = newBook(); 330 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 331 332 pojo.getBooks().add(b); 333 pojo.getHasKeyPks().add(hasKeyPk); 334 pojo.getBidirChildren().add(bidir); 335 bidir.setParent(pojo); 336 337 startEnd.start(); 338 em.persist(pojo); 339 startEnd.end(); 340 341 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 1); 342 343 startEnd.start(); 344 pojo.getBooks().clear(); 345 pojo.getHasKeyPks().clear(); 346 pojo.getBidirChildren().clear(); 347 em.merge(pojo); 348 startEnd.end(); 349 350 try { 351 ds.get(KeyFactory.stringToKey(b.getId())); 352 fail("expected enfe"); 353 } catch (EntityNotFoundException enfe) { 354 // good 355 } 356 357 try { 358 ds.get(hasKeyPk.getId()); 359 fail("expected enfe"); 360 } catch (EntityNotFoundException enfe) { 361 // good 362 } 363 364 try { 365 ds.get(KeyFactory.stringToKey(bidir.getId())); 366 fail("expected enfe"); 367 } catch (EntityNotFoundException enfe) { 368 // good 369 } 370 371 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 372 assertEquals(4, pojoEntity.getProperties().size()); 373 assertTrue(pojoEntity.hasProperty("bidirChildren")); 374 assertNull(pojoEntity.getProperty("bidirChildren")); 375 assertTrue(pojoEntity.hasProperty("books")); 376 assertNull(pojoEntity.getProperty("books")); 377 assertTrue(pojoEntity.hasProperty("hasKeyPks")); 378 assertNull(pojoEntity.getProperty("hasKeyPks")); 379 380 assertCountsInDatastore(pojo.getClass(), bidir.getClass(), 1, 0); 381 } 382 383 void testFindWithOrderBy(Class<? extends HasOneToManyWithOrderByJPA> pojoClass, 384 StartEnd startEnd) throws Exception { 385 getExecutionContext().getNucleusContext().getPersistenceConfiguration().setProperty( 386 "datanucleus.appengine.allowMultipleRelationsOfSameType", true); 387 388 Entity pojoEntity = new Entity(pojoClass.getSimpleName()); 389 ds.put(pojoEntity); 390 391 Entity bookEntity1 = Book.newBookEntity(pojoEntity.getKey(), "auth1", "22222", "title 1"); 392 ds.put(bookEntity1); 393 394 Entity bookEntity2 = Book.newBookEntity(pojoEntity.getKey(), "auth2", "22222", "title 2"); 395 ds.put(bookEntity2); 396 397 Entity bookEntity3 = Book.newBookEntity(pojoEntity.getKey(), "auth1", "22221", "title 0"); 398 ds.put(bookEntity3); 399 400 pojoEntity.setProperty("booksByAuthorAndTitle", Utils.newArrayList(bookEntity2.getKey(), bookEntity3.getKey(), bookEntity1.getKey())); 401 pojoEntity.setProperty("booksByIdAndAuthor", Utils.newArrayList(bookEntity3.getKey(), bookEntity2.getKey(), bookEntity1.getKey())); 402 pojoEntity.setProperty("booksByAuthorAndId", Utils.newArrayList(bookEntity2.getKey(), bookEntity1.getKey(), bookEntity3.getKey())); 403 ds.put(pojoEntity); 404 405 startEnd.start(); 406 HasOneToManyWithOrderByJPA pojo = 407 em.find(pojoClass, KeyFactory.keyToString(pojoEntity.getKey())); 408 assertNotNull(pojo); 409 assertNotNull(pojo.getBooksByAuthorAndTitle()); 410 assertEquals(3, pojo.getBooksByAuthorAndTitle().size()); 411 assertEquals("title 2", pojo.getBooksByAuthorAndTitle().get(0).getTitle()); 412 assertEquals("title 0", pojo.getBooksByAuthorAndTitle().get(1).getTitle()); 413 assertEquals("title 1", pojo.getBooksByAuthorAndTitle().get(2).getTitle()); 414 415 assertNotNull(pojo.getBooksByIdAndAuthor()); 416 assertEquals(3, pojo.getBooksByIdAndAuthor().size()); 417 assertEquals("title 0", pojo.getBooksByIdAndAuthor().get(0).getTitle()); 418 assertEquals("title 2", pojo.getBooksByIdAndAuthor().get(1).getTitle()); 419 assertEquals("title 1", pojo.getBooksByIdAndAuthor().get(2).getTitle()); 420 421 assertNotNull(pojo.getBooksByAuthorAndId()); 422 assertEquals(3, pojo.getBooksByAuthorAndId().size()); 423 assertEquals("title 2", pojo.getBooksByAuthorAndId().get(0).getTitle()); 424 assertEquals("title 1", pojo.getBooksByAuthorAndId().get(1).getTitle()); 425 assertEquals("title 0", pojo.getBooksByAuthorAndId().get(2).getTitle()); 426 427 startEnd.end(); 428 } 429 430 void testFind(Class<? extends HasOneToManyJPA> pojoClass, 431 Class<? extends BidirectionalChildJPA> bidirClass, 432 StartEnd startEnd) throws Exception { 433 Entity pojoEntity = new Entity(pojoClass.getSimpleName()); 434 ds.put(pojoEntity); 435 436 Entity bookEntity = Book.newBookEntity(pojoEntity.getKey(), "auth1", "22222", "title 1"); 437 ds.put(bookEntity); 438 439 Entity hasKeyPkEntity = new Entity(HasKeyPkJPA.class.getSimpleName(), pojoEntity.getKey()); 440 hasKeyPkEntity.setProperty("str", "yar"); 441 ds.put(hasKeyPkEntity); 442 443 Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey()); 444 bidirEntity.setProperty("childVal", "yap"); 445 ds.put(bidirEntity); 446 447 pojoEntity.setProperty("books", Utils.newArrayList(bookEntity.getKey())); 448 pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey())); 449 pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey())); 450 ds.put(pojoEntity); 451 452 startEnd.start(); 453 HasOneToManyJPA pojo = em.find(pojoClass, KeyFactory.keyToString(pojoEntity.getKey())); 454 assertNotNull(pojo); 455 assertNotNull(pojo.getBooks()); 456 assertEquals(1, pojo.getBooks().size()); 457 assertEquals("auth1", pojo.getBooks().iterator().next().getAuthor()); 458 assertNotNull(pojo.getHasKeyPks()); 459 assertEquals(1, pojo.getHasKeyPks().size()); 460 assertEquals("yar", pojo.getHasKeyPks().iterator().next().getStr()); 461 assertNotNull(pojo.getBidirChildren()); 462 assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal()); 463 assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent()); 464 startEnd.end(); 465 } 466 467 void testQuery(Class<? extends HasOneToManyJPA> pojoClass, 468 Class<? extends BidirectionalChildJPA> bidirClass, 469 StartEnd startEnd) throws Exception { 470 Entity pojoEntity = new Entity(pojoClass.getSimpleName()); 471 ds.put(pojoEntity); 472 473 Entity bookEntity = Book.newBookEntity(pojoEntity.getKey(), "auth", "22222", "the title"); 474 ds.put(bookEntity); 475 476 Entity hasKeyPkEntity = new Entity(HasKeyPkJPA.class.getSimpleName(), pojoEntity.getKey()); 477 hasKeyPkEntity.setProperty("str", "yar"); 478 ds.put(hasKeyPkEntity); 479 480 Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey()); 481 bidirEntity.setProperty("childVal", "yap"); 482 ds.put(bidirEntity); 483 484 pojoEntity.setProperty("books", Utils.newArrayList(bookEntity.getKey())); 485 pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey())); 486 pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey())); 487 ds.put(pojoEntity); 488 489 javax.persistence.Query q = em.createQuery( 490 "select from " + pojoClass.getName() + " b where id = :key"); 491 q.setParameter("key", KeyFactory.keyToString(pojoEntity.getKey())); 492 startEnd.start(); 493 @SuppressWarnings("unchecked") 494 List<HasOneToManyJPA> result = (List<HasOneToManyJPA>) q.getResultList(); 495 assertEquals(1, result.size()); 496 HasOneToManyJPA pojo = result.get(0); 497 assertNotNull(pojo.getBooks()); 498 assertEquals(1, pojo.getBooks().size()); 499 assertEquals("auth", pojo.getBooks().iterator().next().getAuthor()); 500 assertEquals(1, pojo.getBooks().size()); 501 assertNotNull(pojo.getHasKeyPks()); 502 assertEquals(1, pojo.getHasKeyPks().size()); 503 assertEquals("yar", pojo.getHasKeyPks().iterator().next().getStr()); 504 assertNotNull(pojo.getBidirChildren()); 505 assertEquals(1, pojo.getBidirChildren().size()); 506 assertEquals("yap", pojo.getBidirChildren().iterator().next().getChildVal()); 507 assertEquals(pojo, pojo.getBidirChildren().iterator().next().getParent()); 508 startEnd.end(); 509 } 510 511 void testChildFetchedLazily(Class<? extends HasOneToManyJPA> pojoClass, 512 Class<? extends BidirectionalChildJPA> bidirClass) throws Exception { 513 DatastoreServiceConfig config = getStoreManager().getDefaultDatastoreServiceConfigForReads(); 514 // force a new emf to get created after we've installed our own 515 // DatastoreService mock 516 emf.close(); 517 tearDown(); 518 DatastoreService mockDatastore = EasyMock.createMock(DatastoreService.class); 519 DatastoreService original = DatastoreServiceFactoryInternal.getDatastoreService(config); 520 DatastoreServiceFactoryInternal.setDatastoreService(mockDatastore); 521 try { 522 setUp(); 523 524 Entity pojoEntity = new Entity(pojoClass.getSimpleName()); 525 ds.put(pojoEntity); 526 527 Entity bookEntity = Book.newBookEntity(pojoEntity.getKey(), "auth", "22222", "the title"); 528 ds.put(bookEntity); 529 530 Entity hasKeyPkEntity = new Entity(HasKeyPkJPA.class.getSimpleName(), pojoEntity.getKey()); 531 hasKeyPkEntity.setProperty("str", "yar"); 532 ds.put(hasKeyPkEntity); 533 534 Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey()); 535 bidirEntity.setProperty("childVal", "yap"); 536 ds.put(bidirEntity); 537 538 Transaction txn = EasyMock.createMock(Transaction.class); 539 EasyMock.expect(txn.getId()).andReturn("1").times(2); 540 txn.commit(); 541 EasyMock.expectLastCall(); 542 EasyMock.replay(txn); 543 EasyMock.expect(mockDatastore.beginTransaction(EasyMock.isA(TransactionOptions.class))).andReturn(txn); 544 // the only get we're going to perform is for the pojo 545 EasyMock.expect(mockDatastore.get(txn, pojoEntity.getKey())).andReturn(pojoEntity); 546 EasyMock.replay(mockDatastore); 547 548 beginTxn(); 549 HasOneToManyJPA pojo = em.find(pojoClass, KeyFactory.keyToString(pojoEntity.getKey())); 550 assertNotNull(pojo); 551 pojo.getId(); 552 commitTxn(); 553 } finally { 554 // need to close the pmf before we restore the original datastore service 555 emf.close(); 556 DatastoreServiceFactoryInternal.setDatastoreService(original); 557 } 558 EasyMock.verify(mockDatastore); 559 } 560 561 void testDeleteParentDeletesChild(Class<? extends HasOneToManyJPA> pojoClass, 562 Class<? extends BidirectionalChildJPA> bidirClass, 563 StartEnd startEnd) throws Exception { 564 Entity pojoEntity = new Entity(pojoClass.getSimpleName()); 565 ds.put(pojoEntity); 566 567 Entity bookEntity = Book.newBookEntity(pojoEntity.getKey(), "auth", "22222", "the title"); 568 ds.put(bookEntity); 569 570 Entity hasKeyPkEntity = new Entity(HasKeyPkJPA.class.getSimpleName(), pojoEntity.getKey()); 571 hasKeyPkEntity.setProperty("str", "yar"); 572 ds.put(hasKeyPkEntity); 573 574 Entity bidirEntity = new Entity(bidirClass.getSimpleName(), pojoEntity.getKey()); 575 bidirEntity.setProperty("childVal", "yap"); 576 ds.put(bidirEntity); 577 578 pojoEntity.setProperty("books", Utils.newArrayList(bookEntity.getKey())); 579 pojoEntity.setProperty("hasKeyPks", Utils.newArrayList(hasKeyPkEntity.getKey())); 580 pojoEntity.setProperty("bidirChildren", Utils.newArrayList(bidirEntity.getKey())); 581 ds.put(pojoEntity); 582 583 startEnd.start(); 584 HasOneToManyJPA pojo = em.find(pojoClass, KeyFactory.keyToString(pojoEntity.getKey())); 585 em.remove(pojo); 586 startEnd.end(); 587 assertCountsInDatastore(pojoClass, bidirClass, 0, 0); 588 } 589 590 private static int nextId = 0; 591 592 static String nextNamedKey() { 593 return "a" + nextId++; 594 } 595 596 public void testRemoveObject(HasOneToManyJPA pojo, BidirectionalChildJPA bidir1, 597 BidirectionalChildJPA bidir2, 598 StartEnd startEnd) throws Exception { 599 pojo.setVal("yar"); 600 bidir1.setChildVal("yam1"); 601 bidir2.setChildVal("yam2"); 602 Book b1 = newBook(); 603 Book b2 = newBook(); 604 b2.setTitle("another title"); 605 HasKeyPkJPA hasKeyPk1 = new HasKeyPkJPA(nextNamedKey()); 606 HasKeyPkJPA hasKeyPk2 = new HasKeyPkJPA(nextNamedKey()); 607 hasKeyPk2.setStr("yar 2"); 608 pojo.getBooks().add(b1); 609 pojo.getBooks().add(b2); 610 pojo.getHasKeyPks().add(hasKeyPk1); 611 pojo.getHasKeyPks().add(hasKeyPk2); 612 pojo.getBidirChildren().add(bidir1); 613 pojo.getBidirChildren().add(bidir2); 614 615 startEnd.start(); 616 em.persist(pojo); 617 startEnd.end(); 618 619 assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), 1, 2); 620 621 String bidir1Id = bidir1.getId(); 622 String bookId = b1.getId(); 623 Key hasKeyPk1Key = hasKeyPk1.getId(); 624 pojo.getBidirChildren().remove(bidir1); 625 pojo.getBooks().remove(b1); 626 pojo.getHasKeyPks().remove(hasKeyPk1); 627 628 startEnd.start(); 629 em.merge(pojo); 630 startEnd.end(); 631 632 startEnd.start(); 633 pojo = em.find(pojo.getClass(), pojo.getId()); 634 assertNotNull(pojo.getId()); 635 assertEquals(1, pojo.getBooks().size()); 636 assertEquals(1, pojo.getHasKeyPks().size()); 637 assertEquals(1, pojo.getBidirChildren().size()); 638 assertNotNull(bidir2.getId()); 639 assertNotNull(bidir2.getParent()); 640 assertNotNull(b2.getId()); 641 assertNotNull(hasKeyPk2.getId()); 642 assertEquals(bidir2.getId(), pojo.getBidirChildren().iterator().next().getId()); 643 assertEquals(hasKeyPk2.getId(), pojo.getHasKeyPks().iterator().next().getId()); 644 assertEquals(b2.getId(), pojo.getBooks().iterator().next().getId()); 645 646 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 647 assertNotNull(pojoEntity); 648 assertEquals(4, pojoEntity.getProperties().size()); 649 assertEquals(Collections.singletonList(KeyFactory.stringToKey(bidir2.getId())), pojoEntity.getProperty("bidirChildren")); 650 assertEquals(Collections.singletonList(KeyFactory.stringToKey(b2.getId())), pojoEntity.getProperty("books")); 651 assertEquals(Collections.singletonList(hasKeyPk2.getId()), pojoEntity.getProperty("hasKeyPks")); 652 653 startEnd.end(); 654 655 try { 656 ds.get(KeyFactory.stringToKey(bidir1Id)); 657 fail("expected EntityNotFoundException"); 658 } catch (EntityNotFoundException enfe) { 659 // good 660 } 661 try { 662 ds.get(KeyFactory.stringToKey(bookId)); 663 fail("expected EntityNotFoundException"); 664 } catch (EntityNotFoundException enfe) { 665 // good 666 } 667 try { 668 ds.get(hasKeyPk1Key); 669 fail("expected EntityNotFoundException"); 670 } catch (EntityNotFoundException enfe) { 671 // good 672 } 673 Entity bidirChildEntity = ds.get(KeyFactory.stringToKey(bidir2.getId())); 674 assertNotNull(bidirChildEntity); 675 assertEquals("yam2", bidirChildEntity.getProperty("childVal")); 676 assertEquals(KeyFactory.stringToKey(bidir2.getId()), bidirChildEntity.getKey()); 677 assertKeyParentEquals(pojo.getId(), bidirChildEntity, bidir2.getId()); 678 679 Entity bookEntity = ds.get(KeyFactory.stringToKey(b2.getId())); 680 assertNotNull(bookEntity); 681 assertEquals("max", bookEntity.getProperty("author")); 682 assertEquals("22333", bookEntity.getProperty("isbn")); 683 assertEquals("another title", bookEntity.getProperty("title")); 684 assertEquals(KeyFactory.stringToKey(b2.getId()), bookEntity.getKey()); 685 assertKeyParentEquals(pojo.getId(), bookEntity, b2.getId()); 686 687 Entity hasKeyPkEntity = ds.get(hasKeyPk2.getId()); 688 assertNotNull(hasKeyPkEntity); 689 assertEquals("yar 2", hasKeyPkEntity.getProperty("str")); 690 assertEquals(hasKeyPk2.getId(), hasKeyPkEntity.getKey()); 691 assertKeyParentEquals(pojo.getId(), hasKeyPkEntity, hasKeyPk2.getId()); 692 693 Entity parentEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 694 assertNotNull(parentEntity); 695 assertEquals(4, parentEntity.getProperties().size()); 696 assertEquals("yar", parentEntity.getProperty("val")); 697 assertEquals(Collections.singletonList(bidirChildEntity.getKey()), parentEntity.getProperty("bidirChildren")); 698 assertEquals(Collections.singletonList(bookEntity.getKey()), parentEntity.getProperty("books")); 699 assertEquals(Collections.singletonList(hasKeyPkEntity.getKey()), parentEntity.getProperty("hasKeyPks")); 700 701 assertCountsInDatastore(pojo.getClass(), bidir1.getClass(), 1, 1); 702 } 703 704 void testChangeParent(HasOneToManyJPA pojo, HasOneToManyJPA pojo2, 705 StartEnd startEnd) throws Exception { 706 switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_not_allowed); 707 Book b1 = new Book(); 708 pojo.getBooks().add(b1); 709 710 startEnd.start(); 711 em.persist(pojo); 712 startEnd.end(); 713 714 startEnd.start(); 715 pojo2.getBooks().add(b1); 716 try { 717 em.persist(pojo2); 718 startEnd.end(); 719 fail("expected exception"); 720 } catch (PersistenceException e) { 721 rollbackTxn(); 722 } 723 } 724 725 void testNewParentNewChild_NamedKeyOnChild(HasOneToManyJPA pojo, 726 StartEnd startEnd) throws Exception { 727 Book b1 = new Book("named key"); 728 pojo.getBooks().add(b1); 729 730 startEnd.start(); 731 em.persist(pojo); 732 startEnd.end(); 733 734 Entity bookEntity = ds.get(KeyFactory.stringToKey(b1.getId())); 735 assertEquals("named key", bookEntity.getKey().getName()); 736 } 737 738 void testAddAlreadyPersistedChildToParent_NoTxnDifferentEm(HasOneToManyJPA pojo) { 739 switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed); 740 Book book = new Book(); 741 em.persist(book); 742 em.close(); 743 em = emf.createEntityManager(); 744 pojo.getBooks().add(book); 745 try { 746 em.persist(pojo); 747 em.close(); 748 fail("expected exception"); 749 } catch (PersistenceException e) { 750 // good 751 } 752 753 assertEquals(0, countForClass(pojo.getClass())); 754 assertEquals(1, countForClass(Book.class)); 755 } 756 757 void testAddAlreadyPersistedChildToParent_NoTxnSameEm(HasOneToManyJPA pojo) { 758 switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed); 759 Book book = new Book(); 760 em.persist(book); 761 em.close(); 762 em = emf.createEntityManager(); 763 pojo.getBooks().add(book); 764 try { 765 em.persist(pojo); 766 em.close(); 767 fail("expected exception"); 768 } catch (PersistenceException e) { 769 // good 770 } 771 772 assertEquals(0, countForClass(pojo.getClass())); 773 assertEquals(1, countForClass(Book.class)); 774 } 775 776 void testFetchOfOneToManyParentWithKeyPk(HasOneToManyKeyPkJPA pojo, 777 StartEnd startEnd) throws Exception { 778 startEnd.start(); 779 em.persist(pojo); 780 startEnd.end(); 781 782 startEnd.start(); 783 pojo = em.find(pojo.getClass(), pojo.getId()); 784 assertEquals(0, pojo.getBooks().size()); 785 startEnd.end(); 786 } 787 788 void testFetchOfOneToManyParentWithLongPk(HasOneToManyLongPkJPA pojo, 789 StartEnd startEnd) throws Exception { 790 startEnd.start(); 791 em.persist(pojo); 792 startEnd.end(); 793 794 startEnd.start(); 795 pojo = em.find(pojo.getClass(), pojo.getId()); 796 assertEquals(0, pojo.getBooks().size()); 797 startEnd.end(); 798 } 799 800 void testFetchOfOneToManyParentWithUnencodedStringPk(HasOneToManyUnencodedStringPkJPA pojo, 801 StartEnd startEnd) throws Exception { 802 pojo.setId("yar"); 803 startEnd.start(); 804 em.persist(pojo); 805 startEnd.end(); 806 807 startEnd.start(); 808 pojo = em.find(pojo.getClass(), pojo.getId()); 809 assertEquals(0, pojo.getBooks().size()); 810 startEnd.end(); 811 } 812 813 void testAddChildToOneToManyParentWithLongPk( 814 HasOneToManyLongPkJPA pojo, BidirectionalChildLongPkJPA bidirChild, 815 StartEnd startEnd) throws Exception { 816 startEnd.start(); 817 em.persist(pojo); 818 startEnd.end(); 819 820 startEnd.start(); 821 pojo = em.find(pojo.getClass(), pojo.getId()); 822 Book b = new Book(); 823 pojo.getBooks().add(b); 824 pojo.getBidirChildren().add(bidirChild); 825 bidirChild.setParent(pojo); 826 startEnd.end(); 827 828 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 829 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId())); 830 Entity pojoEntity = ds.get(KeyFactory.createKey(pojo.getClass().getSimpleName(), pojo.getId())); 831 assertEquals(pojoEntity.getKey(), bookEntity.getParent()); 832 assertEquals(pojoEntity.getKey(), bidirEntity.getParent()); 833 } 834 835 void testAddChildToOneToManyParentWithUnencodedStringPk( 836 HasOneToManyUnencodedStringPkJPA pojo, BidirectionalChildUnencodedStringPkJPA bidirChild, 837 StartEnd startEnd) throws Exception { 838 pojo.setId("yar"); 839 startEnd.start(); 840 em.persist(pojo); 841 startEnd.end(); 842 843 startEnd.start(); 844 pojo = em.find(pojo.getClass(), pojo.getId()); 845 Book b = new Book(); 846 pojo.getBooks().add(b); 847 pojo.getBidirChildren().add(bidirChild); 848 startEnd.end(); 849 850 Entity bookEntity = ds.get(KeyFactory.stringToKey(b.getId())); 851 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidirChild.getId())); 852 Entity pojoEntity = ds.get(KeyFactory.createKey(pojo.getClass().getSimpleName(), pojo.getId())); 853 assertEquals(pojoEntity.getKey(), bookEntity.getParent()); 854 assertEquals(pojoEntity.getKey(), bidirEntity.getParent()); 855 } 856 857 void testAddQueriedParentToBidirChild(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 858 StartEnd startEnd) throws Exception { 859 startEnd.start(); 860 em.persist(pojo); 861 startEnd.end(); 862 863 startEnd.start(); 864 pojo = (HasOneToManyJPA) em.createQuery("select from " + pojo.getClass().getName() + " b").getSingleResult(); 865 bidir.setParent(pojo); 866 pojo.getBidirChildren().add(bidir); 867 em.persist(bidir); 868 startEnd.end(); 869 870 startEnd.start(); 871 pojo = (HasOneToManyJPA) em.createQuery("select from " + pojo.getClass().getName() + " b").getSingleResult(); 872 assertEquals(1, pojo.getBidirChildren().size()); 873 startEnd.end(); 874 875 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId())); 876 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 877 assertEquals(pojoEntity.getKey(), bidirEntity.getParent()); 878 } 879 880 void testAddFetchedParentToBidirChild(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 881 StartEnd startEnd) throws Exception { 882 startEnd.start(); 883 em.persist(pojo); 884 startEnd.end(); 885 886 startEnd.start(); 887 pojo = em.find(pojo.getClass(), pojo.getId()); 888 bidir.setParent(pojo); 889 pojo.getBidirChildren().add(bidir); 890 em.persist(bidir); 891 startEnd.end(); 892 893 startEnd.start(); 894 pojo = (HasOneToManyJPA) em.createQuery("select from " + pojo.getClass().getName() + " b").getSingleResult(); 895 assertEquals(1, pojo.getBidirChildren().size()); 896 startEnd.end(); 897 898 Entity bidirEntity = ds.get(KeyFactory.stringToKey(bidir.getId())); 899 Entity pojoEntity = ds.get(KeyFactory.stringToKey(pojo.getId())); 900 assertEquals(pojoEntity.getKey(), bidirEntity.getParent()); 901 } 902 903 private static final class PutPolicy implements DatastoreServiceInterceptor.Policy { 904 private final List<Object[]> putParamList = Utils.newArrayList(); 905 public void intercept(Object o, Method method, Object[] params) { 906 if (method.getName().equals("put")) { 907 putParamList.add(params); 908 } 909 } 910 } 911 912 PutPolicy setupPutPolicy(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 913 StartEnd startEnd) throws Throwable { 914 PutPolicy policy = new PutPolicy(); 915 DatastoreServiceInterceptor.install(getStoreManager(), policy); 916 try { 917 emf.close(); 918 switchDatasource(getEntityManagerFactoryName()); 919 Book book = new Book(); 920 pojo.getBooks().add(book); 921 pojo.getBidirChildren().add(bidir); 922 HasKeyPkJPA hasKeyPk = new HasKeyPkJPA(); 923 pojo.getHasKeyPks().add(hasKeyPk); 924 925 startEnd.start(); 926 em.persist(pojo); 927 startEnd.end(); 928 // 1 put for the parent, 3 puts for the children, 1 more put 929 // to add the child keys back on the parent 930 assertEquals(5, policy.putParamList.size()); 931 policy.putParamList.clear(); 932 return policy; 933 } catch (Throwable t) { 934 DatastoreServiceInterceptor.uninstall(); 935 throw t; 936 } 937 } 938 939 void testOnlyOnePutOnChildUpdate(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 940 StartEnd startEnd) throws Throwable { 941 PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd); 942 try { 943 startEnd.start(); 944 pojo = em.find(pojo.getClass(), pojo.getId()); 945 pojo.getBooks().iterator().next().setTitle("some author"); 946 pojo.getBidirChildren().iterator().next().setChildVal("blarg"); 947 pojo.getHasKeyPks().iterator().next().setStr("double blarg"); 948 startEnd.end(); 949 } finally { 950 DatastoreServiceInterceptor.uninstall(); 951 } 952 // 1 put for each child update 953 assertEquals(3, policy.putParamList.size()); 954 } 955 956 void testOnlyOneParentPutOnParentAndChildUpdate(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 957 StartEnd startEnd) throws Throwable { 958 PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd); 959 try { 960 startEnd.start(); 961 pojo = em.find(pojo.getClass(), pojo.getId()); 962 pojo.setVal("another val"); 963 pojo.getBooks().iterator().next().setTitle("some author"); 964 pojo.getBidirChildren().iterator().next().setChildVal("blarg"); 965 pojo.getHasKeyPks().iterator().next().setStr("double blarg"); 966 startEnd.end(); 967 } finally { 968 DatastoreServiceInterceptor.uninstall(); 969 } 970 // 1 put for the parent update, 1 put for each child update 971 assertEquals(4, policy.putParamList.size()); 972 } 973 974 void testOnlyOneParentPutOnChildDelete(HasOneToManyJPA pojo, BidirectionalChildJPA bidir, 975 StartEnd startEnd, 976 int expectedUpdatePuts) throws Throwable { 977 PutPolicy policy = setupPutPolicy(pojo, bidir, startEnd); 978 try { 979 startEnd.start(); 980 pojo = em.find(pojo.getClass(), pojo.getId()); 981 pojo.setVal("another val"); 982 pojo.getBooks().clear(); 983 pojo.getBidirChildren().clear(); 984 pojo.getHasKeyPks().clear(); 985 startEnd.end(); 986 } finally { 987 DatastoreServiceInterceptor.uninstall(); 988 } 989 assertEquals(expectedUpdatePuts, policy.putParamList.size()); 990 } 991 992 void assertCountsInDatastore(Class<? extends HasOneToManyJPA> pojoClass, 993 Class<? extends BidirectionalChildJPA> bidirClass, 994 int expectedParent, int expectedChildren) { 995 assertEquals(pojoClass.getName(), expectedParent, countForClass(pojoClass)); 996 assertEquals(bidirClass.getName(), expectedChildren, countForClass(bidirClass)); 997 assertEquals(Book.class.getName(), expectedChildren, countForClass(Book.class)); 998 assertEquals(HasKeyPkJPA.class.getName(), expectedChildren, countForClass(HasKeyPkJPA.class)); 999 } 1000 1001 Book newBook() { 1002 Book b = new Book(nextNamedKey()); 1003 b.setAuthor("max"); 1004 b.setIsbn("22333"); 1005 b.setTitle("yam"); 1006 return b; 1007 } 1008}