搞了好久终于搞明白了,以前做树形数据的时候通过各种麻烦的方法做出树形的数据,那是有多麻烦啊!!一直就没想过通过一对多的关系来解决,今天突然来感原来可以这么简单就解决树形的数据,在这里记录一下.
表结构:
CREATE TABLE `nav` (
`id` int(200) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(200) DEFAULT NULL COMMENT '类别名称',
`namepy` varchar(200) DEFAULT NULL COMMENT '拼音',
`sl` int(200) DEFAULT NULL COMMENT '每个类别下的数量',
`flag` int(10) DEFAULT NULL COMMENT '用来判断它下面是否有list',
`parent_id` int(200) DEFAULT NULL COMMENT '父id',
`order_id` int(10) DEFAULT NULL COMMENT '排序',
`level` int(10) DEFAULT NULL COMMENT '级别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8;
/*Data for the table `nav` */
LOCK TABLES `nav` WRITE;
insert into `nav`(`id`,`name`,`namepy`,`sl`,`flag`,`parent_id`,`order_id`,`level`) values (1,'root','root',8,0,0,0,0),(2,'实验室概况','shiyanshijianjie',5,0,1,2,1),(3,'实验室简介','shiyanshijianjie',0,0,2,1,2),(4,'学术委员会','xueshuweiyuanhui',0,0,2,2,2),(5,'组织结构','zuzhijiegou',0,0,2,3,2),(6,'仪器设备','yiqishebei',0,1,2,4,2),(7,'规章制度','guizhangzhidu',0,1,2,5,2),(8,'新闻资讯','xinwenzhongxin',2,0,1,3,1),(9,'新闻中心 ','xinwenzhongxin',0,1,8,1,2),(10,'通知公告','tongzhitonggao',0,1,8,2,2),(11,'科学研究','yanjiufangxiang',5,0,1,4,1),(12,'研究方向','yanjiufangxiang',0,0,11,1,2),(13,'研究队伍','yanjiuduiwu',0,0,11,2,2),(14,'科研项目','keyanxiangmu',0,1,11,3,2),(15,'科研成果','keyanchengguo',0,1,11,4,2),(16,'技术服务','jishufuwu',0,0,11,5,2),(17,'合作交流','guojihezuo',3,0,1,5,1),(18,'国际合作 ','guojihezuo',0,1,17,1,2),(19,'学术会议','xueshuhuiyi',0,1,17,2,2),(20,'国际合作 ','guojihezuo',0,0,17,3,2),(21,'人才培养','yanjiushengxinxi',4,0,1,6,1),(22,'研究生信息','yanjiushengxinxi',0,1,21,1,2),(23,'校内导师','xiaoneidaoshi',0,0,21,2,2),(24,'校外导师','xiaowaidaoshi',0,0,21,3,2),(25,'产学研基地','chanxueyanjidi',0,0,21,4,2),(26,'下载中心','wenjianguizhang',4,0,1,7,1),(27,'文件/规章','wenjianguizhang',0,0,26,1,2),(28,'学术报告','xueshubaogao',0,0,26,2,2),(29,'表格','biaoge',0,0,26,3,2),(30,'其它','qita',0,0,26,4,2),(31,'首页','main',0,0,1,1,1);
实体:
@Entity
@Table(name = "nav")
public class Nav implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Integer id;
@Column(name = "name")
private String lbmc;//类别名称
@Column(name = "namepy")
private String lbmcPy;//类别名称
@Column(name = "sl")
private int sl;//数量
@Column(name = "flag")
private int flag;//标识判断是否有子list
@Column(name = "order_id")
private int order_id;//级别排序
@Column(name = "level")
private int level;//级别
@ManyToOne(cascade={CascadeType.ALL},fetch = FetchType.LAZY) //多对一的关联FetchType.LAZY(懒加载)a) 只有真正获取数据时才发出SQL语句
/**(定义列名) @JoinColumn与@Column相区别的是:@JoinColumn注释的是保存表与表之间关系的字段,它要标注在实体属性上。而 @Column标注的是表中不包含表关系的字段。*/
@JoinColumn(name="parent_id")//这是自关联的pid列名设置
//多对一,@JoinColumn与@column类似,指定映射的数据库字段
private Nav parent;//父id
@OneToMany(targetEntity = Nav.class,cascade={CascadeType.ALL}, mappedBy="parent",fetch = FetchType.EAGER)//一对多,mappedBy="parent"表示由parent主导(即在parent端有值)
@OrderBy("order_id") //List的映射可以进行排序,对order_id进行排序
private List<Nav> childrens=new ArrayList<Nav>();
}
dao:
@Override
public List<Nav> queryAllNav(int id) {
String hql="from Nav nav where nav.parent.id=:id order by order_id";
Query q1=getCurrentSession().createQuery(hql).setInteger("id", id);
List<Nav> list=q1.list();
return list;
}
测试: 采用的是集成测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@Transactional
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class Spring_integration_testing {
@Resource
private ApplicationContext ctx;
@Resource
@Qualifier("ArticleServiceImpl")
private ArticleService adService;
@Test
public void testSave3() throws Exception{
List<Nav> allNavs=adService.queryAllNav(1);//查询出一级导航的
for(Nav nav:allNavs){
System.out.println("-----------------------");
System.out.println(nav.getLbmc());
System.out.println(nav.getChildrens().size());
System.out.println(nav.getParent().getLbmc());
for(Nav nav3:nav.getChildrens()){
System.out.println("===================");
System.out.println(nav3.getLbmc());
System.out.println(nav3.getChildrens().size());
System.out.println(nav3.getParent().getLbmc());
System.out.println("===================");
}
System.out.println("-----------------------");
}
}
}
运行结果:
root
-----------------------
-----------------------
实验室概况
5
root
===================
实验室简介
0
实验室概况
===================
===================
学术委员会
0
实验室概况
===================
===================
组织结构
0
实验室概况
===================
===================
仪器设备
0
实验室概况
===================
===================
规章制度
0
实验室概况
===================
-----------------------
-----------------------
新闻资讯
2
root
===================
新闻中心
0
新闻资讯
===================
===================
通知公告
0
新闻资讯
===================
-----------------------
-----------------------
科学研究
5
root
===================
研究方向
0
科学研究
===================
===================
研究队伍
0
科学研究
===================
===================
科研项目
0
科学研究
===================
===================
科研成果
0
科学研究
===================
===================
技术服务
0
科学研究
===================
-----------------------
-----------------------
合作交流
3
root
===================
国际合作
0
合作交流
===================
===================
学术会议
0
合作交流
===================
===================
国际合作
0
合作交流
===================
-----------------------
-----------------------
人才培养
4
root
===================
研究生信息
0
人才培养
===================
===================
校内导师
0
人才培养
===================
===================
校外导师
0
人才培养
===================
===================
产学研基地
0
人才培养
===================
-----------------------
-----------------------
下载中心
4
root
===================
文件/规章
0
下载中心
===================
===================
学术报告
0
下载中心
===================
===================
表格
0
下载中心
===================
===================
其它
0
下载中心
===================
-----------------------
然后简单的介绍几个Hibernate Annotation关系映射, 级联cascade属性
级联(cascade)属性
1、CascadeType.ALL(包括增、删、改、查,联动操作),其实查不算在内,查Fetch
2、CascadeType.MERGE(合并的join)--不重要
3、CascadeType.PERSIST(保存的时候在级联)
4、CascadeType.REFRESH(刷新说明:比如现在我查询出了数据,另外一个人在我查询数据之后,他对数据做了修改,这是才会级联上,hibernate会自动刷新我查询出来的数据)
5、CascadeType.REMOVE (只要在删除操作时才会级联)
6、我们一般都只设置CascadeType.ALL就OK了,
7、Cascade不是必须的,他的作用只是可以让我们快速的开发,我们也可以通过手动增、删、改、查
Fetch捉取策略
1、FetchType.EAGER(渴望的,希望马上得到)
a) 一对多关系,比如通过get()方法来get出一的一端,他之后会出一条SQL语句,不会自动去查询多的一端,如果设置FetchType.EAGER,会讲他的关联对象查询出来
b) 如果是load的话,他不会发出SQL语句,因为load支持延迟加载,只有真正获取数据时才会发SQL
2、FetchType.LAZY(懒加载)
a) 只有真正获取数据时才发出SQL语句
3、默认是:FetchType.LAZY(一对多)
4、默认是:FetchType.EAGER(多对一)
5、一般使用默认就可以了