最佳实践实例化EntityManager

时间:2016-07-26 13:37:02

标签: java json rest jpa jax-rs

我在另一个主题(Empty List (not Table) at ManyToMany-Relation)遇到了问题,并想知道我的EntityManager用法是否正确。那么什么应该是使用EntityManager的最佳方式?几年前我读了一些关于DAO-Pattern的东西(比如http://www.oracle.com/technetwork/java/dataaccessobject-138824.html),我从那时开始使用它。但现在,当我想加入WebServices课程时,我想到了一个" Service-Layer"会更好,所以我建立一个类

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("role")
public class RoleService {

@GET
@Path("ping")
@Produces(MediaType.TEXT_PLAIN)
public String helloWorld() {
    return "REST-Web-Service ready for Role.class!";
}

public static void create(Role object) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    em.persist(object);
    tx.commit();
    em.close();
}

public static void update(Role object) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    em.merge(object);
    tx.commit();
    em.close();
}

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("id/{id}")
public static Role getRole(@PathParam("id") Integer id) {
    return load(id);
}

@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("name")
public static String getName(@QueryParam("id") Integer id) {
    Role role = findById(id);
    if (role != null) {
        return "[\n   {\n      \"id\":"+id+",\n      \"type\":\"role\",\n      \"name\": \"" + role.getName() + "\",\n      \"query\":\"success\"\n   }\n]";
    }
    return "[\n   {\n      \"id\":"+id+",\n      \"type\":\"role\",\n      \"query\":\"failed\"\n   }\n]";
}

public static Role findById(Integer id) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    Role object = em.find(Role.class, id);
    tx.commit();
    em.close();
    return object;
}

public static Role load(Integer id) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    Role objectResult = em.find(Role.class, id);
    tx.commit();
    em.close();
    return objectResult;
}

public static Role load(Role object) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    Role objectResult = em.find(Role.class, object.getId());
    tx.commit();
    em.close();
    return objectResult;
}

public static void deleteById(Integer id) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    em.remove(em.find(Role.class, id));
    tx.commit();
    em.close();
}

// @DELETE
// @Path("{id}")
public static void delete(Role object) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    em.remove(em.find(Object.class, object.getId()));
    tx.commit();
    em.close();
}

public static List<Role> findByName(String name) {
    EntityManager em = PersistenceUtil.getEntityManagerFactory().createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();
    List<Role> list = em.createQuery("SELECT r FROM Role r WHERE r.name LIKE :name").setParameter("name", "%" + name + "%").getResultList();
    tx.commit();
    em.close();
    return list;
}

}

PersistenceUtil是

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class PersistenceUtil {

/*
 * Name of persistence unit which MUST correlate to persistence-unit name in persistence.xml
 */
private static final String PERSISTENCE_UNIT_NAME = "RoleModel";


private static final EntityManagerFactory entityManagerFactory;
static {
    try {
        entityManagerFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    } catch (Throwable ex) {
        System.err.println("EntityManagerFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static EntityManagerFactory getEntityManagerFactory() {
    return entityManagerFactory;
}

}

但是在文章Entity manager best practices中似乎有所不同。我应该在哪里实例化EntityManager?我应该使用更好的Annotation吗?更好的西格尔顿级?我在每种方法中使用它都可以吗?

您怎么看?

3 个答案:

答案 0 :(得分:2)

我认为最常见的方法是首先使用CDI(上下文和依赖注入)。

使用CDI,您的DAO将获取应用程序容器(Java应用程序服务器,例如Glassfish)注入的EntityManager。它可能看起来像这样:

Page_Load

CDI容器会记录@Dependent public class FooDAO { @PersistenceContext private EntityManager em; public FooEntity find(final Number id) throws NoResultException { return em.find(FooEntity.class, id); } public List<FooEntity> findAll() { return em.createNamedQuery("FooEntity.findAll", FooEntity.class).getResultList(); } // ... } 注释,实体管理器会被实例化,因此您无需担心与之相关的任何内容。事务也由应用程序服务器管理。您可能已经有了persistence.xml,您可以在其中设置所有与数据库相关的设置。对于服务器管理的持久性,它需要定义@PersistenceContext。请参阅网上的大量示例。

在您的服务或业务逻辑类中(取决于您想要多少层),您将使用这样的DAO类:

transaction-type="JTA"

注释@Stateless public class FooManager { @Inject private FooDAO fooDAO; public List<FooEntity> getFoos() { return fooDAO.findAll(); } // ... } @Dependent是两个of many CDI offers。根据此情况,CDI管理器会创建一个或多个类的实例。热门选择包括@Stateless@ViewScoped@SessionScoped。在网上搜索时,不要对JSF或Seam的注释感到困惑。你不想用那些!您想要使用JSF的唯一事情是@ApplicationScoped注释,并且您只将它应用于支持bean(负责视图的java类)。 EJB注释也没关系。它们大多与CDI兼容。

上面的代码和建议是关于Java EE的。一些框架使用自己的注释和模式。最值得注意的是Spring和Play框架。对于这些,请参阅精美的文档。

答案 1 :(得分:1)

无论您使用何种模式,都有一条始终有效的规则。

仅创建EntityManagerFactory onces。可以在每个事务上创建EntityManager,因为它是一个廉价的对象。

就模式而言,DAO和Repository模式及其变体是最常见的。

答案 2 :(得分:0)

我完全同意CDI方法是最好的。控制反转减少了耦合,但保持了系统的内聚力。您也不必担心分配/取消分配经理。

您还可以在persistence.xml中拥有N个持久性单元,并且可以将EntityManager直接分配给该单元。此外,您可以将我在此处设置的上下文类型设置为Transaction。

SELECT ... ip = '127.0.0.1';

我鼓励人们将大型模式分解为单独的持久性单元,这也有助于对某些表进行防火墙访问。我通常将IdentityManager(PicketLink)作为单独的持久性单元。