【发布时间】:2015-03-04 10:00:17
【问题描述】:
该场景基于完整的 Java EE 7 (Wildfly 8),并使用 EJB 3.2、JPA 2.1、JSF 2.2(Mojarra、Primefaces 库)和以下项目结构:
- 网络项目
- EAR 项目
- EJB 项目
- JPA 项目
基本的 CRUD 场景如下所示:
- 用户进入页面或点击新建,输入项目名称并点击保存>项目保存在数据库中并添加到表中
- 用户从表中选择项目 > 项目名称字段已更新为当前所选项目中的适当值
- 用户从表中选择项目,修改它并点击保存 > 修改的项目在数据库和表中更新
- 用户从表中选择项目并单击删除 > 从数据库和表中删除项目
item-overview.xhtml
<h:form id="itemPanel">
<p:panelGrid id="itemPanelGrid" columns="2">
<f:facet name="header">Item</f:facet>
<h:outputLabel for="itemName" value="Item name: " />
<p:inputText id="itemName" value="#{itemController.item.itemName}"></p:inputText>
<f:facet name="footer">
<p:commandButton id="newItem" value="New" update="itemPanelGrid"
process="@this" actionListener="#{itemController.newItem}">
<p:resetInput target="itemPanelGrid" />
</p:commandButton>
<p:commandButton id="deleteItem" value="Delete"
update="itemsPanel @form"
actionListener="#{itemController.deleteItem}" />
<p:commandButton id="saveItem" value="Save"
update="itemsPanel @form" action="#{itemController.saveItem}" />
</f:facet>
</p:panelGrid>
<p:panel id="itemsPanel">
<p:dataTable id="itemTable" var="tableItem" selectionMode="single"
selection="#{itemController.selectedItem}" rowKey="#{tableItem.id}"
emptyMessage="No items available" value="#{itemController.items}">
<p:ajax event="rowSelect" listener="#{itemController.onRowSelect}"
update="@this @form" />
<p:column headerText="Id">
<h:outputText value="#{tableItem.id}" />
</p:column>
<p:column headerText="Item name">
<h:outputText value="#{tableItem.itemName}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
ItemController.java
public class ItemController implements Serializable {
@EJB
private ItemServiceBean itemServiceBean;
private Item item;
private Item selectedItem;
private List<Item> items;
@PostConstruct
public void init() {
item = new Item();
items = itemServiceBean.getAllItems();
}
public void deleteItem() {
if (items.contains(item))
items.remove(item);
itemServiceBean.deleteItem(item);
}
public String saveItem() {
if (!items.contains(item))
items.add(item);
itemServiceBean.saveItem(item);
return null;
}
public void newItem() {
item = new Item();
}
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public Item getSelectedItem() {
return selectedItem;
}
public void setSelectedItem(Item selectedItem) {
this.selectedItem = selectedItem;
}
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("Item selected", ((Item) event.getObject()).getId() + "");
FacesContext.getCurrentInstance().addMessage(null, msg);
this.item = this.selectedItem;
}
}
ItemServiceBean.java
public class ItemServiceBean {
@PersistenceContext
private EntityManager entityManager;
public ItemServiceBean() { }
public void saveItem(Item item) {
entityManager.persist(item);
}
public void deleteItem(Item item) {
Item managedItem = getItem(item);
entityManager.remove(managedItem);
}
public Item updateItem(Item item) {
Item managedItem = getItem(item);
return entityManager.merge(managedItem);
}
public List<Item> getAllItems() {
TypedQuery<Item> query = entityManager.createQuery("SELECT i FROM Item i", Item.class);
return query.getResultList();
}
public Item getItem(Item item) {
return entityManager.find(Item.class, item.getId());
}
}
支持 bean 是 @ViewScoped。后面的 EJB 是无状态的,我想它是一个容器管理的 bean(因为它是默认设置)。
如果您尝试使用EntityManagers remove 方法删除一个项目并简单地传递当前选定的项目,则该对象将被分离。所以,我所做的是从数据库中检索项目,将其放入持久性上下文中并删除它。我原以为它会有所不同,而无需从数据库中检索对象,再次将其放入上下文并删除它。是否有可能避免这些额外步骤?
我曾多次尝试更新现有项目。如果您询问持久性上下文是否已使用 EntityManagers contains 方法管理修改的项目,结果表明该项目不在持久性上下文中。因此,我需要再次从数据库中检索对象,然后使用merge 对其进行更新。我真的怀疑这是首选方式,如果有人对此有任何提示,我会很高兴。
我假设整个事务保持“打开”并且对象保持/s 附加到持久性上下文。
谢谢。
【问题讨论】: