Я использую JPA2 с реализацией Eclipselink на Glassfish 3.
У меня есть простое приложение для входа / выхода.
Это бины сущностей и их отображения:
@Entity
@Table(name = "user_account")
public class UserAccount implements Serializable{
@Id
private Integer id;
private String email;
private String password;
private Integer role;
@OneToOne(fetch=FetchType.EAGER)
@PrimaryKeyJoinColumn
private UserDetail userDetail;
// get+set
}
@Entity
@Table(name = "user_detail")
public class UserDetail implements Serializable{
private static final long serialVersionUID = 1L;
@Id
private Integer id;
@Temporal(TemporalType.DATE)
private Date birth;
@Column(name="origin_city")
private String originCity;
@Column(name="residence_city")
private String residenceCity;
private String description;
@OneToOne(mappedBy="userDetail")
private UserAccount userAccount;
}
В классе UserService
у меня есть простая реализация CRUD.Все методы работают нормально, но проблема в том, что иногда объект Entity, сохраненный в контексте Persistance / JPA Cache, не синхронизируется с информацией базы данных.
В качестве конкретного примера, когда я удаляю некоторые пользовательские данные (из таблицы user_detail) запись базы данных удаляется, но когда я снова читаю информацию, возвращаемая сущность все еще имеет информацию Details.Я предполагаю, что эта информация была сохранена в кеше JPA и возвращена без предварительной проверки базы данных.
Это правильное поведение?Есть ли способ сохранить информацию кэша синхронизированной с базой данных?
LE : Пользовательская служба содержит метод read(email, password)
, который вызывает вспомогательный метод.Этот вспомогательный метод содержит запрос CriteriaAPI, который приносит всем пользователям желаемый адрес электронной почты и пароль.Запрос Criteria протестирован и работает нормально.
public UserAccount read(String email, String password){
List<UserAccount> userList = getUserList(null, email, password, Constants.RESULT_SINGLE);
return (userList.isEmpty() ? null : userList.get(0));
}
private List<UserAccount> getUserList(Integer id, String email, String password, String resultType){
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<UserAccount> shell = builder.createQuery(UserAccount.class);
Root<UserAccount> entity = shell.from(UserAccount.class);
shell.select(entity);
shell.distinct(true);
List<Predicate> predicateList = new ArrayList<Predicate>();
if (id != null){
ParameterExpression<Integer> param = builder.parameter(Integer.class, "id");
predicateList.add(builder.equal(entity.get("id"), param));
}
if (email != null){
ParameterExpression<String> param = builder.parameter(String.class, "email");
predicateList.add(builder.equal(entity.get("email"), param));
}
if (password != null){
ParameterExpression<String> param = builder.parameter(String.class, "password");
predicateList.add(builder.equal(entity.get("password"), param));
}
if (predicateList.size() == 1){
shell.where(predicateList.get(0));
} else {
Predicate[] p = new Predicate[predicateList.size()];
p = predicateList.toArray(p);
shell.where(builder.and(p));
}
TypedQuery<UserAccount> selectQuery = em.createQuery(shell);
if (id != null) selectQuery.setParameter("id", id);
if (email != null) selectQuery.setParameter("email", email);
if (password != null) selectQuery.setParameter("password", password);
return selectQuery.getResultList();
}
Это метод удаления из службы:
public boolean deleteDetail(Integer userId) {
boolean ok = true;
try {
UserDetail userDetails = em.find(UserDetail.class, userId);
System.out.println("Trying to delete the detail. The address of the object is: " + userDetails);
em.remove(userDetails);
System.out.println("Object deleted. The address is: " + userDetails);
} catch (Exception e) {
e.printStackTrace();
ok = false;
}
return ok;
}