现在的位置: 首页 > 综合 > 正文

用Hibernate解决Parent/Child问题

2013年01月03日 ⁄ 综合 ⁄ 共 4703字 ⁄ 字号 评论关闭
文章目录

用Hibernate解决Parent/Child问题

前 两周做电子商务的实习项目的时候遇到一个很棘手的问题:首页要做一个商品目录,每个商品大类下面还分几个小类。大类和小类之间的关系也就是 Parent/Child 的关系。当时也是初学 Struts ,被这个问题搅了两天也没搞定,最后用了个特别笨的方法给凑合过去了:jsp页面里调用一个 JavaBean ,这个 JavaBean 在初始化的时候从数据库中读出所有大类,并把这些大类放到一个 ArrayList 中,在jsp中用 logic:iterator 输出所有大类,logic:iterator内部先调用另一个 JavaBean 得到该大类下所有小类,然后嵌套了另一个 logic:iterator 输出小类。我不准备把代码贴出来了,实在是因为代码写的太烂了。

看了几天Hibernate的书,今天就拿这个问题开刀,算是巩固一下这几天的学习成果吧。OK,我们开始!

先建数据库和数据表:表结构如下:

id int PK (编号)
name varchar(20) (类别名)
parentid int (父类的编号)

再在eclipse中新建一个名为 pc 的 web 项目(偶用的是myeclipse做 web 项目)。下面是 Hibernate 的配置方法和 Struts、JSP的代码

Hibernate配置文件:hibernate.cfg.xml

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>

<session-factory>
<property name="connection.username">study</property>
<property name="connection.url">jdbc:sqlserver://localhost:1433</property>
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<property name="myeclipse.connection.profile">news</property>
<property name="connection.password">study</property>
<property name="connection.driver_class">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="show_sql">true</property>
<mapping resource="name/yinqiang/pc/hibernate/Pc.hbm.xml" />

</session-factory>

</hibernate-configuration>

Hibernate映射文件:Pc.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
<hibernate-mapping>
<class name="name.yinqiang.pc.hibernate.Pc" table="pc" schema="dbo" catalog="news">
<id name="id" type="integer">
<column name="id" />
<generator class="native"></generator>
</id>
<property name="name" type="string">
<column name="name" length="50" not-null="true" />
</property>
<property name="parentid" type="integer">
<column name="parentid" not-null="true" />
</property>
<set
inverse="true"
lazy="true"
name="child">
<key column="parentid" />
<one-to-many class="name.yinqiang.pc.hibernate.Pc" />
</set>

</class>
</hibernate-mapping>

这里面的红字部分是配置文件的核心内容,它定义了parentid和id之间的关系

Hibernate持久化类:Pc.java

package name.yinqiang.pc.hibernate;
import java.util.HashSet;
import java.util.Set;
public class Pc implements java.io.Serializable {
private static final long serialVersionUID = 2764441994073705343L;
private Integer id;
private String name;
private Integer parentid;
private Set child = new HashSet(0);

// Constructors
/** default constructor */
public Pc() {
}
/** minimal constructor */
public Pc(String name, Integer parentid) {
this.name = name;
this.parentid = parentid;
}

/** full constructor */
public Pc(String name, Integer parentid, Set child) {
this.name = name;
this.parentid = parentid;
this.child = child;
}
// Property accessors
public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}
public Integer getParentid() {
return this.parentid;
}

public void setParentid(Integer parentid) {
this.parentid = parentid;
}
public Set getChild() {
return this.child;
}

public void setChild(Set child) {
this.child = child;
}

}

Hibernate的部分基本都配置完成了,下面新建一个Struts的Action:

Struts配置文件:struts-config.xml(action-mappings部分)

<action-mappings >
<action
input="/index.jsp"
path="/showtree"
type="name.yinqiang.pc.action.ShowtreeAction"
validate="false">
<forward name="success" path="/showtree.jsp" />
</action>
</action-mappings>

ShowtreeAction.java(execute方法的代码)

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {
Session session = HibernateSessionFactory.currentSession();
Transaction tx = session.beginTransaction();
List list = session.createQuery("from Pc pc where pc.parentid=0").list();
tx.commit();

Iterator it = list.iterator();
while(it.hasNext()){
Pc pc = (Pc)it.next();
pc.getChild().iterator();
}

HibernateSessionFactory.closeSession();

request.setAttribute("list",list);

return mapping.findForward("success");
}

红字的部分如果不写话在打开jsp页面的时候就会出错,至于为什么要这样写、是不是应该这样写我也不太清楚(刚开始学Hibernate,还很菜,好多问题都还没弄明白)

OK,最后一步,用于显示数据的JSP文件:showtree.jsp

<logic:present name="list" scope="request">
<c:forEach items="${list}" var="element">
<p>大类:<html:link page="/classinfo.do?id=${element.id}">${element.name}</html:link><br />
<c:forEach items="${element.child}" var="child">
小类:<html:link page="/classinfo.do?id=${child.id}">${child.name}</html:link>&nbsp;&nbsp;
</c:forEach>
</p>
</c:forEach>
</logic:present>

这里用的是JSTL标签循环遍历集合。内层的循环输出一个父类下的所有子类,外层循环输出所有的父类。

完工了,deploy一下这个项目,打开浏览器,输入地址:http://localhost:8080/pc/showtree.do 可不要直接输入jsp文件的地址哦!

10b10f0772b.jpg

HaHa,成功了!!

注:写的比较多也比较乱,其实核心内容就在于Hibernate映射文件的配置和Struts Action部分的代码。如果有朋友不明白的话欢迎和我交流。

评论

这里可以使用session in view 的解决方案, 但效率和你现在的用法基本一样, 不过代码不会这么罗嗦, 也不会报session is closed的异常, 执行的SQL语句将是 1 + 所有的子节点数.

最好的做法应该是“迫切左外连接”查询了, 呵

抱歉!评论已关闭.