一:数据表设计(分类表)
说明:各个分类之间的关系相当于树型结构。每个类别叫做节点,最上面的类别叫做根节点,根节点没有父节点,有若干个孩子节点。
最下面的类别叫做叶子节点,叶子节点有一个或者没有父节点,没有孩子节点。每个节点有一个或者没有父节点,每个节点有一个或者没有孩子节点
Id | Name | Show_order | Level | Parent_id | Id_leaf |
主键ID | 节点名称 | 同类节点排序 | 节点级别 | 父节点ID | 是否叶子节点 |
|
| 当显示同类节点的时候,可以以Show_order进行倒序或者正序进行显示 | 根节点的level为1,根节点的孩子节点为2,跟孩子节点同一级别的节点也为2 | 如果没有父节点,则为空 | 如果是叶子节点,则为TRUE,否则为FALSE |
二:添加分类说明
说明:添加分类时需要用户填写的字段有:类别名称(Name)、所属类别(Parent_id)、类别排序(Show_order)。
提交的时候:
· 如果所属大类选择了“==为父节点==“时,则添加的节点为根节点,即Parent_id为null;如果选择了某一节点,则添加的节点为所选节点的子节点,Parent_id为所选节点的ID。
· 新添加的节点都是叶子节点(Id_leaf为True)。只有当要在节点下面添加孩子节点的时候,才把它改为非叶子节点。
· 根节点的level为1。新添加节点的level为所选节点的level加1。
三:添加分类代码
以下是三个控件和提交按钮绑定的代码:
<h:inputText id="name" required="true" value="#{helpCatHome.instance.name}" />
<h:selectOneMenu value="#{helpCatHome.instance.parent}" id="parentId" required="false">
<s:selectItems value="#{helpCatList.helpCats}" var="_helpCats"
label="#{_helpCats.wrapName.replace(' ',' ')}"
rendered="#{not empty helpCatList.helpCats}"
noSelectionLabel="==为父节点==" />
<s:convertEntity />
</h:selectOneMenu>
<h:inputText id="showOrder" required="true" value="#{helpCatHome.instance.showOrder}" />
<h:commandButton id="save"
value="提交" action="#{helpCatHome.persist}"
rendered="#{!helpCatHome.managed}" />
说明:在s:selectItems组件中,value绑定的是helpCatList组件的helpCats属性
以下是绑定helpcats属性的代码:
@Name("helpCatList")
@Scope(ScopeType.PAGE)
public class HelpCatList extends EntityQuery<HelpCat> {
// 选出第一级分类
private List<HelpCat> helpCats = new LinkedList<HelpCat>();
private static final String EJBQL = "select helpCat from HelpCat helpCat where helpCat.parent=null";
private static final String[] RESTRICTIONS = {};
private HelpCat helpCat = new HelpCat();
public HelpCatList() {
setEjbql(EJBQL);
setRestrictionExpressionStrings(Arrays.asList(RESTRICTIONS));
setOrder("show_order desc and id desc");
}
/**
* 得到按层次划分的分类列表
*
*/
public List<HelpCat> getHelpCats() {
if (helpCats.isEmpty()) {
List<HelpCat> cats = getResultList();
helpCats.addAll(cats); //得到所有父节点,并把父节点都添加到helpcats属性中
Iterator<HelpCat> ir = cats.iterator();
while (ir.hasNext()) {
HelpCat c = ir.next();
iteratorGoodsCats(c);
}
}
return helpCats;
}
// 递归遍历分类把所有孩子节点都添加到属性helpCats中
private void iteratorGoodsCats(HelpCat cat) {
if (cat == null)
return;
int pos = helpCats.indexOf(cat);// 当前位置
Set<HelpCat> childCats = cat.getChildren();
if (!childCats.isEmpty()) {
for (HelpCat c : childCats) {
info("child iterator start,parent id=" + cat.getId()
+ ",child id=" + c.getId());
helpCats.add(pos + 1, c);
pos++;
}
for (HelpCat c : childCats) {
iteratorGoodsCats(c);
}
}
}
public void setHelpCats(List<HelpCat> cats) {
this.helpCats = cats;
}
}
以下是helpCatHome类的代码:
@Name("helpCatHome")
public class HelpCatHome extends EntityHome<HelpCat> {
@RequestParameter
Long helpCatId; //如果传递过来helpCatId,则通过instance就可以实例化以helpCatId为主键的helpCat实例
@Override
public Object getId() {
if (helpCatId == null) {
return super.getId();
} else {
return helpCatId;
}
}
@Override
@Begin
public void create() {
super.create();
}
@Override
public String persist() {
initLevel();
return super.persist(); //调用超类的函数,把当前home类所维护的helpCat实例添加到数据库
}
@Override
public String update() {
initLevel();
return super.update();
}
private void initLevel() {
HelpCat parent = getInstance().getParent(); // 得到当前实例(节点)的父节点
if (parent != null) {
int level = parent.getLevel() + 1;
getInstance().setLevel(level); // 如果父节点不为空,则此节点的level为父节点的level+1
if (parent.getIsLeaf()) {
parent.setIsLeaf(false); // 如果父节点是叶子节点,则把其改为非叶子节点
}
} else {
getInstance().setLevel(1); // 如果父节点为空,则当前节点为根节点,level为1
}
getInstance().setIsLeaf(true); // 把当前节点设置为叶子节点
}
}
说明:
helpCatHome是对helpCat组件中的实例进行操作的组件。
通过instance,如果传递过来helpCatId参数,就实例化以helpCatId为主键ID的helpCat实例,并通过#{helpCatHome.instance.name},#{helpCatHome.instance.parent},#{helpCatHome.instance.showOrder}绑定了helpCat实例的三个属性到页面的组件中。
这时可以通过修改页面组件中的内容,然后调用helpCatHome组件的update()函数更新到数据库中
如果没有传递过来参数,则通过instance来新建一个helpCat实例,#{helpCatHome.instance.name},#{helpCatHome.instance.parent},#{helpCatHome.instance.showOrder}绑定的值将作为这个实例的三个属性,然后可以调用helpCatHome组件的persist()函数,将这个实例添加到数据库中。