PageRenderTime 36ms CodeModel.GetById 12ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tests/com/google/appengine/datanucleus/jpa/JPAAttachDetachTest.java

http://datanucleus-appengine.googlecode.com/
Java | 341 lines | 269 code | 29 blank | 43 comment | 0 complexity | 8bf325735944752ff2b5293bc6055b64 MD5 | raw file
  1/*
  2 * /**********************************************************************
  3 * Copyright (c) 2009 Google Inc.
  4 *
  5 * Licensed under the Apache License, Version 2.0 (the "License");
  6 * you may not use this file except in compliance with the License.
  7 * You may obtain a copy of the License at
  8 *
  9 * http://www.apache.org/licenses/LICENSE-2.0
 10 *
 11 * Unless required by applicable law or agreed to in writing, software
 12 * distributed under the License is distributed on an "AS IS" BASIS,
 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14 * See the License for the specific language governing permissions and
 15 * limitations under the License.
 16 * **********************************************************************/
 17package com.google.appengine.datanucleus.jpa;
 18
 19import com.google.appengine.api.datastore.Entity;
 20import com.google.appengine.api.datastore.EntityNotFoundException;
 21import com.google.appengine.api.datastore.KeyFactory;
 22import com.google.appengine.datanucleus.Utils;
 23import com.google.appengine.datanucleus.test.jdo.DetachableWithMultiValuePropsJDO;
 24import com.google.appengine.datanucleus.test.jpa.BidirectionalChildListJPA;
 25import com.google.appengine.datanucleus.test.jpa.Book;
 26import com.google.appengine.datanucleus.test.jpa.DetachableJPA;
 27import com.google.appengine.datanucleus.test.jpa.HasGrandchildJPA;
 28import com.google.appengine.datanucleus.test.jpa.HasOneToManyListJPA;
 29import com.google.appengine.datanucleus.test.jpa.HasOneToManySetJPA;
 30
 31
 32import java.io.ByteArrayInputStream;
 33import java.io.ByteArrayOutputStream;
 34import java.io.IOException;
 35import java.io.ObjectInputStream;
 36import java.io.ObjectOutputStream;
 37import java.io.Serializable;
 38import java.util.Date;
 39import java.util.List;
 40
 41import javax.jdo.JDOHelper;
 42import javax.jdo.ObjectState;
 43
 44/**
 45 * @author Max Ross <maxr@google.com>
 46 */
 47public class JPAAttachDetachTest extends JPATestCase {
 48
 49  private <T extends Serializable> T toBytesAndBack(T obj)
 50      throws IOException, ClassNotFoundException {
 51    ByteArrayOutputStream baos = new ByteArrayOutputStream();
 52    ObjectOutputStream oos = new ObjectOutputStream(baos);
 53    oos.writeObject(obj);
 54
 55    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
 56    ObjectInputStream ois = new ObjectInputStream(bais);
 57    return (T) ois.readObject();
 58  }
 59
 60  public void testSimpleSerializeWithTxns()
 61      throws IOException, ClassNotFoundException, EntityNotFoundException {
 62    beginTxn();
 63    DetachableJPA pojo = new DetachableJPA();
 64    pojo.setVal("yar");
 65    Date now = new Date();
 66    pojo.setDate(now);
 67    em.persist(pojo);
 68    commitTxn();
 69    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
 70    assertTrue(Date.class.isAssignableFrom(pojo.getDate().getClass()));
 71    em.close(); // Detaches objects in L1 cache
 72    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
 73    em = emf.createEntityManager();
 74    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
 75
 76    pojo = toBytesAndBack(pojo);
 77
 78    assertEquals("yar", pojo.getVal());
 79    assertEquals(now, pojo.getDate());
 80    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
 81    beginTxn();
 82    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
 83    pojo.setVal("not yar");
 84    Date differentNow = new Date(now.getTime() + 1);
 85    pojo.setDate(differentNow);
 86    assertEquals(ObjectState.DETACHED_DIRTY, JDOHelper.getObjectState(pojo));
 87    pojo = em.merge(pojo);
 88    assertEquals(ObjectState.PERSISTENT_DIRTY, JDOHelper.getObjectState(pojo));
 89    commitTxn();
 90    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
 91    Entity e = ds.get(KeyFactory.createKey(DetachableJPA.class.getSimpleName(), pojo.getId()));
 92    assertEquals("not yar", e.getProperty("val"));
 93    assertEquals(differentNow, e.getProperty("date"));
 94  }
 95
 96  public void testSimpleSerializeWithoutTxns() throws Exception {
 97    switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
 98    DetachableJPA pojo = new DetachableJPA();
 99    pojo.setVal("yar");
100    Date now = new Date();
101    pojo.setDate(now);
102    em.persist(pojo);
103    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
104    em.close(); // Detaches objects in L1 cache
105    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
106    assertEquals(Date.class, pojo.getDate().getClass());
107    em = emf.createEntityManager();
108    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
109
110    pojo = toBytesAndBack(pojo);
111
112    assertEquals("yar", pojo.getVal());
113    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
114    pojo.setVal("not yar");
115    Date differentNow = new Date(now.getTime() + 1);
116    pojo.setDate(differentNow);
117    assertEquals(ObjectState.DETACHED_DIRTY, JDOHelper.getObjectState(pojo));
118    em.merge(pojo);
119    em.close(); // Detaches objects in L1 cache
120    Entity e = ds.get(KeyFactory.createKey(DetachableJPA.class.getSimpleName(), pojo.getId()));
121    assertEquals("not yar", e.getProperty("val"));
122    assertEquals(differentNow, e.getProperty("date"));
123  }
124
125  public void testMergeAfterFetch() throws Exception {
126    switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_allowed);
127    DetachableJPA pojo = new DetachableJPA();
128    pojo.setVal("yar");
129    Date now = new Date();
130    pojo.setDate(now);
131    em.persist(pojo);
132    em.close();
133    em = emf.createEntityManager();
134//    beginTxn();
135//    pojo = em.find(DetachableJPA.class, pojo.getId());
136    pojo = (DetachableJPA) em.createQuery("select from " + DetachableJPA.class.getName() + " b").getSingleResult();
137//    commitTxn();
138    em.close();
139    em = emf.createEntityManager();
140    assertEquals("yar", pojo.getVal());
141    pojo.setVal("not yar");
142    em.merge(pojo);
143    em.close();
144    Entity e = ds.get(KeyFactory.createKey(DetachableJPA.class.getSimpleName(), pojo.getId()));
145    assertEquals("not yar", e.getProperty("val"));
146  }
147
148  // TODO Should not be referring to DetachableWithMultiValuePropsJDO since is JDO!!
149  public void testSerializeWithMultiValueProps() throws Exception {
150    beginTxn();
151    DetachableWithMultiValuePropsJDO pojo = new DetachableWithMultiValuePropsJDO();
152    pojo.setStrList(Utils.newArrayList("c", "d"));
153    em.persist(pojo);
154    commitTxn();
155    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
156    em.close(); // Detaches objects in L1 cache
157    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
158    em = emf.createEntityManager();
159    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
160
161    pojo = toBytesAndBack(pojo);
162
163    assertEquals(Utils.newArrayList("c", "d"), pojo.getStrList());
164    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
165    beginTxn();
166    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
167    // reattach to the pm - this turns our regular list field into a managed
168    // list field
169    pojo = em.merge(pojo);
170    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
171    pojo.getStrList().add("e");
172    commitTxn();
173    Entity e = ds.get(KeyFactory.createKey(DetachableWithMultiValuePropsJDO.class.getSimpleName(), pojo.getId()));
174    assertEquals(3, ((List<String>)e.getProperty("strList")).size());
175    assertEquals(Utils.newArrayList("c", "d", "e"), e.getProperty("strList"));
176  }
177
178  public void testSerializeWithOneToMany_AddChildToBidirectionalDetached() throws Exception {
179    beginTxn();
180    HasOneToManyListJPA pojo = new HasOneToManyListJPA();
181    pojo.setVal("yar");
182    BidirectionalChildListJPA bidir = new BidirectionalChildListJPA();
183    bidir.setChildVal("yar2");
184    pojo.getBidirChildren().add(bidir);
185    em.persist(pojo);
186    commitTxn();
187    em.close();
188    em = emf.createEntityManager();
189
190    pojo = toBytesAndBack(pojo);
191    assertEquals("yar", pojo.getVal());
192    assertEquals(1, pojo.getBidirChildren().size());
193    BidirectionalChildListJPA bidir2 = new BidirectionalChildListJPA();
194    bidir.setChildVal("yar3");
195    pojo.getBidirChildren().add(bidir2);
196    // Don't set the parent - this ref won't get updated when we call
197    // merge and we'll get an exception.
198//    bidir2.setParent(pojo);
199    beginTxn();
200    pojo = em.merge(pojo);
201    commitTxn();
202    Entity e = ds.get(KeyFactory.stringToKey(bidir2.getId()));
203    assertEquals(KeyFactory.stringToKey(pojo.getId()), e.getKey().getParent());
204  }
205
206  public void testSerializeWithOneToMany_AddChildToUnidirectionalDetached() throws Exception {
207    beginTxn();
208    HasOneToManyListJPA pojo = new HasOneToManyListJPA();
209    pojo.setVal("yar");
210    Book b = new Book();
211    b.setAuthor("harry");
212    pojo.getBooks().add(b);
213    em.persist(pojo);
214    commitTxn();
215    em.close();
216    em = emf.createEntityManager();
217
218    pojo = toBytesAndBack(pojo);
219    assertEquals("yar", pojo.getVal());
220    assertEquals(1, pojo.getBooks().size());
221    Book b2 = new Book();
222    b2.setAuthor("yar3");
223    pojo.getBooks().add(b2);
224    // Don't set the parent - this ref won't get updated when we call
225    // merge and we'll get an exception.
226//    bidir2.setParent(pojo);
227    beginTxn();
228    pojo = em.merge(pojo);
229    commitTxn();
230    Entity e = ds.get(KeyFactory.stringToKey(b2.getId()));
231    assertEquals(KeyFactory.stringToKey(pojo.getId()), e.getKey().getParent());
232  }
233
234  public void testSerializeWithOneToMany_AddGrandchildToUnidirectionalDetached() throws Exception {
235    beginTxn();
236    HasGrandchildJPA hasGrandchild = new HasGrandchildJPA();
237    HasOneToManySetJPA pojo = new HasOneToManySetJPA();
238    hasGrandchild.getYar().add(pojo);
239    pojo.setVal("yar");
240    Book b = new Book();
241    b.setAuthor("harry");
242    pojo.getBooks().add(b);
243    em.persist(hasGrandchild);
244    commitTxn();
245    em.close();
246    em = emf.createEntityManager();
247
248    hasGrandchild = toBytesAndBack(hasGrandchild);
249    pojo = hasGrandchild.getYar().iterator().next();
250    assertEquals("yar", pojo.getVal());
251    assertEquals(1, pojo.getBooks().size());
252    Book b2 = new Book();
253    b2.setAuthor("yar3");
254    pojo.getBooks().add(b2);
255    // Don't set the parent - this ref won't get updated when we call
256    // merge and we'll get an exception.
257//    bidir2.setParent(pojo);
258    beginTxn();
259    hasGrandchild = em.merge(hasGrandchild);
260    commitTxn();
261    Entity e = ds.get(KeyFactory.stringToKey(b2.getId()));
262    assertEquals(KeyFactory.stringToKey(pojo.getId()), e.getKey().getParent());
263  }
264
265  public void testSerializeWithOneToMany_AddChildToReattached() throws Exception {
266    beginTxn();
267    HasOneToManyListJPA pojo = new HasOneToManyListJPA();
268    pojo.setVal("yar");
269    BidirectionalChildListJPA bidir = new BidirectionalChildListJPA();
270    bidir.setChildVal("yar2");
271    pojo.getBidirChildren().add(bidir);
272    em.persist(pojo);
273    commitTxn();
274    em.close();
275    em = emf.createEntityManager();
276
277    pojo = toBytesAndBack(pojo);
278    assertEquals("yar", pojo.getVal());
279    assertEquals(1, pojo.getBidirChildren().size());
280    beginTxn();
281    pojo = em.merge(pojo);
282    BidirectionalChildListJPA bidir2 = new BidirectionalChildListJPA();
283    bidir.setChildVal("yar3");
284    pojo.getBidirChildren().add(bidir2);
285    bidir2.setParent(pojo);
286    commitTxn();
287    Entity e = ds.get(KeyFactory.stringToKey(bidir2.getId()));
288    assertEquals(KeyFactory.stringToKey(pojo.getId()), e.getKey().getParent());
289  }
290  
291  public void testDeleteDetachedObject_NoTxn() {
292    switchDatasource(EntityManagerFactoryName.nontransactional_ds_non_transactional_ops_not_allowed);
293    DetachableJPA pojo = new DetachableJPA();
294    pojo.setVal("yar");
295    Date now = new Date();
296    pojo.setDate(now);
297    em.persist(pojo);
298    em.close(); // Detaches objects in L1 cache
299    assertEquals(ObjectState.DETACHED_CLEAN, JDOHelper.getObjectState(pojo));
300    em = emf.createEntityManager();
301    pojo = em.find(pojo.getClass(), pojo.getId());
302    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
303    em.close();
304    em = emf.createEntityManager();
305    pojo = em.merge(pojo);
306    // this is wrong and it will start to fail when we upgrade to DN 2.0
307    // We're tracking this with bug
308    // http://code.google.com/p/datanucleus-appengine/issues/detail?id=142
309    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
310//    assertEquals(ObjectState.HOLLOW_PERSISTENT_NONTRANSACTIONAL, JDOHelper.getObjectState(pojo));
311//    em.remove(pojo);
312//    assertEquals(ObjectState.PERSISTENT_NEW_DELETED, JDOHelper.getObjectState(pojo));
313//    em.close();
314//    em = emf.createEntityManager();
315//    assertNull(em.find(pojo.getClass(), pojo.getId()));
316  }
317  
318  public void testDeleteDetachedObject_Txn() {
319    beginTxn();
320    DetachableJPA pojo = new DetachableJPA();
321    pojo.setVal("yar");
322    Date now = new Date();
323    pojo.setDate(now);
324    em.persist(pojo);
325    commitTxn();
326    Long id = pojo.getId();
327    beginTxn();
328    pojo = em.find(pojo.getClass(), pojo.getId());
329    commitTxn();
330    beginTxn();
331    pojo = em.merge(pojo);
332    em.remove(pojo);
333    assertEquals(ObjectState.PERSISTENT_DELETED, JDOHelper.getObjectState(pojo));
334    commitTxn();
335    beginTxn();
336    assertNull(em.find(pojo.getClass(), id));
337    rollbackTxn();
338  }
339
340
341}