使用Hibernate建立树形结构
递归查询子节点,会发出N多次select查询
可以在Node中定义一个字段,额外记录其与parent的id间的关系,如1|3|6|12
然后使用like进行模糊查询,只需要查询1次即可找出所有的child。
虽然模糊查询慢,但只发出1条语句,所以效率可能比发出N多次递归查询快!
实体类
package org.leadfar.hibernate.model;
import java.util.Set;
public class Node {
private int id;
private String name;
private Node parent;
private Set<Node> children;//一的一端使用集合存储对方引用
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Node getParent() {
return parent;
}
public void setParent(Node parent) {
this.parent = parent;
}
public Set<Node> getChildren() {
return children;
}
public void setChildren(Set<Node> children) {
this.children = children;
}
}
映射文件
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <class name="org.leadfar.hibernate.model.Node" table="t_node" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <many-to-one name="parent" column="pid"> </many-to-one> <set name="children" lazy="extra" inverse="true"> <key column="pid"></key> <one-to-many class="org.leadfar.hibernate.model.Node"></one-to-many> </set> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import java.io.File;
import java.util.Iterator;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Test_tree extends TestCase {
/**
* 建立一个文件目录树。可以根据某个节点查找其父节点,也可以查找其子节点
* 查找父节点--many-to-one
* 查找子节点--one-to-many
*
* 关联关系---parent字段,可以看做是外键
* 从多的一端即孩子端建立关联关系
*/
public void tree_save() {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
Session session = sfactory.openSession();
try {
session.beginTransaction();
save(session,new File("F:\\oracle"),null);
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
}
public void tree_findParent() {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
Session session = sfactory.openSession();
try {
session.beginTransaction();
Node node = (Node)session.load(Node.class, 2034);
find_parent(node);
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
}
public void tree_findChild() {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
Session session = sfactory.openSession();
try {
session.beginTransaction();
Node node = (Node)session.load(Node.class, 22);
find_child(node,0);
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
}
//保存一个文件目录树到数据库---parent记录父子关系
private void save(Session session,File file,Node parent) {
Node node = new Node();
node.setName(file.getName());
node.setParent(parent);
session.save(node);
if(file.exists()) {
File[] f = file.listFiles();
if(f!=null && f.length>0) {
for(File sub : f) {
if(sub.isDirectory())
save(session,sub,node);
}
}
}
}
//查找给定节点的父节点
private void find_parent(Node node) {
System.out.print(node.getName());
Node parent = node.getParent();
if(parent!=null) {
System.out.print("-->");
find_parent(parent);
}
}
//给定节点查找其子节点
private void find_child(Node node,int level) {
for(int i=0;i<level;i++) {
System.out.print("\t");
}
System.out.println(node.getName());
Set<Node> childs = node.getChildren();
if(childs.size()!=0) {
for(Node n : childs){
find_child(n,level+1);
}
}
}
}