我在另一个主题(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吗?更好的西格尔顿级?我在每种方法中使用它都可以吗?
您怎么看?
答案 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)作为单独的持久性单元。