2

JPAとHibernate、そしてもちろんMVCを使用して、永続性を追加するように求められた既存のJava-JSFプロジェクトがあります。Postgres を DBMS として、Netbeans を IDE として使用しています。私は多くの調査を行い、開始前よりも混乱してしまったので、これまでに得たものは次のとおりです。

私のプロジェクトは、ユーザーが登録して求人に応募できる求人情報 Web サイトである必要があります。しかし、ユーザーを登録するだけで行き詰まっています。私のビューには、JSF を使用して構築された register.xhtml ページがあり、モデル パッケージには User.java クラスがあり、コントローラーには UserController Bean もあります。register.xhtml は、 User オブジェクトを永続化することになっている UserController Bean の register() メソッドを呼び出します。

次のように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>  

また、シングルトンであり、内部にシングルトン EntityManagerFactory を持つ PersistenceManager.java クラスも作成しました。

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 を呼び出す登録フォームがあります (すべての i18n キーやその他のもので混乱しているため、ここには含めません)。

register() メソッドが「登録済み」を返す場合、ユーザーをアプリケーション ログインに導くナビゲーション ルールがあります。"duplicateuser" が返された場合は register.xhtml に戻り、別のエラー メッセージがスローされた場合はユーザーを register.xhtml に戻します (これらにはあまりロジックが含まれていないため、単純にする必要がありました)。 )。

問題は、作成された User テーブルを取得しましたが、そこに永続化された User がなく、エラー メッセージ、例外なども何も表示されないということです。デバッグ時に、UserController Bean の EntityTransaction オブジェクトは、トランザクションを begin=true、次に commit=true として表示するため、すべてが機能しているように見えます。しかし、DBをチェックインするとテーブルが作成されましたが、そこにはユーザーがいません:(

また、PersistenceManager をシングルトンとして使用し、UserController Bean 内にすべての永続化ロジックを貼り付けたときに、正しい方法で進んでいるかどうか疑問に思っています。誰かがこれで私を少し導くことができれば、私は非常に感謝しています! :)

4

1 に答える 1

1

getEM() メソッドは、呼び出されるたびに新しい EntityManager を作成します。これは、トランザクションを開始するために使用するエンティティ マネージャーが、後で persist(user); を呼び出すものと同じではないことを意味します。の上。したがって、トランザクションはコミットされますが、変更を含む EM には結び付けられません。

静的 PM を使用して EntityManagers を保持することはお勧めできません。EntityManagers 自体はスレッド セーフではないからです。EntityManagers を取得するために使用するのは良いかもしれませんが、register およびその他のメソッドは entityManager を直接保持する必要があり、完了したら閉じる必要があります。PM には、シャットダウンまたはアンデプロイ時にファクトリを閉じるクリーンアップ メソッドも必要です。

于 2012-11-30T16:39:53.353 に答える