2

所以我有一个这样的示例代码:

package biz.tugay.books10Aug.dao;
/* User: koray@tugay.biz 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();
    }

}

这就是我对它进行单元测试的方式:

package biz.tugay.books10Aug.dao;
/* User: koray@tugay.biz 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);
    }

}

这一切都很好。我的问题是关于OOP的。

我决定 BookDaoImpl 不应该负责获取 EntityManager。这应该是 BookService 的责任。为什么?我真的不知道。

此外,谁应该负责获得交易、开始和提交?又是 BookService 还是 BookDao?

4

2 回答 2

1

我的观点是 BookDao 知道 EntityManager 是可以的,因为它是关于数据持久性的方式。关于事务 - 它是服务层的责任,因为它负责业务逻辑实现和业务需求中定义的事务边界。然而,独立于持久性技术实现事务管理会很棒(现在您使用 JPA,明天使用 JDBC,稍后会使用其他东西)。认为 Spring 的事务注释可能是这种方法的一个很好的例子。

于 2015-08-10T20:28:47.473 回答
1

JPA Transaction 应该在服务层上进行管理。这是一个反例:假设find您的 DAO 层中有一个方法:

public Book find(long id) {
      return entityManager.find(Book.class, id);
}

您的 Book 类拥有一组页面:

@OneToMany(mappedBy = "book", fetch = LAZY")
private Set<Page> pages;

public Set<Page> getPages() {
    return pages;
}

如果 entityManager 在 DAO 中有生命周期,getPages()则从您的服务层调用方法将导致延迟初始化异常

当然,在每条规则中都有例外,但一般来说,您应该在服务层(或存储库层,取决于措辞)管理您的事务。您甚至可以在 DAO 层中使用 MANDATORY 事务分界属性,以使其成为强制性的。

于 2015-08-10T20:26:38.730 回答