在@RequestScoped bean 的回发中保留 GET 参数
Retain GET parameter on postback on @RequestScoped bean
我想在数据库中仅更新表单中指定的那些字段。在实体 "account" 中,我使用注释 @DynamicUpdate
.
类 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
,以加载数据的形式,点击"Save"。它写入一个错误:
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}"/>
。但这是行不通的。请帮助我。
您的错误是您(懒惰地)在 getter 方法而不是 @PostConstruct
中加载实体。在 JSF 能够调用 setId()
之前,实体正在 loaded/created。无论如何,在 getter 方法中执行业务逻辑是令人担忧的。 You'd better not do that and keep the getter methods untouched.
因为您想使用 @RequestScoped
bean,所以 <f:viewParam>
对您来说不是很有用。准备 @PostConstruct
中的实体为时已晚,因此可以用提交的值填充它。它可以很好地与 @ViewScoped
bean 一起工作,因为它在回发时被重用。
在@RequestScoped
bean中需要自己抓取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>
我想在数据库中仅更新表单中指定的那些字段。在实体 "account" 中,我使用注释 @DynamicUpdate
.
类 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
,以加载数据的形式,点击"Save"。它写入一个错误:
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}"/>
。但这是行不通的。请帮助我。
您的错误是您(懒惰地)在 getter 方法而不是 @PostConstruct
中加载实体。在 JSF 能够调用 setId()
之前,实体正在 loaded/created。无论如何,在 getter 方法中执行业务逻辑是令人担忧的。 You'd better not do that and keep the getter methods untouched.
因为您想使用 @RequestScoped
bean,所以 <f:viewParam>
对您来说不是很有用。准备 @PostConstruct
中的实体为时已晚,因此可以用提交的值填充它。它可以很好地与 @ViewScoped
bean 一起工作,因为它在回发时被重用。
在@RequestScoped
bean中需要自己抓取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>