我正在尝试做类似Facebook的墙,但我遇到了问题。
我的数据库只有两个表,一个用于用户,一个用于帖子。 每个帖子都有对用户的引用(用户表的外键)。
我试图让它工作并且它很好,每个用户都可以插入自己的帖子并看到其他人制作的帖子,但插入功能不能正常工作!
当我插入一个新帖子时,它已正确插入数据库,但它只是在下一次服务器重启之前不会显示! 似乎映射的帖子集合没有正确更新,因此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;
我该如何解决?
编辑:
这是与帖子一起使用的Managed Bean。它由JSF页面调用,该页面使用getPosts()填充dataTable,并使用表单插入帖子(postText是另一个具有getter和setter的属性)
@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);
}
这个托管Bean调用另一个Bean(PostManager),它只调用一个自动生成的PostFacade类,它将数据插入到数据库中。
@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);
}
使用此类代码
中的代码重新发布帖子@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;
}
编辑2:
这是我的登录方法
User u = userManager.doLogin(username, password);
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
session.setAttribute("username", u.getUsername());
这是Posts Managed Bean的getPosts()方法
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
user = utenteFacade.find(session.getAttribute("username));
posts = new LinkedList<Post>(user.getPosts());
它应该完全按照我之前说过的方式执行,因此我将用户名(plain String)存储到会话中,然后调用facade的find方法来获取用户的新实例。 怎么了?
编辑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();
}
答案 0 :(得分:0)
当您收到用户的帖子时,您将从会话中获得该用户。因此,很明显,如果您在会话中存储用户后添加或删除了某些帖子,您将看不到它们。
不要将用户缓存在会话中,一切都会好的。如果用户必须在某处缓存,则它位于Hibernate二级缓存中。