tapestry5做一个更新页面使用了选择分类的select组件,分类不变的情况下提交报错

bianweiall 发布于 2012/07/27 17:57
阅读 1K+
收藏 0

我修改页面的时候,如果我换一个分类,提交没问题,数据库里都更新了,按照原来默认的分类不变提交直接就报错了,数据库里其他字段都更新了,就是两表关联的外键为空了,不是很理解


页面类 

ArticleUpdate.java

package com.bw.pages.article;

import java.util.Date;
import java.util.List;

import org.apache.tapestry5.SelectModel;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.PageActivationContext;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.corelib.components.Errors;
import org.apache.tapestry5.corelib.components.Select;
import org.apache.tapestry5.corelib.components.TextArea;
import org.apache.tapestry5.corelib.components.TextField;
import org.apache.tapestry5.ioc.annotations.Inject;

import com.bw.entities.Article;
import com.bw.entities.Category;
import com.bw.services.dao.jpa.AppJpaDAO;
import com.bw.util.CategoryEncoder;
import com.bw.util.CategorySelectModel;

public class ArticleUpdate {
	@Property
	private Article article;
	
	@Property
	private Category category;
	
	@Property
	private List<Category> categorys;

	@PageActivationContext
	private int id;

	@Inject
	private AppJpaDAO dao;

	@SuppressWarnings("unused")
	@Component
	private Errors errors;

	@SuppressWarnings("unused")
	@Component(parameters = { "value=article.title" })
	private TextField articleTitle;

	@SuppressWarnings("unused")
	@Component(parameters = { "value=article.content" })
	private TextArea articleContent;
	
	@SuppressWarnings("unused")
	@Component(parameters = { "value=category", "encoder=categoryEncoder",
			"model=categoryModel","blankLabel=${article.category.getTitle()}"})
	private Select categorySelect;

	public SelectModel getCategoryModel() {
		return new CategorySelectModel(categorys);
	}

	@SuppressWarnings("rawtypes")
	public ValueEncoder getCategoryEncoder() {
		return new CategoryEncoder(dao);
	}

	void onPrepare(){
		if (article == null) {
			article = dao.findByID(Article.class, id);
		}
		categorys = dao.findWithJpql("select o from _category o order by o.level asc");
	}
	
	Object onSuccess() {
		String s = new java.text.SimpleDateFormat("yyyy-MM-dd hh🇲🇲ss")
				.format(new Date());
		article.setCreatedtime(s);
		article.setCategory(category);
		dao.update(article);
		return ArticleList.class;
	}

}

页面模版

ArticleUpdate.tml

<html t:type="layout" title="编辑BLOG"
	xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter">
	<t:form>
		<p t:id="errors" />
		<p>
			分类:
			<select t:id="categorySelect"></select>
		</p>
		<p>
			标题:
			<input type="text" t:id="articleTitle" />
		</p>
		<p>
			内容:
			<input type="text" t:id="articleContent" />
		</p>
		<p>
			<input type="submit" value="保存" />
		</p>
	</t:form>
</html>

错误提示:

[ERROR] article.ArticleList Render queue error in Expansion[PropBinding[expansion article/List(article.category.getId())]]: Property 'category' (within property expression 'article.category.getId()', of com.bw.pages.article.ArticleList@547f5496) is null.
org.apache.tapestry5.ioc.internal.util.TapestryException: Property 'category' (within property expression 'article.category.getId()', of com.bw.pages.article.ArticleList@547f5496) is null. [at classpath:com/bw/pages/article/ArticleList.tml, line 58]
	at org.apache.tapestry5.internal.bindings.PropBinding.get(PropBinding.java:63)
	at org.apache.tapestry5.internal.structure.ExpansionPageElement.render(ExpansionPageElement.java:45)
	at org.apache.tapestry5.internal.services.RenderQueueImpl.run(RenderQueueImpl.java:72)
	at org.apache.tapestry5.internal.services.PageRenderQueueImpl.render(PageRenderQueueImpl.java:124)
	at $PageRenderQueue_14e66a5d5794.render(Unknown Source)
	at $PageRenderQueue_14e66a5d5793.render(Unknown Source)
	at org.apache.tapestry5.internal.services.MarkupRendererTerminator.renderMarkup(MarkupRendererTerminator.java:37)
	at org.apache.tapestry5.services.TapestryModule$30.renderMarkup(TapestryModule.java:1980)
	at $MarkupRenderer_14e66a5d5797.renderMarkup(Unknown Source)

JAP关系映射相关

Article.java

package com.bw.entities;  
  
import javax.persistence.CascadeType;  
import javax.persistence.Column;  
import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.GenerationType;  
import javax.persistence.Id;  
import javax.persistence.JoinColumn;  
import javax.persistence.ManyToOne;  
import javax.persistence.SequenceGenerator;  
  
@Entity(name = "_article")  
@SequenceGenerator(name = "article_id_seq", sequenceName = "article_id_seq")  
public class Article {  
  
    @Id  
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "article_id_seq")  
    private int id;  
    private String title;  
  
    @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.REFRESH })  
    @JoinColumn(name = "categoryid")  
    private Category category;  
  
    // @Lob 不知道为什么用这个就乱码!  
    @Column(length = 8000)  
    private String content;  
    private String createdtime;  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getTitle() {  
        return title;  
    }  
  
    public void setTitle(String title) {  
        this.title = title;  
    }  
  
    public String getContent() {  
        return content;  
    }  
  
    public void setContent(String content) {  
        this.content = content;  
    }  
  
    public String getCreatedtime() {  
        return createdtime;  
    }  
  
    public void setCreatedtime(String createdtime) {  
        this.createdtime = createdtime;  
    }  
  
    public Category getCategory() {  
        return category;  
    }  
  
    public void setCategory(Category category) {  
        this.category = category;  
    }  
  
}

Category.java

package com.bw.entities;  
  
import java.util.HashSet;  
import java.util.Set;  
  
import javax.persistence.CascadeType;  
import javax.persistence.Entity;  
import javax.persistence.FetchType;  
import javax.persistence.GeneratedValue;  
import javax.persistence.GenerationType;  
import javax.persistence.Id;  
import javax.persistence.OneToMany;  
import javax.persistence.SequenceGenerator;  
  
@Entity(name = "_category")  
@SequenceGenerator(name = "seq_id_category", sequenceName = "seq_id_category")  
public class Category {  
  
    @Id  
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_id_category")  
    private int id;  
    private String title;  
    private int level;  
      
    @OneToMany(mappedBy="category",cascade=CascadeType.ALL,fetch=FetchType.LAZY)  
    private Set<Article> articles = new HashSet<Article>();  
  
    public int getId() {  
        return id;  
    }  
  
    public void setId(int id) {  
        this.id = id;  
    }  
  
    public String getTitle() {  
        return title;  
    }  
  
    public void setTitle(String title) {  
        this.title = title;  
    }  
  
    public int getLevel() {  
        return level;  
    }  
  
    public void setLevel(int level) {  
        this.level = level;  
    }  
  
    public Set<Article> getArticles() {  
        return articles;  
    }  
  
    public void setArticles(Set<Article> articles) {  
        this.articles = articles;  
    }  
  
}


自定义select组件相关

CategoryOptionModel.java

package com.bw.util;  
  
import java.util.Map;  
  
import org.apache.tapestry5.OptionModel;  
  
import com.bw.entities.Category;  
  
public class CategoryOptionModel implements OptionModel {  
  
    private Category category;  
  
    public CategoryOptionModel(Category category) {  
        this.category = category;  
    }  
  
    public String getLabel() {  
        return category.getTitle();  
    }  
  
    public boolean isDisabled() {  
        // TODO Auto-generated method stub  
        return false;  
    }  
  
    public Map<String, String> getAttributes() {  
        // TODO Auto-generated method stub  
        return null;  
    }  
  
    public Object getValue() {  
        return category;  
    }  
  
}

CategorySelectModel.java

package com.bw.util;  
  
import java.util.ArrayList;  
import java.util.List;  
  
import org.apache.tapestry5.OptionGroupModel;  
import org.apache.tapestry5.OptionModel;  
import org.apache.tapestry5.util.AbstractSelectModel;  
  
import com.bw.entities.Category;  
  
public class CategorySelectModel extends AbstractSelectModel {  
  
    private List<Category> categorys;  
  
    public CategorySelectModel(List<Category> categorys) {  
        this.categorys = categorys;  
    }  
  
    public List<OptionGroupModel> getOptionGroups() {  
        // TODO Auto-generated method stub  
        return null;  
    }  
  
    public List<OptionModel> getOptions() {  
        List<OptionModel> list = new ArrayList<OptionModel>();  
        for (Category c : categorys) {  
            list.add(new CategoryOptionModel(c));  
        }  
        return list;  
    }  
  
}

CategoryEncoder.java

package com.bw.util;  
  
import org.apache.tapestry5.ValueEncoder;  
  
import com.bw.entities.Category;  
import com.bw.services.dao.jpa.AppJpaDAO;  
  
@SuppressWarnings("rawtypes")  
public class CategoryEncoder implements ValueEncoder {  
  
    private AppJpaDAO source;  
  
    public CategoryEncoder(AppJpaDAO source) {  
        this.source = source;  
    }  
  
    public String toClient(Object obj) {  
        return "" + ((Category) obj).getId();  
    }  
  
    public Object toValue(String str) {  
        return source.findByID(Category.class, Integer.parseInt(str));  
    }  
  
}


加载中
返回顶部
顶部