Suggested Pages

Friday, June 29, 2012

JPA - EntityManager : Persist Entities Part I

In this post we'll see the method persist of Entity Manager and we'll take a look at the most common problems, you can face.
Consider the following entity beans.
Parent.java

 ...
@Entity
public class Parent {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int parentId;
 
 @Column
 private String name;

 @OneToMany(cascade=CascadeType.PERSIST,mappedBy="parent")
 private List<Child> children;
 ...
}
    

Child.java
 ...
@Entity
public class Child {
 
 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private int childId;
 
 @Column
 private String name;
 
 @ManyToOne
 private Parent parent;
 
 ...
}


GenericDAO.java

...

@Repository
public class GenericDAO {

 @PersistenceContext(unitName = "persistenceUnitTest")
 private EntityManager entityManager;


 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Parent parent) {
  System.out.println("------------save(): start -------");
  entityManager.persist(parent);
  System.out.println("------------save(): end -------");
 }
 @Transactional(propagation = Propagation.REQUIRED)
 public void save(Child child) {
  System.out.println("------------save(): start -------");
  entityManager.persist(child);
  System.out.println("------------save(): end -------");
 }
}

Save a transient entity



DAOTest.java
...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveTransientEntity() {
  System.out.println("------------testTransientEntity(): start -------");
  Child child=new Child();
  child.setChildId(1);
  child.setName("child1");
  genericDAO.save(child);
  System.out.println("------------testTransientEntity(): end -------");
 }

}

Persist method of Entity Manager can be applied to a transient entity. So this test method complete successfully.

Save a detached entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;


 @Test
 public void testSaveDetachedObject() {
  System.out.println("------------testSaveDetachedObject(): start -------");
  Child child=new Child();
  child.setChildId(2);
  child.setName("child2");
  genericDAO.save(child);
  child.setName("childNew");
  genericDAO.save(child);
  System.out.println("------------testSaveDetachedObject(): end -------");
 }
 
}

Persist method of Entity Manager can't be applied to a detached entity. An error occurs: org.hibernate.PersistentObjectException: detached entity passed to persist: com.simonefolinojavablog.persistence.entity.Child ;
This happens because JPA/Hibernate distinguishes between transient entities and detached entities by the id. Because i used @GeneratedValue(strategy=GenerationType.IDENTITY) the database will create the id automatically when a row is created in the database.

Save an entity that has a dependency with another transient entity


DAOTest.java

...

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "DAOTest-context.xml")
public class DAOTest {

 @Autowired
 private GenericDAO genericDAO;

  
 @Test
 public void testSaveEntityWithTransientAssociation() {
  System.out.println("------------testSaveEntityWithTransientAssociation(): start -------");
  Child child=new Child();
  child.setChildId(3);
  child.setName("child3");
  Parent parent = new Parent();
  parent.setParentId(3);
  parent.setName("parent3");
  child.setParent(parent);    // ManyToOne association
  genericDAO.save(child);
  System.out.println("------------testSaveEntityWithTransientAssociation(): end -------");
 }
 
}

}

Persist method of Entity Manager can't be be applied to a transient entity that has a dependency with another transient entity. An error occurs: object references an unsaved transient instance - save the transient instance before flushing: com.simonefolinojavablog.persistence.entity.Child.parent -> com.simonefolinojavablog.persistence.entity.Parent
This exception occurs because we have to persist the Parent entity before persisting Child entity. You cannot persist an entity that has references with a transient entity but you can if this entity is a detached entity.

No comments :

Post a Comment

Suggested Pages