package groovy.jpa import javax.persistence.* import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean import demo.jpa.Person import org.grails.plugins.jpa.util.JPATestHelper public class JPACategoryTests extends GroovyTestCase { def emf, em; void setUp() { emf = JPATestHelper.createTempEntityManagerFactory(includes: 'demo.jpa.*') em = emf.createEntityManager() } void tearDown() { JPAContextHolder.clear(); } void testCategoryParentAPI() { em.transaction.begin() em.persist(new Person(name: 'person1')) em.persist(new Person(name: 'person2')) em.persist(new Person(name: 'person3')) em.transaction.commit() use(JPACategory) { assertEquals 3, em.executeQuery("select p from Person p")?.size() assertEquals 1, em.executeQuery("select p from Person p where p.name = 'person1'")?.size() } } void testPersitRefreshMergeRemove() { em.transaction.begin() em.persist(new Person(name: 'person1')) em.persist(new Person(name: 'person2')) em.persist(new Person(name: 'person3')) em.transaction.commit() try { use(JPACategory) {new Person(name: 'person4').persist() } fail("persist() without context shall throw exception") } catch (e) {} // with 3 initial records, instead of 4 use(JPACategory) { assertEquals 3, em.executeQuery("select p from Person p")?.size()} // insert 1 more def trialPerson = new Person(name: 'person4') JPAContextHolder.setJPA(new JPA(em:em)) use(JPACategory) { trialPerson.persist() } // now we have 4 records use(JPACategory) { assertEquals 4, em.executeQuery("select p from Person p")?.size()} use(JPACategory) { assertEquals 'person4', em.executeQuery("select p from Person p")[3].'name'} // update to create detached instance, and refresh to clear the change assertFalse JPAContextHolder.entityManager.transaction.active trialPerson.'name' = 'person4.1' // person becomes detached use(JPACategory) { trialPerson.refresh()} assertEquals 'person4', trialPerson.'name' //refresh shall discard the change use(JPACategory) { assertEquals 'person4', em.executeQuery("select p from Person p")[3].'name'} trialPerson.'name' = 'person4.2' // person becomes detached use(JPACategory) { trialPerson.merge()} assertEquals 'person4.2', trialPerson.'name' //merge shall flash the change use(JPACategory) { assertEquals 'person4.2', em.executeQuery("select p from Person p")[3].'name'} use(JPACategory) { assertEquals 4, em.executeQuery("select p from Person p")?.size()} use(JPACategory) { trialPerson.remove()} use(JPACategory) { assertEquals 3, em.executeQuery("select p from Person p")?.size()} use(JPACategory) { assertEquals 0, em.executeQuery("select p from Person p where p.name = ?", ['person4.2'])?.size()} } void testPersist() { //use diff ways to persist JPAContextHolder.setJPA(new JPA(em:em)) use(JPACategory) { assertEquals 0, em.executeQuery("select p from Person p")?.size()} // static JPACategory.persist(em, new Person(name: 'static')) use(JPACategory) { assertEquals 1, em.executeQuery("select p from Person p")?.size()} // no arg use(JPACategory) { new Person(name: 'no arg').persist() } use(JPACategory) { assertEquals 2, em.executeQuery("select p from Person p")?.size()} // with cfg = anything cfg for testing the interface use(JPACategory) { new Person(name: 'with cfg').persist(any: true) } use(JPACategory) { assertEquals 3, em.executeQuery("select p from Person p")?.size()} // actual implementation JPACategory.persist(em, new Person(name: 'static'), any: true) use(JPACategory) { assertEquals 4, em.executeQuery("select p from Person p")?.size()} } /** * commit| hasTx | !hasTx * ------+-------+------- * true | Y | Y * null | Y | N * false | N | N */ void testPersistTransaction() { JPAContextHolder.setJPA(new JPA(em:em)) assertFalse JPAContextHolder.transaction?.active def tx; // 1. hasTx && commit == true tx = JPAContextHolder.transaction.with {EntityTransaction t -> t.begin(); t} assertTrue JPAContextHolder.transaction?.active use(JPACategory) { new Person(name: 'dummy').persist(commit: true) } use(JPACategory) { assertEquals 1, em.executeQuery("select p from Person p")?.size()} assertFalse JPAContextHolder.transaction?.active // 2. !hasTx && commit == true use(JPACategory) { new Person(name: 'dummy').persist(commit: true) } use(JPACategory) { assertEquals 2, em.executeQuery("select p from Person p")?.size()} assertFalse JPAContextHolder.transaction?.active // 3. hasTx && commit == null, with tx, the tx shall be kept unless specially told not to do so tx = JPAContextHolder.transaction.with {EntityTransaction t -> t.begin(); t} use(JPACategory) { new Person(name: 'dummy').persist() } use(JPACategory) { assertEquals 3, em.executeQuery("select p from Person p")?.size()} assertTrue JPAContextHolder.transaction?.active // 4. !hasTx && commit == null, w/o tx, a new one is created and will be closed JPAContextHolder.transaction.commit() assertFalse JPAContextHolder.transaction?.active use(JPACategory) { new Person(name: 'dummy').persist() } use(JPACategory) { assertEquals 4, em.executeQuery("select p from Person p")?.size()} assertFalse JPAContextHolder.transaction?.active // 5. hasTx && commit == false tx = JPAContextHolder.transaction.with {EntityTransaction t -> t.begin(); t} assertTrue JPAContextHolder.transaction?.active use(JPACategory) { new Person(name: 'dummy').persist(commit: false) } use(JPACategory) { assertEquals 5, em.executeQuery("select p from Person p")?.size()} assertTrue JPAContextHolder.transaction?.active // 2. !hasTx && commit == true JPAContextHolder.transaction.commit() assertFalse JPAContextHolder.transaction?.active use(JPACategory) { new Person(name: 'dummy').persist(commit: false) } use(JPACategory) { assertEquals 6, em.executeQuery("select p from Person p")?.size()} assertTrue JPAContextHolder.transaction?.active } }