@SuppressWarnings({"unchecked"})
  private void cleanup() {
    Session s = openSession();
    s.beginTransaction();

    s.createQuery("delete from SubItem").executeUpdate();
    for (Hoarder hoarder : (List<Hoarder>) s.createQuery("from Hoarder").list()) {
      hoarder.getItems().clear();
      s.delete(hoarder);
    }

    for (Category category : (List<Category>) s.createQuery("from Category").list()) {
      if (category.getExampleItem() != null) {
        category.setExampleItem(null);
        s.delete(category);
      }
    }

    for (Item item : (List<Item>) s.createQuery("from Item").list()) {
      item.setCategory(null);
      s.delete(item);
    }

    s.createQuery("delete from Item").executeUpdate();

    s.getTransaction().commit();
    s.close();
  }
  @SuppressWarnings({"unchecked"})
  private void cleanup() {
    EntityManager em = getOrCreateEntityManager();
    em.getTransaction().begin();

    for (Hoarder hoarder : (List<Hoarder>) em.createQuery("from Hoarder").getResultList()) {
      hoarder.getItems().clear();
      em.remove(hoarder);
    }

    for (Category category : (List<Category>) em.createQuery("from Category").getResultList()) {
      if (category.getExampleItem() != null) {
        category.setExampleItem(null);
        em.remove(category);
      }
    }

    for (Item item : (List<Item>) em.createQuery("from Item").getResultList()) {
      item.setCategory(null);
      em.remove(item);
    }

    em.createQuery("delete from Item").executeUpdate();

    em.getTransaction().commit();
    em.close();
  }
  @Test
  public void testTopLevelManyToOneChangedToNewEntity() {
    Item item1 = new Item();
    item1.setName("item1 name");
    Category category = new Category();
    category.setName("category");

    item1.setCategory(category);
    category.setExampleItem(item1);

    Session s = openSession();
    Transaction tx = s.beginTransaction();
    s.persist(item1);
    tx.commit();
    s.close();

    // get another representation of item1
    s = openSession();
    tx = s.beginTransaction();
    Item item1_1 = (Item) s.get(Item.class, item1.getId());
    tx.commit();
    s.close();

    // change many-to-one in top level to be a new (transient)
    Category categoryNewer = new Category();
    categoryNewer.setName("newer category");
    item1.setCategory(categoryNewer);

    // put the other representation in categoryNewer
    categoryNewer.setExampleItem(item1_1);

    s = openSession();
    tx = s.beginTransaction();
    Item item1Merged = (Item) s.merge(item1);
    // the many-to-one from the top level item will win.
    assertEquals(categoryNewer.getName(), item1Merged.getCategory().getName());
    assertSame(item1Merged, item1Merged.getCategory().getExampleItem());
    tx.commit();
    s.close();

    s = openSession();
    tx = s.beginTransaction();
    item1 = (Item) s.get(Item.class, item1.getId());
    assertEquals(categoryNewer.getName(), item1.getCategory().getName());
    assertSame(item1, item1.getCategory().getExampleItem());
    // make sure original category is still there
    Category categoryQueried =
        (Category) s.createQuery("from Category c where c.name='category'").uniqueResult();
    assertNotNull(categoryQueried);
    // make sure original category has the same item.
    assertSame(item1, categoryQueried.getExampleItem());
    // set exampleItem to null to avoid constraint violation on cleanup.
    categoryQueried.setExampleItem(null);
    tx.commit();
    s.close();

    cleanup();
  }