2011-08-28 191 views
0

我正在使用Eclipse和Glassfish 3.0。雖然以前我做過類似的事情,但對於這項技術來說還很陌生很簡單,真的有一個綁定到後臺bean的數據表。添加方法並刪除我已經介紹的方法 - 問題出在我調用的更新方法。我似乎無法看到在組件(HtmlInputText)中找到的更改,並不介意將數據傳回表中。更新在h:dataTable中更新後未反映在JPA實體中

我爲數據表的代碼如下(和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)); 
} 

} 

任何人都可以提出,如果這看起來有點好嗎?或者我完全失去了它的陰謀!

+0

其實只是強調,在更新方法 - 即使我的System.out.println(category.getDescription())我得到表中的舊值 - 而不是ui值。即使當我試圖獲取component.getValue()時,它也會返回舊值! –

+1

而不是從樹中獲取輸入組件,爲什麼不將它綁定到您的支持bean的屬性? –

+0

Arjan - 這是我問題所在的地方......我想我正在數據表中這樣做。但是,當我system.out.println getDescription值時,它始終具有舊值(而不是字段中已更改的值)。也許我沒有正確實施它...

回答

0

正如我所看到的,您已經忘記了<h:form>。這對保存輸入非常必要。

+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方法裏面的列表。這是一個非常糟糕的主意。一個吸氣人員應該只是一個訪問點的bean財產,而不是做一些商業工作。在bean的生命中可以多次調用getter。數據庫將在每次調用時被觸發,並且在表單提交期間由JSF更新的本地collection屬性將在稍後的時間再次被覆蓋。這沒有意義。

在(後)構造函數方法或動作(偵聽器)方法中執行業務工作。絕對不是在吸氣。下面是一些代碼改進最低開球例如:

<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是傳遞參數的支持,因爲EL 2.2的Servlet 3.0的(部分),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; 
    } 

} 

這應該是它。另請參見:

+0

這看起來不錯 - 謝謝。我會進一步研究這一點! –

+1

這確實是一個很好的開球示例。這是我們在幾乎所有豆類中使用的經過驗證的工作方式。 –