我正在使用jsf spring hibernate和primefaces开展一个项目。我有一个表单,我在其中添加项目。该表单的一个字段不是原始类型,而是自定义对象。我知道我必须使用转换器并获得我选择的对象。我已经尝试了一个没有运气的自定义转换器,因为我无法注入服务并且始终为null。所以我转向omnifaces让我的生活更轻松,继续前进。不幸的是我也遇到了问题。我仔细查看我的代码,但我看不出什么是错的。下面我添加与问题相关的代码: 首先我使用omnifaces的页面:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<h:head><title>Welcome to OTV_JSF_Spring_Hibernate_Project</title></h:head>
<h:body>
<ui:include src="/pages/topMenu.xhtml"/>
<h:form>
<table>
<tr>
<td><h:outputLabel for="itemId" value="id: "/></td>
<td><h:inputText id="itemId" value="#{inventoryItemsMB.itemId}"></h:inputText></td>
</tr>
<tr>
<td><h:outputLabel for="RefItemCategories" value="Category Code"/></td>
<td>
<h:selectOneMenu value="#{inventoryItemsMB.refItemCategories}" id="refItemCategories" immediate="true" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{refItemCategoriesMB.refItemCategoriesList}" var="ref" itemLabel="#{ref.itemCategoryDescription}" itemValue="#{ref}"/>
<!--<f:converter converterId="catConverter"/>-->
</h:selectOneMenu>
</td>
</tr>
<tr>
<td><h:outputLabel for="description" value="Description"/></td>
<td><h:inputText id="description" value="#{inventoryItemsMB.description}" immediate="false"></h:inputText></td>
</tr>
<tr>
<td><h:outputLabel for="AvgMonthlyUsage" value="Average Monthly Usage: "/></td>
<td><h:inputText id="AvgMonthlyUsage" value="#{inventoryItemsMB.avgMonthlyUsage}"></h:inputText></td>
</tr>
<tr>
<td><h:outputLabel for="reorderQuantity" value="Reorder Quantity: "/></td>
<td><h:inputText id="reorderQuantity" value="#{inventoryItemsMB.reorderQuantity}"></h:inputText></td>
</tr>
<tr>
<td><h:outputLabel for="Price" value="Price: "/></td>
<td><h:inputText id="Price" value="#{inventoryItemsMB.price}"></h:inputText></td>
</tr>
<tr>
<td><h:outputLabel for="ItemStockLevels" value="Item stock levels: "/></td>
<td><h:inputText id="ItemStockLevels" value="#{itemStockLevelsMB.quantityInStock}"></h:inputText></td>
</tr>
<tr>
<td><p:commandButton id="addInventoryItems" value="ADD" action="#{inventoryItemsMB.addInventoryItems}" ajax="false" immediate="false"/></td>
</tr>
</table>
</h:form>
</h:body>
其次是我的managedBeans:
@ManagedBean(name="inventoryItemsMB")
@RequestScoped
public class InventoryItemsManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final String SUCCESS = "successInventoryItems";
private static final String ERROR = "error";
@ManagedProperty(value="#{InventoryItemsService}")
IInventoryItemsService inventoryItemsService;
List<InventoryItems> inventoryItemsList;
private int id;
private String avgMonthlyUsage;
String description;
Set<ItemStockLevels> itemStockLevels;
float price;
String reorderQuantity;
RefItemCategories refItemCategories;
byte[] photo;
public String addInventoryItems(){
try{
InventoryItems inventoryItems = new InventoryItems();
//RefItemCategories refItemCategories = new RefItemCategories();
inventoryItems.setAvgMonthlyUsage(getAvgMonthlyUsage());//DONE is it a string?look at impl
inventoryItems.setDescription(getDescription());//DONE
inventoryItems.setItemId(getItemId());//DONE
inventoryItems.setItemStockLevels(getItemStockLevels());//DONE ----- why is it a set?
inventoryItems.setPhoto(getPhoto());
inventoryItems.setPrice(getPrice());//DONE
inventoryItems.setRefItemCategories(getRefItemCategories());//DONE---why refItemCategories
inventoryItems.setReorderQuantity(getReorderQuantity());//DONE-----why string?
//refItemCategories.getItemCategoryCode();
//refItemCategories.getItemCategoryDescription();
getInventoryItemsService().addInventoryItems(refItemCategories, inventoryItems);
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
public List<InventoryItems> getInventoryItemsList() {
inventoryItemsList = new ArrayList<InventoryItems>();
inventoryItemsList.addAll(getInventoryItemsService().getInventoryItems());
return inventoryItemsList;
}
public IInventoryItemsService getInventoryItemsService() {
return inventoryItemsService;
}
public void setInventoryItemsService(IInventoryItemsService inventoryItemsService) {
this.inventoryItemsService = inventoryItemsService;
}
public void setInventoryItemsList(List<InventoryItems> inventoryItemsList) {
this.inventoryItemsList = inventoryItemsList;
}
public int getItemId() {
return id;
}
public void setItemId(int id) {
this.id = id;
}
public void setAvgMonthlyUsage(String avgMonthlyUsage){
this.avgMonthlyUsage = avgMonthlyUsage;
}
public String getAvgMonthlyUsage(){
return avgMonthlyUsage;
}
public void setDescription(String description){
this.description = description;
}
public String getDescription(){
return description;
}
public void setItemStockLevelses(Set<ItemStockLevels> itemStockLevels){
this.itemStockLevels = itemStockLevels;
}
public Set<ItemStockLevels> getItemStockLevels(){
return itemStockLevels;
}
public void setPrice(float price){
this.price = price;
}
public float getPrice(){
return price;
}
public void setReorderQuantity(String reorderQuantity){
this.reorderQuantity = reorderQuantity;
}
public String getReorderQuantity(){
return reorderQuantity;
}
public void setRefItemCategories(RefItemCategories refItemCategories){
this.refItemCategories = refItemCategories;
}
public RefItemCategories getRefItemCategories(){
return refItemCategories;
}
public byte[] getPhoto(){
return photo;
}
public void setPhoto(byte[] photo){
this.photo = photo;
}
}
和其他管理的大豆
@ManagedBean(name="refItemCategoriesMB")
@RequestScoped
public class RefItemCategoriesManagedBean implements Serializable{
private static final long serialVersionUID = 1L;
private static final String SUCCESS = "addCategorySuccess";
private static final String ERROR = "error";
@ManagedProperty(value="#{RefItemCategoriesService}")
IRefItemCategoriesService refItemCategoriesService;
List<RefItemCategories> refItemCategoriesList;
private int id;
private String description;
public String addRefItemCategories(){
try{
RefItemCategories refItemCategories = new RefItemCategories();
refItemCategories.setItemCategoryCode(getItemCategoryCode());
refItemCategories.setItemCategoryDescription(getItemCategoryDescription());
getRefItemCategoriesService().addRefItemCategories(refItemCategories);
return SUCCESS;
} catch (DataAccessException e){
e.printStackTrace();
}
return ERROR;
}
public List<RefItemCategories> getRefItemCategoriesList() {
refItemCategoriesList = new ArrayList<RefItemCategories>();
refItemCategoriesList.addAll(getRefItemCategoriesService().getRefItemCategories());
return refItemCategoriesList;
}
public IRefItemCategoriesService getRefItemCategoriesService() {
return refItemCategoriesService;
}
public void setRefItemCategoriesService(IRefItemCategoriesService refItemCategoriesService) {
this.refItemCategoriesService = refItemCategoriesService;
}
public void setRefItemCategoriesList(List<RefItemCategories> refItemCategoriesList) {
this.refItemCategoriesList = refItemCategoriesList;
}
public String DeleteCategory(RefItemCategories refItemCategoriesList){
getRefItemCategoriesService().deleteRefItemCategories(refItemCategoriesList);
return SUCCESS;
}
public void setItemCategoryCode(int id){
this.id = id;
}
public int getItemCategoryCode(){
return id;
}
public void setItemCategoryDescription(String description){
this.description = description;
}
public String getItemCategoryDescription(){
return description;
}
@Override
public boolean equals(Object object){
if(this.id == ((RefItemCategories) object).getItemCategoryCode()) {
return true;
}else {
return false;
}
}
}
服务我无法注入:
@Transactional(readOnly = true)
@Service("RefItemCategoriesService")
public class RefItemCategoriesService implements IRefItemCategoriesService{
@Autowired
RefItemCategoriesDAOImpl refItemCategoriesDAO;
@Transactional(readOnly = false)
@Override
public void addRefItemCategories(RefItemCategories refItemCategories) {
getRefItemCategoriesDAO().addRefItemCategories(refItemCategories);
}
@Transactional(readOnly = false)
@Override
public void updateRefItemCategories(RefItemCategories refItemCategories) {
getRefItemCategoriesDAO().updateRefItemCategoriesUser(refItemCategories);
}
@Transactional(readOnly = false)
@Override
public void deleteRefItemCategories(RefItemCategories refItemCategories) {
getRefItemCategoriesDAO().deleteRefItemCategories(refItemCategories);
}
@Override
public RefItemCategories getRefItemCategoriesByID(int id) {
return getRefItemCategoriesDAO().getRefItemCategoriesById(id);
}
@Override
public List<RefItemCategories> getRefItemCategories() {
return getRefItemCategoriesDAO().getRefItemCategories();
}
public RefItemCategoriesDAO getRefItemCategoriesDAO(){
return refItemCategoriesDAO;
}
}
这样我得到一个事务错误,其中item_cat_code(db表)不能为null。 谢谢你的时间。
答案 0 :(得分:3)
根据documentation,omnifaces.SelectItemsConverter
依赖于待转换对象的Object#toString()
表示来正确匹配所选项目。您没有显示RefItemCategories
实体的代码,所以它只是猜测,但症状表明您确实没有@Override
您实体上的toString()
,因此依靠default FQN@hashcode
representation。只有在同一视图的回发中,可用项目(<f:selectItems>
的值)完全时,这一切才有效。
但是,提供可用项的RefItemCategoriesManagedBean
辅助bean是请求作用域,并将它们加载到getter中。每当getter被击中时,都会返回一个包含全新实例的全新列表。那些哈希码与已经加载在可用项列表中的哈希码没有相同的哈希码,因此提交的所选项永远不会与任何新加载的项匹配。
因此至少有2个设计问题。
@ViewScoped
。@PostConstruct
。如果您同时解决这两个问题,那么问题就会消失。
或者,只需为您的实体实施toString()
即可。 E.g。
public class RefItemCategories {
@Override
public String toString() {
return "RefItemCategories[" + id + "]";
}
}
顺便说一句,在equals()
支持bean类上看到RefItemCategoriesManagedBean
方法很奇怪。你不是故意把它放在RefItemCategories
实体上吗?无论如何,请仔细阅读SelectItemsConverter
{{1}}如何正确使用它以及如何正确设计您的实体。