【问题标题】:Store a value manually setted in Database存储在数据库中手动设置的值
【发布时间】:2015-02-23 23:27:04
【问题描述】:

我有一个 jsf 表单,用户在其中键入一个 int 和一个字符串值,单击“保存”按钮后将它们存储在数据库中。

<h:form id="TbtestCreateForm">
    <p:inputText value="#{tbtestController.selected.name}" />
    <p:commandButton actionListener="#{tbtestController.saveNew}" value="#{myBundle.Save}" />
</h:form>

我正在使用具有外观模式的 EJB,它执行 AbstractController 类中定义的 CRUD 操作,该类使用“绑定”实体类的 AbstractFacade。

我需要的是手动硬编码/设置表单中的字符串值,并将其与用户通知的 int 值一起存储在数据库中,在同一操作中(同一对象) .

我尝试过如下操作,但没有成功:

@Named
public class MyBean implements Serializable {

@Inject
TbtestController tbtestController;

private String myName;
//GETTERS AND SETTERS

@PostConstruct
public void init() {
    myName = "some foo name";
    Tbtest myTbtest = new Tbtest();
    myTbtest.setName(myName);
    tbtestController.setSelected(myTbtest);
    tbtestController.saveNew(null); // to simulate what the savNew method do
}

我创建了一个可以在以下位置克隆的小型 netbeans 项目:https://github.com/f6750699/webAppTest.git

下面是 AbstractController 类中定义的 2 个方法:

saveNew 方法:

public void saveNew(ActionEvent event) {
    String msg = ResourceBundle.getBundle("/MyBundle").getString(itemClass.getSimpleName() + "Created");
    persist(PersistAction.CREATE, msg);
    if (!isValidationFailed()) {
        items = null; // Invalidate list of items to trigger re-query.
    }
} 

persist 方法:

private void persist(PersistAction persistAction, String successMessage) {
    if (selected != null) {
        this.setEmbeddableKeys();
        try {
            if (persistAction != PersistAction.DELETE) {
                this.ejbFacade.edit(selected);
            } else {
                this.ejbFacade.remove(selected);
            }
            JsfUtil.addSuccessMessage(successMessage);
        } catch (EJBException ex) {
            Throwable cause = JsfUtil.getRootCause(ex.getCause());
            if (cause != null) {
                if (cause instanceof ConstraintViolationException) {
                    ConstraintViolationException excp = (ConstraintViolationException) cause;
                    for (ConstraintViolation s : excp.getConstraintViolations()) {
                        JsfUtil.addErrorMessage(s.getMessage());
                    }
                } else {
                    String msg = cause.getLocalizedMessage();
                    if (msg.length() > 0) {
                        JsfUtil.addErrorMessage(msg);
                    } else {
                        JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
                    }
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
            JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/MyBundle").getString("PersistenceErrorOccured"));
        }
    }
}

我非常感谢一些帮助,因为我已经坚持了一段时间。

提前致谢。


保罗莫里斯解决方案

正如保罗建议的那样,我专注于一门课:

@Named
@ViewScoped
public class TbtestController extends AbstractController<Tbtest> {

@EJB
private TbtestFacade ejbFacade;

public TbtestController() {
    super(Tbtest.class); //-> there is already an invocation here, see below
}

@PostConstruct
@Override
public void init() {
    super.setFacade(ejbFacade);
//Paul Morris solution below
    myName = "some foo name";
    this.setMyName(myName);
    this.saveNew(null); // to simulate what the savNew method do
}

private String myName;

public void setMyName(String name) {
    myName = name;
}

@Override
public void saveNew(ActionEvent event) {
    this.getSelected().setName(myName);
    //super.(event); // -> invocation of a superclass constructor must be the first line in the subclass constructor, but there is already one invocation, see above. Then, I've tried to invoke the super method:
   super.saveNew(event); // but this didn't resolved, as it launches a NullPointerException, see below.
 }
}

例外:

org.jboss.weld.exceptions.WeldException: WELD-000049: Unable to invoke public void beans.TbtestController.init() on beans.TbtestController@37668b21
[...]
Caused by: java.lang.NullPointerException
at beans.TbtestController.saveNew(TbtestController.java:40)
at beans.TbtestController.init(TbtestController.java:29)
... 87 more

【问题讨论】:

  • 但没有成功”。此 EL #{tbtestController.selected.name} 是否评估为 null?您是否遇到了一些错误/异常,或者发生了一些完全不同/奇怪的事情?
  • 不,当用户键入字符串值时,此 EL 工作正常,但我希望他只键入整数,字符串应手动设置。我试过的是#{myBean.myName},得到了value="#{myBean.myName}": Target Unreachable, identifier 'myBean' resolved to null。我需要在某个类中设置/硬编码值,但我不知道在哪里......
  • CDI bean 的默认范围是@Dependent。您可以尝试指定您需要的适当范围,或者该 bean 应该具有 @Dependent 范围吗?
  • 提到的异常已经在 MyBean 中使用了@SessionScoped...

标签: jsf jakarta-ee ejb persistence facade


【解决方案1】:

这一切都错了。将 AbstractController 类保留为已生成。相反,修改派生类 TbtestController 并为硬编码字符串添加一个属性。然后重写 saveNew 方法,如下所示:

private String myName;

public void setMyName(String name) {
    myName = name;
}

@Override
public void saveNew(ActionEvent event) {
    this.getSelected().setName(myName);
    super.saveNew(event);    

}  

你的 bean 方法应该像这样编码:

@PostConstruct
public void init() {
    myName = "some foo name";
    tbtestController.setMyName(myName);

}

虽然我不确定你为什么有 MyBean 类。在 Controller 中对字符串进行硬编码,然后在表单中使用 Controller saveNew 方法,就像问题顶部一样。

更新

试试这个...

@Named
@ViewScoped
public class TbtestController extends AbstractController<Tbtest> {

    @EJB
    private TbtestFacade ejbFacade;

    public TbtestController() {
        super(Tbtest.class); //-> there is already an invocation here, see below
    }

    @PostConstruct
    @Override
    public void init() {
        super.setFacade(ejbFacade);
        //Paul Morris solution below
        myName = "";

    }

    private String myName;

    public void setMyName(String name) {
        myName = name;
    }

    public String getMyName(String name) {
        if (myName.isEmpty()) {
            myName = "Default Value";
        }
        return myName;
    }


    @Override
    public void saveNew(ActionEvent event) {
        this.getSelected().setName(this.getMyName(myName));
        super.saveNew(event); 
    }
}

【讨论】:

  • Paul Morris,非常感谢您的帮助,但我已尝试使用您的解决方案,但仍有一些问题。请您检查更新的帖子并帮助我吗?非常感谢。
  • 我做了一些改变。请参阅更新部分了解控制器的外观。试试这个,它应该可以工作。
  • 是的,你完全按照我想要的方式解决了!我不知道如何报复,因为这对我来说太重要了。伙计,我太高兴了!!上帝保佑你,兄弟!
【解决方案2】:

请注意:在 JSF 中,MVC 控制器不是用户编写的代码。它们是 FacesServlet 和标签实现。

当人们将 JSF 支持 bean 命名为“XXXController”时,我的迂腐倾向变得很糟糕。一个backing bean是一个模型。 action 方法和 Listeners 是额外的 MVC 功能,而不是 Controller 方法。 Controller 所做的只是将数据复制到 View 和从 View 复制数据,正如我所说,JSF 会自动执行此操作,而无需求助于用户代码。

【讨论】:

  • 我已经知道了(检查 myBean.java)。事实上,正如他所建议的那样,我已经使用这种方式为 Paul Morris 提供便利。但是感谢您的关注。
猜你喜欢
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-13
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多