I have a problem with entities not being refreshed when values in the database are changed from outside the JPA session. For instance, I have a user entity:
@Entity
@Cacheable(false)
public class UserBean implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToMany(mappedBy = "receiver")
@JoinTable(name = "NOTIFICATIONS_RECEIVED")
private List<NotificationBean> notificationsReceived;
...
}
And notifications entity:
@Entity
@Cacheable(false)
public class NotificationBean implements Serializable{
@Id
@GeneratedValue
private Long id;
@ManyToOne
private UserBean receiver;
...
}
I use this inside a JSF application and have a SessionScoped bean, which loads the user after login and stores it:
@Named("sessionManager")
@SessionScoped
public class SessionManagerBean implements Serializable {
@PersistenceUnit(unitName = "PU")
private EntityManagerFactory emf;
private UserBean user;
public UserBean getUser() throws Exception {
if (user == null) {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
String username = request.getRemoteUser();
if (username != null) {
EntityManager em = null;
try {
utx.begin();
em = emf.createEntityManager();
Query query = em.createQuery("SELECT u from UserBean u WHERE u.username = ?1");
query.setParameter(1, username);
user = (UserBean) query.getSingleResult();
}
catch (Exception e) {
try {
utx.rollback();
} catch (Exception e) {
} finally {
utx.commit();
em.close();
}
}
return user;
}
}
}
public void refreshUser() {
EnitytManager em = emf.createEntityManager();
// similar code as above to retrieve the user from the database
em.refresh(user);
}
}
The page which displays the notifications calls refreshUser()
when it loads:
<f:metadata>
<f:event type="preRenderView" listener="#{sessionManager.refreshUser()}" />
</f:metadata>
The user data is not refreshed though and notifications which are displayed on the page are not updated when I refresh the page.
However, if I change refreshUser()
to:
public void refreshUser() {
EntityManager em = emf.createEntityManager();
List<NotificationBean> notifications = em.createNativeQuery("SELECT * FROM NOTIFICATIONBEAN WHERE RECEIVER_ID = " +
user.getId() + ";").getResultList();
user.setMatchChallengesReceived(notifications);
}
the notifications are updated.
I have more variable than notifications that I need to refresh from the database and it would be a lot of code to do the same for each one. I thought em.refresh(user)
should reload all variables that have changed from the database for me. I thought it is a caching issue, so I added @Cacheable(false)
to UserBean
and NotificationBean
, but it has no effect.
What am I doing wrong?