【问题标题】:A few questions about Play2 and Hibernate关于 Play2 和 Hibernate 的几个问题
【发布时间】:2014-09-08 13:02:55
【问题描述】:

我是Hibernate4的初学者。我用 Hibernate 4.3.6 entitymanager 配置了 Play 2.2.4 并编写了一个测试应用程序。所以,我有实体类Subject.java

package models.entities;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.Table;

import play.data.validation.Constraints;

@Entity
@Table(name="subjects")
public class Subject {

    @Id
    @Column(name="sub_pcode")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    @Column(name="sub_name")
    @Constraints.Required
    public String name;

    public int getId() {
        return id;
    }

    public Subject() {
        id = 0;
    }

    public void save() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        if (id == 0) {
            em.persist(this);      
        } else {
            em.merge(this);
        }
        em.getTransaction().commit();
        em.close();     
    }

    public void delete() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Subject tmpSubject = em.find(Subject.class, id);
        if (tmpSubject != null) {
            em.remove(tmpSubject);      
        }
        em.getTransaction().commit();
        em.close();     
    }

    public static Subject get(int id) {
        Subject result;
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        result = em.find(Subject.class, id);      
        em.getTransaction().commit();
        em.close();
        return result;
    }

    @SuppressWarnings("unchecked")
    public static List<Subject> fetchAll() {
        List<Subject> result = new ArrayList<>();
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("testPU");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        Query q = em.createQuery("SELECT s FROM Subject s");
        result = q.getResultList();
        em.getTransaction().commit();
        em.close();
        return result;
    }
}

和控制器类Application.java

package controllers;

import models.entities.Subject;
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;
import views.html.list;


public class Application extends Controller {

    public static Result index() {
        return ok(index.render("Your new application is ready."));
    }

    public static Result addSubject() {
        Subject s = new Subject();
        s.name = "test subject";
        s.save();
        return ok(list.render(Subject.fetchAll()));
    }

    public static Result deleteSubject(int id) {
        Subject s = Subject.get(id);
        if (null != s) {
            s.delete();
        }
        return ok(list.render(Subject.fetchAll()));
    }

    public static Result updateSubject(int id) {
        Subject s = Subject.get(id);
        if (null != s) {
            s.name = "new subject";
            s.save();
        }
        return ok(list.render(Subject.fetchAll()));
    }

}

我只想问几个问题:

  1. 为什么我可以在不附加的情况下合并实体(在save() 方法中),但是 如果我想删除实体(通过delete() 方法) - 我需要 先找到实体,否则我有一个关于删除分离的例外 实体?

  2. 似乎从控制器类中我可以使用 JPA.em() @Transactional 注释以简化使用休眠的工作。有没有 使用休眠事务和实体管理器的最简单方法 来自非控制器类?

  3. 如果我的代码风格不好,谁能给我关于策略的好建议 hibernate用法等等? 此致。感谢您的建议和回答。

【问题讨论】:

    标签: java hibernate jpa playframework-2.0


    【解决方案1】:
    1. 不应每次都创建您的 EntityManagerFactory 电动势。 EntityManagerFactory 是线程安全的,您应该将其用作静态。如果每次你的表现都会下降时创建它。
    2. 实体不应处理事务,它们仅用于反映数据库数据。使用实体的正确方法是在存储库/DAO 类中。
    3. 为什么在构造函数中使用id = 0;?默认值已经是 0。
    4. 不要在控制器中打开事务。控制器应该只处理进入和退出项目的内容。如果您在其中添加事务,您将增加不必要的复杂性并增加代码的耦合。您可以使用模式 OpenSessionInView、EJB 组件或注入/AOP 事务控制器。
    5. 要删除一个实体,您需要先附加它。您可以使用 getReference 方法:Entity justId = entityManager.getReference(Entity.class, ID)

    看看这份有助于您了解 JPA 基础知识的材料:http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/

    【讨论】:

    • 感谢您的回答。因此,第一步(我认为)将是为Subject 创建 DAO 类,将所有方法(如 getfetchall 等)移动到该 DAO 类中,并且每个 DAO 类最多创建一个 EntityManagerFactory 实例。对吗?
    • 每个应用程序一个 EntityMagerFactory。并且您不应该允许您的实体使用 EntityManager,而只有 EntityManager 应该使用实体。
    • 这就是为什么我需要 DAO 类?使 EntityManager 使用实体,反之亦然。对吗?
    • 是的,实体不应访问 EntityManager。
    猜你喜欢
    • 2015-05-10
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-12
    • 2011-08-24
    相关资源
    最近更新 更多