Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 哪个班级应该负责启动/ ;在JPA中结束交易?_Java_Oop_Responsibility - Fatal编程技术网

Java 哪个班级应该负责启动/ ;在JPA中结束交易?

Java 哪个班级应该负责启动/ ;在JPA中结束交易?,java,oop,responsibility,Java,Oop,Responsibility,我有一个这样的示例代码: 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 BookDaoI

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

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。这应该是图书服务部门的责任。为什么?我真的不知道


此外,谁的职责应该是获取事务、开始和提交?又是图书服务还是书刀

应该在服务层上管理JPA事务。这里有一个反例: 考虑在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;
}
@OneToMany(mappedBy=“book”,fetch=LAZY”)
专用设置页面;
公共集getPages(){
返回页面;
}
如果entityManager在DAO中具有生命周期,则从服务层调用
getPages()
方法将导致延迟初始化异常

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

我的意见是,BookDao了解EntityManager是可以的,因为它是关于数据持久性的方式。
关于事务——它是服务层的责任,因为它负责业务逻辑实现和业务需求中定义的事务边界。但是,独立于持久性技术来实现事务管理将是非常好的(现在您正在使用JPA,明天是JDBC,稍后是其他东西)。我认为Spring的事务注释可能是这种方法的一个很好的例子。

所以我不应该在构造函数中提供EntityManager,而是应该在DAO的方法中获得它?但是我将如何在服务层启动事务?例如,您的DAO级别可能会提供启动/提交事务的方法。在这种情况下,您将从持久性级别的实现中抽象出来。所以我的持久性方法应该只为entityManager.persist(book);?我理解的对吗?@KorayTugay正确;通常您会将JPA与一些应用程序容器或Spring一起使用,为您管理事务。在这种情况下,EntityManager绑定到事务,即事务在服务层启动-此时,实体管理器被创建、绑定到事务并传播到DAO laYerThank,我只是想学习,所以我目前没有使用任何容器。最后一个问题,我应该在构造函数中传递实体管理器还是每个方法传递一个实体管理器?@KorayTugay这是一个很好的学习方法!像Spring这样的框架通过代理传递它,代理从线程局部变量获取实际的实体管理器。它允许您一方面创建DAO类的单个实例,另一方面不将其添加到每个方法的参数中。出于学习目的,您可以选择任何方法,实际上它们都可以工作。使用构造函数意味着您必须为每个服务方法调用创建一个新的DAO instance;通过参数传递它意味着您将使API更加dif很好。当你觉得JPA让你感到舒服的时候,试试Spring!非常感谢你的时间。如果你有时间,你能不能也检查一下?再次非常感谢,谢谢。