2011-12-27 9 views
0

Facebookの壁のようなものをしようとしていますが、問題があります。@OneToMayコレクションの更新

私のDBは、ユーザー用と投稿用の2つのテーブルで作成されています。 各投稿には、ユーザへの参照(ユーザテーブルへの外部キー)があります。

私はそれを動作させようとしましたが、それは非常にうまくいって、各ユーザーは自分の投稿を挿入し、他人が作成したものを見ることができます。

新しい投稿を挿入すると、データベースに正しく挿入されますが、次のサーバーが再起動するまで表示されません。 マップされた投稿のコレクションは正しく更新されていないようです。そのため、Beanは最初に実行したときに見つけたものを返します。

は、ここでエンティティをマッピングするために使用されるコードです:

USER

public class User implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id  
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 20) 
@Column(name = "username") 
private String username; 
@Basic(optional = false) 
@NotNull 
@Size(min = 1, max = 45) 
@Column(name = "password") 
private String password; 
@Basic(optional = false) 
@NotNull 
@Column(name = "regDate") 
@Temporal(TemporalType.DATE) 
private Date regDate; 
@Basic(optional = false) 
@NotNull 
@Column(name = "id") 
private int id; 
@Column(name = "birthDate") 
@Temporal(TemporalType.DATE) 
private Date birthDate; 
@Size(max = 255) 
@Column(name = "avatar") 
private String avatar; 
@Size(max = 45) 
@Column(name = "name") 
private String name; 
@Size(max = 45) 
@Column(name = "surname") 
private String surname; 
@OneToMany(mappedBy="utente", fetch = FetchType.EAGER) 
private Collection<Post> posts; 

POST

public class Post implements Serializable { 
private static final long serialVersionUID = 1L; 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
@Basic(optional = false) 
@NotNull 
@Column(name = "id") 
private Integer id = 0; 
@Basic(optional = false) 
@NotNull 
@Lob 
@Size(min = 1, max = 65535) 
@Column(name = "text") 
private String text; 
@Basic(optional = false) 
@NotNull 
@Column(name = "date") 
@Temporal(TemporalType.DATE) 
private Date date; 
@Basic(optional = false) 
@NotNull 
@Column(name = "time") 
@Temporal(TemporalType.TIME) 
private Date time; 
@JoinColumn(name = "user", referencedColumnName = "username") 
@ManyToOne(fetch = FetchType.EAGER, optional = false) 
private User user; 

私はそれをどのように修正することができますか?

編集:

ここでは、投稿と連携するマネージドビーンがあります。ビーンは、その別のビーン(PostManager)を呼び出し、管理

@Named(value = "postsMB") 
@RequestScoped 
public class PostsMB { 

@EJB 
private UtenteFacadeLocal userFacade; 
@EJB 
private PostManagerLocal postManager; 
protected String username; 

/** Creates a new instance of PostsMB */ 
public PostsMB() { 
} 
protected List<Post> posts; 

/** 
* Get the value of posts 
* 
* @return the value of posts 
*/ 
public List<Post> getPosts() { 
    //Let's see if we are trying to display posts from another user (passed with a GET param) or from the logged in user 
    username = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("username"); 
    if (username != null && !username.isEmpty()) { 
     user = userFacade.find(username); 
    } 
    if (user == null) { 
     HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false); 
     user = (Utente) session.getAttribute("user"); 
     if (user == null) { 
      return null; 
     } 
    } 
    //Once we've got the right user, we get all his posts 
    posts = new LinkedList<Post>(user.getPosts());   
    return posts; 
} 
public void insertPost() { 
    //We get the user from the session and we use it to insert the post 
    user = (Utente) ((HttpSession) (FacesContext.getCurrentInstance().getExternalContext().getSession(false))).getAttribute("user"); 
    postManager.insertPost(postText, user); 
} 

(postTextはゲッターとセッターを持つ別のプロパティです)のdataTableとポストを挿入するためのフォームを埋めるために)としてgetPostsを使用してJSFページ(で呼ばれています自動的に生成されたPostFacadeクラスを呼び出して、データをDBに挿入します。

ここに私のログイン方法

User u = userManager.doLogin(username, password); 
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true); 
     session.setAttribute("username", u.getUsername()); 

だと、ここでの私としてgetPostsだ()メソッド:

@Stateless 
public class PostManager implements PostManagerLocal { 

@EJB 
private PostFacadeLocal postFacade; 

@Override 
public void insertPost(Post post) { 
    postFacade.create(post);   
} 

@Override 
public void insertPost(String text, User user) { 
    Post p = new Post(); 
    p.setText(text); 
    p.setUser(user); 
    p.setDate(Calendar.getInstance().getTime()); 
    p.setTime(Calendar.getInstance().getTime()); 
    insertPost(p); 
} 

記事は、Userクラスでこのコードを

@OneToMany(mappedBy="user", fetch = FetchType.EAGER) 
private Collection<Post> posts; 

public Collection<Post> getPosts() {   
    return posts; 
} 

public void setPosts(Collection<Post> posts) { 
    this.posts = posts; 
} 

EDIT 2をretrivedていますポストマネージドビーン

HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false); 
     user = utenteFacade.find(session.getAttribute("username)); 
posts = new LinkedList<Post>(user.getPosts()); 

これは私が前に言ったことを正確に行うはずなので、セッションにユーザー名(プレーンストリング)を格納してからファサードのfindメソッドを呼び出してユーザーの新しいインスタンスを取得します。 どうしたの?

EDIT 3:

UtenteFacade

@Stateless 
public class UtenteFacade extends AbstractFacade<Utente> implements UtenteFacadeLocal { 
@PersistenceContext(unitName = "LoginSession-ejbPU") 
private EntityManager em; 

@Override 
protected EntityManager getEntityManager() { 
    return em; 
} 

public UtenteFacade() { 
    super(Utente.class); 
} 

}

AbstractFacade

public abstract class AbstractFacade<T> { 
private Class<T> entityClass; 

public AbstractFacade(Class<T> entityClass) { 
    this.entityClass = entityClass; 
} 

protected abstract EntityManager getEntityManager(); 

public void create(T entity) { 
    getEntityManager().persist(entity); 
} 

public void edit(T entity) { 
    getEntityManager().merge(entity); 
} 

public void remove(T entity) { 
    getEntityManager().remove(getEntityManager().merge(entity)); 
} 

public T find(Object id) { 
    return getEntityManager().find(entityClass, id); 
} 

public List<T> findAll() { 
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
    cq.select(cq.from(entityClass)); 
    return getEntityManager().createQuery(cq).getResultList(); 
} 

public List<T> findRange(int[] range) { 
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
    cq.select(cq.from(entityClass)); 
    javax.persistence.Query q = getEntityManager().createQuery(cq); 
    q.setMaxResults(range[1] - range[0]); 
    q.setFirstResult(range[0]); 
    return q.getResultList(); 
} 

public int count() { 
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
    javax.persistence.criteria.Root<T> rt = cq.from(entityClass); 
    cq.select(getEntityManager().getCriteriaBuilder().count(rt)); 
    javax.persistence.Query q = getEntityManager().createQuery(cq); 
    return ((Long) q.getSingleResult()).intValue(); 
} 
+2

Showは、投稿を作成して読むために使用するコードを使用して、トランザクションの開始とコミットを通知します。 –

+2

ヒントは、コードで母国語を使用しないでください。これは後でいつもあなたに噛み付くでしょう。例えば、このようなサイトで助けを求めるとき。 –

答えて

0

ユーザーのポストを得るとき、あなたはセッションからユーザーを取得します。したがって、セッションにユーザーを格納してからいくつかの投稿が追加または削除された場合は、表示されません。

セッションでユーザーをキャッシュしないでください。すべて正常です。ユーザーがどこかにキャッシュされなければならない場合、ユーザーはHibernate第2レベルキャッシュに入っています。

+0

私はそれを呼び出すたびにデータベースから取得するgetPosts()メソッドではありませんが、 – StepTNT

+0

いいえ。ユーザーのロードに使用されたセッションが終了すると(通常はトランザクションの終了時に)、ユーザーは分離オブジェクトPOJOになります。添付されていても、投稿のコレクションが読み込まれると、それはデータベースからもう読み込まれません。そうした場合、エンティティを呼び出すたびに選択クエリがトリガされ、パフォーマンスは非常に悪くなります。非常に重要な原則を理解していないので、ハイバネート参照文書を必ず読んでください。 –

+0

あなたはPersistence Contextについて話していますか? – StepTNT

関連する問題