JPA和Hibernate让我疯狂而不是坚持我的对象

时间:2012-11-30 15:25:23

标签: hibernate postgresql jpa netbeans persistence

我有一个现有的java-JSF项目,我被要求使用JPA和Hibernate,当然还有MVC来添加持久性。我使用Postgres作为DBMS和Netbeans作为我的IDE。 我做了很多研究,结果在我开始之前就更加困惑了,所以这就是我到目前为止所做的:

我的项目需要是一个工作列表网站,用户可以在其中注册然后申请工作机会。但是我只是注意用户注册了。 My View有一个使用JSF构建的register.xhtml页面,我的Model包中有一个User.java类,我的Controller中也有一个UserController bean。 register.xhtml调用UserController bean中的register()方法,该方法应该保留User对象。

我已经像这样配置了我的persistence.xml:

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">  
<persistence-unit name="TP5PU" transaction-type="RESOURCE_LOCAL">  
<provider>org.hibernate.ejb.HibernatePersistence</provider>  
<non-jta-data-source>tp5</non-jta-data-source>  
<class>model.User</class>  
<exclude-unlisted-classes>true</exclude-unlisted-classes>  
<properties>  
  <property name="configLocation" value="WEB-INF/classes/hibernate.cfg.xml"/>  
  <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>  
  <property name="hibernate.hbm2ddl.auto" value="update"/>  
  <property name="hibernate.connection.username" value="postgres"/>  
  <property name="hibernate.connection.password" value="postgres"/>  
  <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/pootp5"/>  
</properties>  
</persistence-unit>  
</persistence>  

我还创建了一个PersistenceManager.java类,它是一个单例,并且里面还有一个单独的EntityManagerFactory:

import javax.persistence.*;

public class PersistenceManager {

private EntityManagerFactory emf = null;
private EntityManager em = null;
private static PersistenceManager instance = null;

private PersistenceManager(){
}

public static PersistenceManager getInstance() {
    if (instance==null){
        instance=new PersistenceManager();
    }
    return instance;
}

public EntityManagerFactory getEmf() {
    if (emf == null){
        this.setEmf(Persistence.createEntityManagerFactory("TP5PU"));
    }
        return emf;
}

public EntityManager getEm() {
    this.setEm(this.getEmf().createEntityManager());
    return em;
}

public void setEmf(EntityManagerFactory emf) {
    this.emf = emf;
}


public void setEm(EntityManager em) {
    this.em = em;
}
}

现在,我的UserController bean有以下代码:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
import javax.persistence.EntityTransaction;
import model.PersistenceManager;
import model.Usuario;

@ManagedBean (name="userController")
@SessionScoped
public class UserController implements Serializable{

private String username;
private String password;
private String name;
private String lastname;
private String resume;
private PersistenceManager pm;
private EntityTransaction tx;

public UserController() {
    pm = PersistenceManager.getInstance();
    tx = pm.getEm().getTransaction();
}


public String register() {
    User user = new User(this.getUsername(), this.getPassword(), this.getName(), this.getLastname(), this.getResume());
    try {
        getPm().getEmf();
        getTx().begin();
        getPm().getEm().persist(user);
        getTx().commit();
        getPm().getEm().close();
        return "registered";
    }
    catch (org.hibernate.exception.ConstraintViolationException e1){   
        if (getTx().isActive()){
            getTx().rollback();}
        getPm().getEm().close();
        return "duplicateuser";
    }
    catch (Exception e2){   
        if (getTx().isActive()){
            getTx().rollback();}            
        getPm().getEm().close();
        return "registrationerror";
    }
}

//all getters & setters
}

我的所有User.java类都有一堆属性和getter / setter方法:

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class User implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(updatable=false)
protected long userID;
@Column(unique=true)
private String username;
private String password;
private String name;
private String lastname;
private String resume;

//and all the getters & setters needed for each attribute.

register.xhtml页面有一个注册表单(我不在这里,因为它只是一团糟,所有的i18n键和东西)在按下“Register”按钮时调用UserController bean:     

如果register()方法返回“registered”,则会有一个导航规则将用户带到应用程序登录。如果它返回“duplicateuser”,那么它将被恢复到register.xhtml,如果它抛出一个不同的错误消息,它也会将用户带回register.xhtml(是的,这些中涉及的逻辑不多,我需要保持简单)。

问题是,我创建了我的用户表,但没有用户持久存在,并且我没有收到错误消息,异常或任何内容。 在调试时,UserController bean中的EntityTransaction对象将事务显示为starts = true然后commit = true,因此一切似乎都在起作用。但我去检查我的数据库并创建了表,但其中没有用户:(

另外,我想知道当PersistenceManager作为单例并且将所有持久性逻辑粘贴在UserController bean中时,我是否正在以正确的方式进行。 如果有人能指导我一点,我会非常感激! :)

1 个答案:

答案 0 :(得分:1)

您的getEM()方法在每次调用时都会创建一个新的EntityManager。这意味着您用于启动事务的实体管理器与您随后调用persist(user)的实体管理器不同;上。因此,事务提交,但不包含包含更改的EM。

使用静态PM来保存EntityManage是一个坏主意,因为EntityManagers本身并不是线程安全的。使用获取EntityManagers可能会很好,但是寄存器和其他方法需要直接保存在entityManager上,并在完成后关闭它。 PM还应该有一个清理方法,在关闭或取消部署时关闭其工厂。