Я пытаюсь сделать что-то вроде стены Facebook, но у меня есть проблема.
Моя база данных состоит всего из двух таблиц: одна для пользователей и одна для сообщений.В каждом сообщении есть ссылка на пользователя (внешний ключ к пользовательской таблице).
Я пытался заставить его работать, и все идет отлично, каждый пользователь может вставить свои собственные сообщения и увидеть сделанныйдругими, но функция вставки работает не так, как должна!
Когда я вставляю новое сообщение, оно корректно вставляется в базу данных, но просто не будет отображаться до следующего перезапуска сервера!Кажется, что сопоставленная коллекция постов не обновлена правильно, поэтому бин вернет тот, который он нашел при первом запуске.
Вот код, используемый для сопоставления сущностей:
ПОЛЬЗОВАТЕЛЬ
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;
Как это исправить?
РЕДАКТИРОВАТЬ:
Вот управляемый компонент, который работает с сообщениями.Он вызывается страницей 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());
, а вот мой метод getPosts () для управляемого сообщения
HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
user = utenteFacade.find(session.getAttribute("username));
posts = new LinkedList<Post>(user.getPosts());
Он должен делать именно то, что я говорил ранее, поэтомуЯ сохраняю имя пользователя (plain String) в сеансе, а затем вызываю метод 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();
}