So I have a sample code like this:
package biz.tugay.books10Aug.dao;
/* User: [email protected] Date: 10/08/15 Time: 22:54 */
import biz.tugay.books10Aug.model.Book;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
public class BookDaoImpl implements BookDao {
private EntityManager entityManager;
public BookDaoImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Override
public void persist(Book book) {
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(book);
transaction.commit();
}
}
and this is how I unit test it:
package biz.tugay.books10Aug.dao;
/* User: [email protected] Date: 10/08/15 Time: 22:56 */
import biz.tugay.books10Aug.model.Book;
import org.junit.Test;
import javax.persistence.EntityManager;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class BookDaoImplTest {
@Test
public void testPersistNewBook() throws Exception {
PersistenceUtil.initalizeEntityManagerFactory();
EntityManager entityManager = PersistenceUtil.getEntityManager();
BookDao bookDao = new BookDaoImpl(entityManager);
String isbn = new SimpleDateFormat("HHmmss").format(Calendar.getInstance().getTime());
Book book = new Book();
book.setIsbn(isbn);
book.setName("Just Another Book in the DB, Volume: " + isbn);
book.setPrice(10);
book.setPublishDate(Calendar.getInstance().getTime());
book.setPublisher("002");
bookDao.persist(book);
}
}
This all works fine. My question is about OOP.
I decided that BookDaoImpl should not be responsible for getting the EntityManager. It should be the BookService 's responsibility. Why? I a do not know really.
Also, whos responsibility should be to get transaction, begin and commit? Again BookService or BookDao?
JPA Transaction should be managed on a service layer. Here's an counterexample: consider you have a
find
method in your DAO layer:And your Book class owns a collection of pages:
If the entityManager has a lifecycle within a DAO, the call of
getPages()
method made from your service layer will result in lazy initialization exceptionOf course in each rule there are exceptions, but in general you should manage your transaction on service layer (or repository layer depending on wording). You can even use MANDATORY transaction demarcation attribute in your DAO layer in order to make it mandatory.