我使用JPA2與執行的EclipseLink在Glassfish 3.JPA實體更新不及時正確
我有一個簡單的登錄/註銷申請。
這些都是實體Bean的及其映射:
@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實現。所有的方法工作得很好,但問題是,有時保存在Persistance上下文/ JPA緩存中的實體對象不會與數據庫信息同步。
作爲一個具體的例子,當我刪除一些用戶的詳細信息(從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;
}
你的UserService是什麼樣的? – zellus 2012-02-12 23:51:07
@zellus我更新了問題 – TGM 2012-02-13 07:18:06
你如何刪除UserDetail? – 2012-02-13 08:19:49