在系統設計中,常常用到遞歸性質的樹形結果,好比菜單、多級分類等,通常是在同一個表中定義父子關係實現這種結構。java
下面是在Hibernate中,基於Annotation的簡單樹形結構的實現:node
第一步:建立Entity類,並添加註解實現關聯關係mysql
ps: 主要是利用@ManyToOne 和 @OneToMany 配置在同一個Entity類中實現樹形遞歸的結構。hibernate註解形式比在xml配置更加簡潔sql
TreeNode.javasession
1 package com.hfut.hibernate; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 import javax.persistence.CascadeType; 7 import javax.persistence.Entity; 8 import javax.persistence.FetchType; 9 import javax.persistence.GeneratedValue; 10 import javax.persistence.Id; 11 import javax.persistence.JoinColumn; 12 import javax.persistence.ManyToOne; 13 import javax.persistence.OneToMany; 14 15 @Entity 16 public class Node { 17 private int id; 18 private String name; 19 private Node parent; 20 private Set<Node> children = new HashSet<Node>(); 21 22 @Id 23 @GeneratedValue 24 public int getId() { 25 return id; 26 } 27 public void setId(int id) { 28 this.id = id; 29 } 30 public String getName() { 31 return name; 32 } 33 public void setName(String name) { 34 this.name = name; 35 } 36 @ManyToOne(cascade=CascadeType.ALL) 37 @JoinColumn(name="nodeId") 38 public Node getParent() { 39 return parent; 40 } 41 public void setParent(Node parent) { 42 this.parent = parent; 43 } 44 @OneToMany(mappedBy="parent", cascade=CascadeType.ALL,fetch=FetchType.EAGER) 45 public Set<Node> getChildren() { 46 return children; 47 } 48 public void setChildren(Set<Node> children) { 49 this.children = children; 50 } 51 }
第二步:建立hibernate默認配置文件:oracle
hibernate.cfg.xmlapp
1 <?xml version='1.0' encoding='utf-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 6 <hibernate-configuration> 7 8 <session-factory> 9 10 11 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 12 <property name="connection.url">jdbc:mysql://localhost/testone</property> 13 <property name="connection.username">root</property> 14 <property name="connection.password">123456</property> 15 <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 16 <!-- 17 <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> 18 <property name="connection.url">jdbc:oracle:thin:@localhost:1521:SXT</property> 19 <property name="connection.username">scott</property> 20 <property name="connection.password">tiger</property> 21 <property name="dialect">org.hibernate.dialect.OracleDialect</property> 22 --> 23 24 <!-- JDBC connection pool (use the built-in) --> 25 <property name="connection.pool_size">1</property> 26 27 28 29 <!-- Enable Hibernate's automatic session context management --> 30 <property name="current_session_context_class">thread</property> 31 32 <!-- Disable the second-level cache --> 33 <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 34 35 <!-- Echo all executed SQL to stdout --> 36 <property name="show_sql">true</property> 37 <property name="format_sql">true</property> 38 39 <!-- Drop and re-create the database schema on startup 40 <property name="hbm2ddl.auto">update</property> 41 --> 42 <mapping class="com.hfut.hibernate.Node"/> 43 44 </session-factory> 45 46 </hibernate-configuration>
第三步:建立測試文件:ide
TreeNodeTest.java測試
1 package com.hfut.hibernate; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.AnnotationConfiguration; 6 import org.hibernate.tool.hbm2ddl.SchemaExport; 7 import org.junit.AfterClass; 8 import org.junit.BeforeClass; 9 import org.junit.Test; 10 11 import com.hfut.hibernate.TreeNode; 12 13 public class TreeNodeTest { 14 15 private static SessionFactory sessionFactory; 16 17 @BeforeClass 18 public static void beforeClass() { 19 new SchemaExport(new AnnotationConfiguration().configure()).create(false, true); 20 sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); 21 } 22 23 @AfterClass 24 public static void afterClass() { 25 sessionFactory.close(); 26 } 27 28 public void testSave() { 29 Session session = sessionFactory.openSession(); 30 TreeNode node0 = new TreeNode(); 31 node0.setName("父親"); 32 TreeNode node1 = new TreeNode(); 33 node1.setName("大兒子"); 34 TreeNode node2 = new TreeNode(); 35 node2.setName("小兒子"); 36 TreeNode node3 = new TreeNode(); 37 node3.setName("大兒子的大兒子"); 38 TreeNode node4 = new TreeNode(); 39 node4.setName("大兒子的小兒子"); 40 TreeNode node5 = new TreeNode(); 41 node5.setName("小兒子的大兒子"); 42 TreeNode node6 = new TreeNode(); 43 node6.setName("小兒子的小兒子"); 44 45 node0.getChildren().add(node1); 46 node0.getChildren().add(node2); 47 node1.getChildren().add(node3); 48 node1.getChildren().add(node4); 49 node1.setParent(node0); 50 node2.getChildren().add(node5); 51 node2.getChildren().add(node6); 52 node2.setParent(node0); 53 node3.setParent(node1); 54 node4.setParent(node1); 55 node5.setParent(node2); 56 node6.setParent(node2); 57 58 session.beginTransaction(); 59 session.save(node0); 60 session.getTransaction().commit(); 61 session.close(); 62 } 63 @Test 64 public void testLoad() { 65 testSave(); 66 Session session = sessionFactory.openSession(); 67 session.beginTransaction(); 68 TreeNode node = (TreeNode)session.load(TreeNode.class, 1); 69 print(node,0); 70 session.getTransaction().commit(); 71 session.close(); 72 } 73 74 private void print(TreeNode node,int level) { 75 String preStr = ""; 76 for(int i=0;i<level;i++){ 77 preStr +="----"; 78 } 79 System.out.println(preStr+node.getName()); 80 for(TreeNode children:node.getChildren()){ 81 print(children,level+1); 82 } 83 } 84 }
[四]、測試結果fetch
測試結果以下:
父親----小兒子--------小兒子的大兒子--------小兒子的小兒子----大兒子--------大兒子的小兒子--------大兒子的大兒子