2016-07-26 115 views
1

我在另一個主題(Empty List (not Table) at ManyToMany-Relation)中遇到問題並懷疑我的EntityManager用法是否正確。那麼使用EntityManager最好的方法是什麼?幾年前,我閱讀了一些關於DAO模式的內容(如http://www.oracle.com/technetwork/java/dataaccessobject-138824.html),因爲那是我用過的。但現在,當我想加盟類的WebServices我想到了一個「服務層」會比較好,所以我建立一個像實例化EntityManager的最佳實踐

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它看起來不同。 Se應該在哪裏實例化EntityManager?我應該使用更好的註釋嗎?更好的Sigleton級?當我在每種方法中使用它時都可以嗎?

您認爲如何?

+0

CDI(jboss或spring)是一種現代而優雅的方式。 – dit

回答

2

我認爲最常見的方式是首先使用CDI(上下文和依賴注入)。

使用CDI,您的DAO獲取由應用程序容器(Java應用程序服務器,例如Glassfish)注入的EntityManager。它可能是這個樣子:

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

    // ... 
} 

的CDI容器注意到@PersistenceContext註釋和實體管理器被實例化,所以你不必擔心與此相關的任何東西。事務也由應用程序服務器管理。您可能已經擁有了一個persistence.xml,您可以在其中設置所有與數據庫相關的設置。順便說一下,對於服務器管理的持久性,它需要定義transaction-type="JTA"。查看網絡上的大量示例。

在您的服務或業務邏輯類(取決於你想要多少層),你會用你的DAO類是這樣的:

@Stateless 
public class FooManager { 

    @Inject 
    private FooDAO fooDAO; 


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

    // ... 
} 

註解@Dependent@Stateless兩個of many CDI offers。根據這個,CDI管理器會創建一個或多個類的實例。受歡迎的選項包括@ViewScoped,@SessionScoped@ApplicationScoped。在搜索網頁時,不要被JSF或Seam的註釋混淆。你不想使用這些!您想使用JSF的唯一方法是@Named批註,並且僅將該批註應用於支持bean(負責查看的Java類)。 EJB註釋也可以。它們大多與CDI兼容。

上面的代碼和建議是關於Java EE的。一些框架正在使用自己的註釋和模式。最值得注意的是Spring和Play框架。對於這些,請參閱罰款文檔。

1

無論您使用的是哪種模式,都有一條始終有效的規則。

僅創建EntityManagerFactory。可以在每個事務上創建EntityManager,因爲它是一個便宜的對象。

就模式而言,是的DAO和存儲庫模式及其變化是最常見的。

0

我完全同意CDI方法是最好的。控制反轉減少了耦合但保持了系統的凝聚力。您也不必擔心分配/取消分配經理。

您也可以在persistence.xml中擁有N個持久性單元,您可以直接將EntityManager分配給該單元。此外,您可以將我在此處設置的上下文類型設置爲「事務」。

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

我鼓勵人們到分手的大架構成單獨的持久性單元,其還與消防牆面訪問某些表幫助。我通常將我的IdentityManager(PicketLink)作爲單獨的持久性單元。