2012-11-30 76 views
2

我有一個現有的java-JSF項目,我被要求添加持久性,使用JPA和Hibernate,當然還有MVC。我使用Postgres作爲DBMS和Netbeans作爲我的IDE。 我已經做了大量的研究工作,結果在開始之前感到更困惑,所以這裏是我到目前爲止:JPA和Hibernate讓我瘋狂不堅持我的對象

我的項目需要是一個工作列表網站,用戶可以註冊然後申請工作機會。但我只是註冊用戶而已。 我的視圖有一個使用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頁都有一個登記表(這我不包括在這裏,因爲它只是一個爛攤子,所有的國際化鍵和東西)當按下「註冊」按鈕時調用UserController bean:

如果register()方法返回「registered」,那麼會有一個導航規則將用戶帶到應用程序登錄。如果它返回「duplicateuser」,那麼它將返回到register.xhtml,如果它引發了不同的錯誤消息,它也會將用戶帶回register.xhtml(是的,這裏沒有涉及太多邏輯,我需要保持簡單)。

事情是,我得到我的用戶表創建,但沒有用戶被堅持,並且我沒有得到錯誤信息,例外或任何東西。 調試時,UserController bean中的EntityTransaction對象將事務顯示爲started = true,然後落實= true,因此一切似乎都正常。但我去檢查我的數據庫和表已創建,但沒有用戶在它:(

此外,我想知道如果我正在進行正確的方式,當PersistenceManager作爲一個單身人士和堅持所有持久性由於UserController豆內部邏輯。 ,我會非常感謝,如果有人可以指導我有點這個! :)

+1

由於您使用JSF進行編碼,因此可以考慮使用「@PersistenceContext」注入託管實體管理器,而不是創建自己的EMF。 –

+0

非常感謝Craig :)但我嘗試過使用注入的實體管理器,這導致需要使用JTA,這使得我的整個項目爆炸:PI不斷收到JTA錯誤,說不能創建EntityManagerFactory,並且JTA TransactionManager相關的錯誤。我想有些東西沒有正確配置,但我無法弄清楚什麼。 – patr1c1a

+0

您不需要使用JTA來使用注入的實體管理器;只需使用JDBC數據源而不是JTA數據源。至於錯誤,也許你應該調查那些爲什麼失敗的根源呢?查看鏈中的最後一個異常。 –

回答

1

你getEM()方法創建一個新的EntityManager每一個被調用時。這意味着您用來啓動交易的實體管理員與您之後調用的持續(用戶)不同。上。因此,事務提交,但不與綁定到包含您的更改的EM。

使用靜態PM來保存EntityManagers是一個壞主意,因爲EntityManagers本身並不是線程安全的。使用獲得EntityManagers可能會很好,但是註冊表和其他方法需要直接保存到entityManager中,並在完成時關閉它。 PM還應該有一個清理方法,在關閉或取消部署時關閉工廠。