更新后的更改未在h:dataTable中更新后反映在JPA实体中

时间:2011-08-28 15:10:06

标签: jsf jpa datatable

我正在使用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的Mapped实体在这里

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

}

任何人都可以建议这种看起来好吗?或者我完全失去了它的情节!

2 个答案:

答案 0 :(得分:5)

看,

<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。数据库将在每次调用时被点击,并且在表单提交期间由JSF更新的本地collection属性将在稍后再次被覆盖。这毫无意义。

在(post)构造函数方法或action(侦听器)方法中执行业务工作。绝对不是一个吸气剂。以下是一些代码改进的最小启动示例:

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

}

那应该是它。另见:

答案 1 :(得分:0)

如我所见,你忘记了<h:form>。这对于保存输入非常必要。