简体   繁体   English

最佳实践实例化EntityManager

[英]Best Practice instantiating EntityManager

I faced a problem in another topic ( Empty List (not Table) at ManyToMany-Relation ) and wonder if my Usage of EntityManager is correct. 我在另一个主题( ManyToMany-Relation的空列表(不是表))中遇到了问题,并想知道我的EntityManager用法是否正确。 So what should be the best way to use EntityManager? 那么什么应该是使用EntityManager的最佳方式? A few years ago i read something about the DAO-Pattern (like http://www.oracle.com/technetwork/java/dataaccessobject-138824.html ) which i used since that. 几年前我读了一些关于DAO-Pattern的内容(比如http://www.oracle.com/technetwork/java/dataaccessobject-138824.html )。 But now when i want to join the class for WebServices i thought a "Service-Layer" would be better, so i build a class like 但现在,当我想加入WebServices的类时,我认为“服务层”会更好,所以我建立了一个像

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;
}

}

The PersistenceUtil is 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;
}

}

But in the article Entity manager best practices it seems different. 但在文章实体经理的最佳实践中,它似乎有所不同。 Se where should i instantiate EntityManager? 我应该在哪里实例化EntityManager? Should i use better Annotation? 我应该使用更好的Annotation吗? Better a Sigleton-Class? 更好的西格尔顿级? Is it ok when i use it in every method? 我在每种方法中使用它都可以吗?

What do you think? 你怎么看?

I think the most common way is using CDI (context and dependency injection) in first place. 我认为最常见的方法是首先使用CDI(上下文和依赖注入)。

Using CDI your DAO gets the EntityManager injected by the application container (Java app server, eg Glassfish). 使用CDI,您的DAO将获取应用程序容器(Java应用程序服务器,例如Glassfish)注入的EntityManager。 It could look something like this: 它可能看起来像这样:

@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();
    }

    // ...
}

The CDI container takes note of the @PersistenceContext annotation and the Entity Manager gets instantiated, so you don't need to worry about anything related to it. CDI容器记录了@PersistenceContext注释,实体管理器被实例化,因此您无需担心与之相关的任何事情。 The transactions are also managed by the application server. 事务也由应用程序服务器管理。 You probably already have a persistence.xml, where you set all your DB related settings. 您可能已经有了persistence.xml,您可以在其中设置所有与数据库相关的设置。 For the server-managed persistence it needs to define transaction-type="JTA" , by the way. 对于服务器管理的持久性,顺便说一下,它需要定义transaction-type="JTA" See the tons of examples on the web. 请参阅网上的大量示例。

In your service or business logic classes (depending on how many layers you want), you would use your DAO class like this: 在您的服务或业务逻辑类中(取决于您想要多少层),您将使用如下所示的DAO类:

@Stateless
public class FooManager {

    @Inject
    private FooDAO fooDAO;


    public List<FooEntity> getFoos() {
        return fooDAO.findAll();
    }

    // ...
}

The annotations @Dependent , @Stateless are two of many CDI offers . 注释@Stateless @Dependent@Stateless许多CDI提供的两个。 Depending on this the CDI manager creates one or many instances of your classes. 根据此情况,CDI管理器会创建一个或多个类的实例。 Popular choices include @ViewScoped , @SessionScoped and @ApplicationScoped . 热门选择包括@SessionScoped @ViewScoped@SessionScoped@ApplicationScoped When searching the web, don't get confused by JSF's or Seam's annotations. 在网上搜索时,不要对JSF或Seam的注释感到困惑。 You do not want to use those! 你不想用那些! The only thing you want to use of JSF is the @Named annotation, and you apply that one only to the backing beans (java classes which are responsible for view). 你想要使用JSF的唯一东西是@Named注释,你只将它应用于支持bean(负责视图的java类)。 EJB annotations are okay, too. EJB注释也没关系。 They're mostly compatible with CDI. 它们大多与CDI兼容。

The code and suggestions above are about Java EE. 上面的代码和建议是关于Java EE的。 Some frameworks are using their own annotations and patterns. 一些框架使用自己的注释和模式。 Most notable ones are Spring and the Play framework. 最值得注意的是Spring和Play框架。 For these, please refer to the fine docs. 对于这些,请参阅精美的文档。

No matter what Pattern you are using there is one rule that is always valid. 无论您使用何种模式,都有一条始终有效的规则。

Create the EntityManagerFactory only onces. 仅创建EntityManagerFactory onces。 EntityManager can be created on each transaction as it is a cheap object. 可以在每个事务上创建EntityManager,因为它是一个廉价的对象。

In terms of patterns, yes DAO and Repository patterns and their variations are most common. 在模式方面,是DAO和存储库模式及其变体是最常见的。

I fully agree that the CDI method is best. 我完全同意CDI方法是最好的。 The inversion of control reduces the coupling but maintains cohesion of the system. 控制反转减少了耦合,但保持了系统的内聚力。 You also needn't worry about allocation/deallocating the manager. 您也不必担心分配/取消分配经理。

You can also have N number of persistence-unit's in your persistence.xml and you can assign the EntityManager directly to that unit. 您还可以在persistence.xml中拥有N个持久性单元,并且可以将EntityManager直接分配给该单元。 Further you can set the Context Type which I have set here as Transaction. 此外,您可以将我在此处设置的上下文类型设置为Transaction。

@PersistenceContext(unitName = PersistenceStartupService.BJOND_STORE, type=PersistenceContextType.TRANSACTION)
private EntityManager entityManager;

I encourage folks to break-up large schemas into separate persistence units which also helps with fire-walling access to certain tables. 我鼓励人们将大型模式分解为单独的持久性单元,这也有助于对某些表进行防火墙访问。 I usually have my IdentityManager (PicketLink) as a separate persistence unit. 我通常将IdentityManager(PicketLink)作为单独的持久性单元。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM