搞了好久终于搞明白了,以前做树形数据的时候通过各种麻烦的方法做出树形的数据,那是有多麻烦啊!!一直就没想过通过一对多的关系来解决,今天突然来感原来可以这么简单就解决树形的数据,在这里记录一下.
表结构:
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 下载中心 =================== -----------------------
级联(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、一般使用默认就可以了