2015-01-07 56 views
0

我想在數據庫中僅更新表單中指定的那些字段。在實體「帳戶」中,我使用註釋@DynamicUpdate在@RequestScoped bean上回發時保留GET參數

AccountMB@RequestScoped)與方法:

public String update() { 
    getDao().update(getInstance()); 
    return SUCCESS; 
} 

public Account getInstance() { 

    //setId(new Long("1")); 

    if (instance == null) { 
     if (id != null) { 
      instance = loadInstance(); 
     } else { 
      instance = createInstance(); 
     } 
    } 

    return instance; 
} 

,並形成form.xhtml:

<f:metadata> 
    <f:viewParam name="accountId" value="#{accountMB.id}" /> 
</f:metadata> 

<h:form prependId="false"> 

    <h:inputHidden id="accountId" value="#{accountMB.id}"/> 

    <h:inputHidden id="id" value="#{accountMB.instance.id}"/> 

    <h:inputText id="firstName" value="#{accountMB.instance.firstName}"/> 

    <h:commandButton type="submit" action="#{accountMB.update}" value="Save"> 
     <f:setPropertyActionListener target="#{accountMB.id}" value="1" /> 
    </h:commandButton> 
</h:form> 

我打開form.xhtml?accountId=1頁面,在加載數據的形式,點擊 「保存」。它寫一個錯誤:

java.sql.SQLException: ORA-01407: cannot update ("MYBD"."ACCOUNTS"."EMAIL") to NULL 

如果getInstance()方法取消註釋setId(new Long("1"));,該數據被保存。

如果我在AccountMB中使用註釋@ViewScoped,數據將被保存。我想使用註釋@RequestScoped

據我所知,我觸發了createInstance();並且電子郵件字段沒有填寫。

告訴我如何通過id加載方法loadInstance();。我用<f:setPropertyActionListener target="#{accountMB.id}" value="1" /><h:inputHidden id="accountId" value="#{accountMB.id}"/>。但這是行不通的。請幫幫我。

回答

0

你的錯誤是你(懶惰)在getter方法而不是@PostConstruct中加載實體。在JSF能夠調用setId()之前,該實體正在被加載/創建。無論如何,在getter方法中執行業務邏輯都是令人震驚的。 You'd better not do that and keep the getter methods untouched

如果您想使用@RequestScoped bean,那麼<f:viewParam>對您來說並不是非常有用。準備@PostConstruct中的實體爲時已晚,以便可以填寫提交的值。它會在@ViewScoped bean上正常工作,因爲它在回發時被重用。

@RequestScoped豆你需要抓住自己的HTTP請求參數:

@Named 
@RequestScoped 
public class AccountBacking { 

    private Account account; 

    @EJB 
    private AccountService service; 

    @PostConstruct 
    public void init() { 
     String id = FacesContext.getCurrentInstance().getRequestParameterMap().get("accountId"); 
     account = (id != null) ? service.find(Long.valueOf(id)) : new Account(); 
    } 

    public void save() { 
     service.save(account); 
    } 

    public Account getAccount() { 
     return account; 
    } 

} 

然後你就可以擺脫這種形式,因此只是<f:param>被用來保留在回發的GET參數:

<h:form> 
    <h:inputText id="firstName" value="#{accountBacking.account.firstName}"/> 

    <h:commandButton action="#{accountBacking.save}" value="Save"> 
     <f:param name="accountId" value="#{param.accountId}" /> 
    </h:commandButton> 
</h:form>