2014-11-05 183 views
3

我有表格帳戶包含FK到另一個表。

選項1:使用Spring Data JPA更新實體的正確方法是什麼?

@Override 
@Transactional(readOnly = false) 
public Account changePassword(Account existingAccount, String newPassword){ 
    existingAccount.setPassword(newPassword); 
    return accountDAO.save(existingAccount); 
} 

這樣一來,每當我打電話保存(),一個連接是由檢索另一個表ID,然後更新本身。
請注意,即使只更改密碼,所有字段也會更新。

編輯:我發現正在建立連接,因爲我將實體作爲參數傳遞(existingAccount)。如果我在changePassword方法中找到它,它可以正常工作(無連接)。問題是,我需要在控制器中使用此實體進行驗證,因此使相同的數據庫調用2次是毫無意義的。

選項2:

@Modifying 
@Query("UPDATE Account SET password=(:pass) WHERE username=(:username)") 
public void changePassword(@Param("username")String username, @Param("pass")String pass); 

這種方式,僅在@Query自定義更新被執行。

我認爲選項2可能更好,如果涉及到性能,但選項1感覺更像jpa。任何建議感激。

+0

您應該添加'Account'和'AccountRepository'界面的代碼 – 2014-11-05 16:18:33

+0

真的沒有什麼可添加的。選項1是服務層代碼,存儲庫中沒有任何內容,選項2是存儲庫接口代碼。服務層只是調用它,就是這樣。 – Sikor 2014-11-05 16:26:09

回答

2

這兩個都應該沒問題。

動態更新(可選 - 默認爲false):如果你想使用第一種方式,但要避免更新除密碼字段,你可以用註釋@DynamicUpdate(value=true)configure dynamic-update指定用於UPDATE的SQL將會在運行時生成,並可以只包含那些值已更改的列。

您需要使用select-before-update或樂觀鎖定。 select-before-update可能會比更新所有字段的性能更差。

顯然this is implementation-specific and not part of JPA

+0

查看它atm和@ org.hibernate.annotations.Entity已棄用,但@DynamicUpdate(value = true)取而代之。它按照你說的那樣工作,但唯一的問題是第一個選項在更新之前仍然執行連接(甚至現在只更新1個字段 - 密碼)。 – Sikor 2014-11-05 16:36:49

+0

@Sikor:有趣。也許會讓這個聯盟變得懶惰? – 2014-11-05 16:39:14

+0

@OneToOne(fetch = FetchType.LAZY,cascade = CascadeType.ALL)@JoinColumn(name =「pilot_id」),這是懶惰的:D – Sikor 2014-11-05 16:40:05

相關問題