在 h:dataTable 中更新后,更改未反映在 JPA 实体中
我正在使用 Eclipse 和 Glassfish 3.0。尽管我以前做过类似的事情,但对这项技术来说还是很新的。非常简单,确实将数据表绑定到支持 bean。添加方法和删除我已经介绍过的方法 - 问题出在我调用的更新方法上。我似乎看不到组件(HtmlInputText)中发生的更改,更不用说将数据传递回表了。
我的数据表代码如下(以及jsf页面)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:loadBundle basename="resources.application" var="msg"/>
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<body>
<h:form id="mainform">
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
<f:facet name="header">
<h:outputText value="Categories"/>
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText id="input1" value="#{row.description}" valueChangeListener="#{row.inputChanged}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText id="id" value="#{row.id}"/>
</h:column>
<h:column>
<h:commandButton value="Delete" type="submit" action="#{beanCategory.remove}">
<f:setPropertyActionListener target="#{beanCategory.selectedcategory}" value="#{row}"/>
</h:commandButton>
<h:commandButton value="Save" action="#{beanCategory.update}"
>
<f:setPropertyActionListener
target="#{beanCategory.selectedcategory}" value="#{row}" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:inputText id="text1"></h:inputText> <h:commandButton action="#{beanCategory.addCategory}" value="Add" type="submit" id="submitbutton">
</h:commandButton>
<br/><br/>
Messages
<h:messages></h:messages><br /><br />
</h:form>
</body>
</html>
支持 Bean 在这里
package net.bssuk.timesheets.controller;
import java.io.Serializable;
import java.util.List;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.context.FacesContext;
import javax.persistence.*;
import net.bssuk.timesheets.model.Category;
@javax.inject.Named("beanCategory")
@javax.enterprise.context.SessionScoped
public class BeanCategory implements Serializable {
private List<Category> collection;
private EntityManagerFactory emf;
private EntityManager em;
private int selectedid;
private Category selectedcategory;
private HtmlDataTable datatable;
private static final long serialVersionUID = 1L;
public BeanCategory() {
// TODO Auto-generated constructor stub
System.out.println("Bean Constructor");
}
public String addCategory() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Changed - Now attempting to add");
System.out.println("Ready to do cateogory");
Category category = new Category();
FacesContext context = FacesContext.getCurrentInstance();
UIInput input = (UIInput) context.getViewRoot().findComponent(
"mainform:text1");
String value = input.getValue().toString();
if (value != null) {
category.setDescription(input.getValue().toString());
} else {
category.setDescription("Was null");
}
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(category);
tx.commit();
em.close();
emf.close();
// return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
}
return "return.html";
}
public String remove() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Getting Collection");
this.em = this.emf.createEntityManager();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("Number found is " + this.selectedid);
if (selectedcategory != null) {
System.out.println("removing "+selectedcategory.getId()+" - " +selectedcategory.getDescription());
EntityTransaction tx = em.getTransaction();
tx.begin();
System.out.println("Merging..");
this.em.merge(selectedcategory);
System.out.println("removing...");
this.em.remove(selectedcategory);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "index.xhtml";
}
}
public String update() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Update Getting Collection");
Category category = (Category) getDatatable().getRowData();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("PHASE ID="+context.getCurrentPhaseId().toString());
if (category != null) {
// DESCRIPTION VALUE BELOW IS ALWAYS OLD VALUE (IE DATA IN DATABASE)
System.out.println("updating "+category.getId()+" - " +category.getDescription());
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.merge(category);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public void setCollection(List<Category> collection) {
this.collection = collection;
}
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setSelectedid(int id) {
this.selectedid=id;
}
public void setSelectedcategory(Category selectedcategory) {
this.selectedcategory = selectedcategory;
}
public HtmlDataTable getDatatable() {
return datatable;
}
public void setDatatable(HtmlDataTable datatable) {
this.datatable = datatable;
}
public Category getSelectedcategory() {
return selectedcategory;
}
}
我的 JPA 映射实体在这里
package net.bssuk.timesheets.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the CATEGORIES database table.
*
*/
@Entity
@Table(name="CATEGORIES")
@NamedQuery(name="findAll", query = "SELECT c from Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private String description;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
public Category() {
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
好的 - 更新了我的代码以遵循示例。我尝试将 EJB 合并到场景中,如下所示
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
@Stateless
public class CategoryEJB implements CategoryEJBRemote {
@PersistenceContext(unitName="timesheets1")
private EntityManager em;
@Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
@Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
@Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
@Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
我的 EJB 如下
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
@Stateless
public class CategoryEJB implements CategoryEJBRemote {
@PersistenceContext(unitName="timesheets1")
private EntityManager em;
@Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
@Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
@Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
@Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
谁能建议这种看起来是否可以?或者我完全失去了它的情节!
I am working with Eclipse and Glassfish 3.0. Pretty new to this technology although I have done similar things before. Very simple really got a datatable bound to a backing bean. Add methods and remove methods i have covered - the problem lies with the update method I am calling. I cannot seem to see the changes being picked up in the component (HtmlInputText) never mind passing the data back to the table.
My code for the data table is below (and the jsf page)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<f:loadBundle basename="resources.application" var="msg"/>
<head>
<title><h:outputText value="#{msg.welcomeTitle}" /></title>
</head>
<body>
<h:form id="mainform">
<h:dataTable var="row" border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">
<f:facet name="header">
<h:outputText value="Categories"/>
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:inputText id="input1" value="#{row.description}" valueChangeListener="#{row.inputChanged}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Id"/>
</f:facet>
<h:outputText id="id" value="#{row.id}"/>
</h:column>
<h:column>
<h:commandButton value="Delete" type="submit" action="#{beanCategory.remove}">
<f:setPropertyActionListener target="#{beanCategory.selectedcategory}" value="#{row}"/>
</h:commandButton>
<h:commandButton value="Save" action="#{beanCategory.update}"
>
<f:setPropertyActionListener
target="#{beanCategory.selectedcategory}" value="#{row}" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:inputText id="text1"></h:inputText> <h:commandButton action="#{beanCategory.addCategory}" value="Add" type="submit" id="submitbutton">
</h:commandButton>
<br/><br/>
Messages
<h:messages></h:messages><br /><br />
</h:form>
</body>
</html>
Backing Bean is here
package net.bssuk.timesheets.controller;
import java.io.Serializable;
import java.util.List;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlDataTable;
import javax.faces.context.FacesContext;
import javax.persistence.*;
import net.bssuk.timesheets.model.Category;
@javax.inject.Named("beanCategory")
@javax.enterprise.context.SessionScoped
public class BeanCategory implements Serializable {
private List<Category> collection;
private EntityManagerFactory emf;
private EntityManager em;
private int selectedid;
private Category selectedcategory;
private HtmlDataTable datatable;
private static final long serialVersionUID = 1L;
public BeanCategory() {
// TODO Auto-generated constructor stub
System.out.println("Bean Constructor");
}
public String addCategory() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Changed - Now attempting to add");
System.out.println("Ready to do cateogory");
Category category = new Category();
FacesContext context = FacesContext.getCurrentInstance();
UIInput input = (UIInput) context.getViewRoot().findComponent(
"mainform:text1");
String value = input.getValue().toString();
if (value != null) {
category.setDescription(input.getValue().toString());
} else {
category.setDescription("Was null");
}
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(category);
tx.commit();
em.close();
emf.close();
// return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
}
return "return.html";
}
public String remove() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Getting Collection");
this.em = this.emf.createEntityManager();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("Number found is " + this.selectedid);
if (selectedcategory != null) {
System.out.println("removing "+selectedcategory.getId()+" - " +selectedcategory.getDescription());
EntityTransaction tx = em.getTransaction();
tx.begin();
System.out.println("Merging..");
this.em.merge(selectedcategory);
System.out.println("removing...");
this.em.remove(selectedcategory);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "index.xhtml";
}
}
public String update() {
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
System.out.println("Update Getting Collection");
Category category = (Category) getDatatable().getRowData();
FacesContext context = FacesContext.getCurrentInstance();
System.out.println("PHASE ID="+context.getCurrentPhaseId().toString());
if (category != null) {
// DESCRIPTION VALUE BELOW IS ALWAYS OLD VALUE (IE DATA IN DATABASE)
System.out.println("updating "+category.getId()+" - " +category.getDescription());
this.em = this.emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.merge(category);
tx.commit();
em.close();
emf.close();
}else{
System.out.println("Not found");
}
return "index.xhtml";
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public void setCollection(List<Category> collection) {
this.collection = collection;
}
public List<Category> getCollection() {
// this.emf=Persistence.createEntityManagerFactory("timesheets1");
// System.out.println("Getting Collection");
try {
this.emf = Persistence.createEntityManagerFactory("timesheets1");
this.em = this.emf.createEntityManager();
Query query = this.em.createNamedQuery("findAll");
this.collection = query.getResultList();
return this.collection;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void setSelectedid(int id) {
this.selectedid=id;
}
public void setSelectedcategory(Category selectedcategory) {
this.selectedcategory = selectedcategory;
}
public HtmlDataTable getDatatable() {
return datatable;
}
public void setDatatable(HtmlDataTable datatable) {
this.datatable = datatable;
}
public Category getSelectedcategory() {
return selectedcategory;
}
}
My Mapped entity for JPA is here
package net.bssuk.timesheets.model;
import java.io.Serializable;
import javax.persistence.*;
/**
* The persistent class for the CATEGORIES database table.
*
*/
@Entity
@Table(name="CATEGORIES")
@NamedQuery(name="findAll", query = "SELECT c from Category c")
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
private String description;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
public Category() {
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
}
OK - Updated my code to follow example. I have tried to incorporate an EJB into the scenario as follows
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
@Stateless
public class CategoryEJB implements CategoryEJBRemote {
@PersistenceContext(unitName="timesheets1")
private EntityManager em;
@Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
@Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
@Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
@Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
My EJB is below
package net.bssuk.timesheets.ejb;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import net.bssuk.timesheets.model.Category;
@Stateless
public class CategoryEJB implements CategoryEJBRemote {
@PersistenceContext(unitName="timesheets1")
private EntityManager em;
@Override
public List<Category> findCategories() {
// TODO Auto-generated method stub
System.out.println("find categories");
Query query = em.createNamedQuery("findAll");
return query.getResultList();
}
@Override
public Category createCategory(Category category) {
// TODO Auto-generated method stub
em.persist(category);
return category;
}
@Override
public Category udpateCategory(Category category) {
// TODO Auto-generated method stub
return em.merge(category);
}
@Override
public void deleteCategory(Category category) {
// TODO Auto-generated method stub
em.remove(em.merge(category));
}
}
Can anyone suggest if this sort of looks ok? Or have I completely lost the plot with it!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
,
看
您正在 getter 方法中加载列表。这是一个非常糟糕的主意。 getter 应该只是 bean 属性的访问点,而不是做一些业务工作。 getter 在 bean 的生命周期中可以被多次调用。每次调用都会触发数据库,并且 JSF 在表单提交期间更新的本地
collection
属性将在稍后再次被覆盖。这毫无意义。在(后)构造函数方法或操作(侦听器)方法中完成业务工作。绝对不是吸气剂。下面是一个带有一些代码改进的最小启动示例:
(请注意,自 EL 2.2(Servlet 3.0 的一部分)以来就支持在 EL 中传递参数,Glassfish 3 是 Servlet 3.0 容器,因此当
时它绝对应该支持它web.xml
已正确声明为符合 Servlet 3.0 规范)应该就是这样
。另请参阅:
Look,
and
You're loading the list inside a getter method. This is a very bad idea. A getter should solely be an access point to the bean property, not to do some business job. A getter can be called multiple times during bean's life. The DB will be hit on every call and the local
collection
property which was been updated by JSF during form submit will be overwritten again at a later point. This makes no sense.Do the business job in the (post)constructor method or action(listener) methods. Definitely not in a getter. Here's a minimum kickoff example with some code improvements:
(note that passing arguments in EL is supported since EL 2.2 (part of Servlet 3.0), Glassfish 3 is a Servlet 3.0 container, so it should definitely support it when
web.xml
is properly declared conform Servlet 3.0 spec)with
That should be it. See also:
正如我所见,您忘记了
。这对于保存输入是非常必要的。As I see, you have forgotten the
<h:form>
. This is very necessary to save inputs.