在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>

Backing 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;
}
}

OK -更新了我的代码以遵循示例。我尝试将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));
}
}

谁能告诉我这样看起来是否合适?或者我完全失去了剧情!

看,

<h:dataTable var="row"  border="0" value="#{beanCategory.collection}" binding="#{beanCategory.datatable}">

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;
    }
}

你在getter方法中加载列表。这是个很糟糕的主意。getter应该仅仅是bean属性的访问点,而不是做一些业务工作。在bean的生命周期中,getter可以被调用多次。每次调用都会访问DB,并且JSF在表单提交期间更新的本地collection属性将在稍后的时间点再次被覆盖。这没有意义。

在(post)构造函数方法或action(listener)方法中完成业务工作。肯定不是在getter中。下面是一个带有一些代码改进的最小启动示例:

<h:dataTable value="#{bean.categories}" var="category">
    <h:column>
        <h:inputText value="#{category.description}" />
    </h:column>
    <h:column>
        <h:outputText value="#{category.id}" />
    </h:column>
    <h:column>
        <h:commandButton value="Delete" action="#{bean.delete(category)}" />
        <h:commandButton value="Save" action="#{bean.update(category)}" />
    </h:column>
</h:dataTable>
<h:inputText value="#{bean.newCategory.description}" />
<h:commandButton value="Add" action="#{bean.add}" />

(注意EL 2.2 (Servlet 3.0的一部分)就支持在EL中传递参数,Glassfish 3是一个Servlet 3.0容器,所以当web.xml正确声明符合Servlet 3.0规范时,它肯定会支持它)

@ManagedBean
@ViewScoped // Definitely don't use session scoped. I'm not sure about CDI approach, so here's JSF example.
public class Bean {
    private List<Category> categories;
    private Category newCategory;
    @EJB
    private CategoryService categoryService;
    @PostConstruct
    public void init() {
        categories = categoryService.list();
        newCategory = new Category();
    }
    public void add() {
        categoryService.add(newCategory);
        init();
    }
    public void delete(Category category) {
        categoryService.delete(category);
        init();
    }
    public void update(Category category) {
        categoryService.update(category);
        init();
    }
    public List<Category> getCategories() {
        return categories;
    }
    public Category getNewCategory() {
        return newCategory;
    }
}

应该是这样。参见:

  • 为什么JSF多次调用getter
  • 帮助理解JSF's对托管bean的多个调用
  • : getXxx()被调用了这么多次,为什么?

我看你忘了<h:form>

相关内容

  • 没有找到相关文章

最新更新