利用日志调试Hibernate架构中的DAO层方法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
利用日志调试Hibernate架构中的DAO层方法
胡银保;张瑞虹
【摘要】在Hibernate架构开发中,DAO层方法的设计与调试是一个关键环节.本文提出了一种利用Log4j的日志功能,在Hibernate中调试DAO层方法的技术,并利用日志记录跟踪方法的执行过程,为开发人员进行系统设计提供了有力的支持.该
机制可以有效地排除程序执行中的各种错误,呈现DAO层对象在生命周期中的各
种状态及转化过程,在系统设计和调试方面具有较好的辅助功能.
【期刊名称】《陇东学院学报》
【年(卷),期】2013(024)003
【总页数】4页(P16-19)
【关键词】Log4j;日志记录;DAO层方法;方法调试;代码跟踪
【作者】胡银保;张瑞虹
【作者单位】兰州工业学院网络中心,甘肃兰州 730050;甘肃省计算中心,甘肃兰州730000
【正文语种】中文
【中图分类】TP39
Log4j是Apache的一个开放源代码项目,可以控制整个系统日志输出情况.通过配置,可以使用Log4j控制日志信息输送的目的地、输出格式、日志信息级别等,通过使用第三方扩展软件,可以方便地将 Log4j集成到 J2EE、JINI甚至是SNMP
应用中.在J2EE设计中结合Log4j的功能,可以调试并跟踪模型层的各种方法,开发者可以深刻理解底层数据的操作细节,有利于软件的开发工作.
1 日志功能
记录日志报告了有关程序运行的处理过程,这些信息可以是普通的、描述程序进度的状态数据.在应用程序中添加日志记录主要是基于三个目的:①监视代码中变量的变化情况,周期性地记录到文件中供其他应用进行统计分析:②跟踪代码运行时的轨迹,作为日后审计的依据;③担当集成开发环境中的调试器,向文件或控制台打印代码的调试信息[1].本文主要讨论Log4j在调试期间的作用.如果没有记录日志,开发者可能会通过插入println()语句来解释程序的行为,这种方式在调试程序或修复bug期间会带来许多麻烦[2].而有时候,开发系统所支持的调试器也未必能反映出所有的真实情况.在Hibernate开发过程中,它自带的日志记录器Log就可以完成在不修改代码的情况下,自由地控制调试信息的输出.而开源项目Log4j是一个功能更强大的日志组件,提供方便的日志记录,它具有日志信息输送的目的地可选、日志输出格式灵活、控制日志输出级别等优点,可以通过配置文件灵活地配置上面的操作[3].
Log4j由三个主要的组件组成:Logger、Appender、Layout.其中:Logger组件负责在程序的运行过程中生成日志,并且负责对日志进行筛选,并指定记录日志的级别;Appender组件用来确定日志描述输出的目的地,如控制台、文件系统、数据库、服务器等,一个Logger组件可以对应多个Appender组件,表示一个Logger可以向多个设备输出相应的信息,再与日志级别配合使用可以使日志功能得到进一步的提高;Layout组件定义了日志记录的样式和内容,Log4j提供了一些已经定义好了的布局[4].
一个Logger组件可以包含多个Appender组件,这意味着一个日志描述可以输出到多个设备上,每个Appender组件都必须对应一种Layout组件,用来确定所
输出的样式.三者的关系如图1所示.
图1 Log4j主要组件的关系
日志记录器(Logger)的行为是分等级的,Log4j建议只使用四个级别,优先级从高到低分别是 ERROR、WARN、INFO、DEBUG.通过定义级别,可以控制到应用程序中相应级别的日志信息的开关.程序会打印高于或等于所设置级别的日志,设置的日志等级越高,打印出来的日志就越少.
2 DAO层中方法的执行
在J2EE项目开发中,Hibernate框架为数据持久层提供了一系列的DAO层方法,完成数据的存储、删除、更新、查询等功能,如:save()、findByExample()、attachDirty()等等.在项目的开发过程中,当程序执行的结果出现问题,或者开发者想跟踪程序的执行过程时,设计者可以通过两种方法获取相关的信息,即:加断
点调试,或者在配置文件中设置“show_sql”属性的值为true.然而,这两种方
法都不是很全面.有时对程序的跟踪执行并没有显示错误,但是却得不到正确的结果;有时生成的sql语句不符合设计者的意图,不能达到设计要求.下面说明几种
设计中出现的问题.
假设数据库test中有一个用户表user,包含用户名和密码两个字段,其中userName字段是主键.
2.1 用户注册功能中出现的问题
设计用户注册功能时,在调试和运行中遇到以下两个问题:
⑴设计用户注册功能时,用到DAO层的save()方法.如果按照这个方法原样执行,是保存不了数据的.在调试的过程中,将“show_sql”参数的属性设置成true值,结果不显示存储时生成的SQL语句,同时程序没有任何错误地逐层执行,直到按
设计要求提示“用户注册成功”,但查看数据表时,没有注册的信息.
⑵当不经意注册同名的用户时,结果肯定是失败,这与理论上的分析是相吻合
的.设计者需要知道失败的原因以便改进设计流程提醒用户.此时调试程序,形成的SQL语句没有问题,存储失败时抛出的异常体现不出具体的原因,只能靠设计
者自己分析并解决这个问题了.
2.2 用户登录功能中出现的问题
在执行登录功能时要查询登录的用户信息,形成的查询对象以user为例.设计者最先使用的DAO层方法便是find-ByExample(user),依据user对象在数据表中进行查询,如果返回的List对象不为空,说明这个用户存储在,则登录成功;反之,登录失败.但是执行结果是:输入表中存在的用户数据,查找成功;但是输入不存在
的用户名,密码保留为表中已有的某条记录的数据,结果显示查找成功.这个结果出乎设计者的意料.分析SQL语句后得知:方法按照非关键字段—密码进行了条件查询,而忽略了对关键字段的比较,导致密码相同的非法用户登录成功.设计者需要知道底层执行的具体过程,从而找出问题的解决办法.
2.3 跟踪attachDirty()方法的执行策略
Hibernate中的对象有三种状态,即瞬时状态(Transient)、持久状态(Persistent)
和脱管状态(Detached).通过Session的save()和saveOrUpdate()方法可以把
一个瞬时对象与数据库相关联而成为持久化对象,通过Session的update()、save-OrUpdate()和lock()等方法,可以把脱管对象变为持久对象,DAO层中的merge()、attachDirty()、attachClean()等方法就体现了这些对象之间的转换关系.如果跟踪这些方法的执行过程,仅仅做程序调试工作是不够的,必须有一个行之有效的方法可以反映出对象的状态变化.
3 方法的调试
3.1 利用Log4j进行调试的准备工作
在利用Log4j进行日志记录并做调试工作之前,必须要进行一些设置工作,这些
工作分为以下几个步骤.
⑴ 将log4j.jar文件复制到项目的类路径下.由于Hibernate支持中已经包含了Log4j的jar包,这一步可以跳过.
⑵ 在src目录下创建Log4j日志配置文件—log4j.properties,代码如下:
根据配置信息,在D盘的根目录下创建了日志文件hibernate.log,并把调试过程中DEBUG级别及以上的日志记录到这个文件中,以备调试者查看.
⑶在DAO类中创建Logger对象,并在方法中记录日志.
在需要调试的方法中开始记录日志,如:
3.2 利用日志文件解决问题
⑴解决用户注册功能中的问题
利用自动生成的save()方法实现注册(录入数据为<“计算机”,“computer”>),数据表中没有进行存储,日志文件中记录的关键信息如图2所示.
图2 执行save()方法后的日志文件
通过查看日志文件可知,底层没有实现持久化工作,因此看不到生成的SQL语句及参数的传递和绑定过程.从理论上分析,持久化对象总是与Session和Transaction相关联,在一个Session中,对持久对象的改变必须在 Transaction 终止,也就是执行commit()之后,才在数据库中真正运行SQL进行变更,持久对象的状态才会与数据库进行同步.因此运行结果与理论相结合,便找到了问题的所在,修改save()方法,便可以保存数据了,程序如下:
同样的道理,输入已存在的数据(录入数据为<“计算机”,“123456”>)再次
注册后,查看日志文件,结果如图3所示.
图3 注册已有用户后的日志文件
从日志文件可以看出,提示有重复的关键字要进行存储,session不能够同步数据库.
⑵解决用户登录功能中的问题
利用DAO层的findByExample()方法测试登录功能,测试数据为<“电脑”,“computer”>,需要说明的是:此时数据表中没有这条记录,存在的记录是<“计算机”,“computer”>.运行结果显示:电脑,you login in successfull!查看日志文件,如图4所示.
图4 非法用户登录的日志文件
从日志可以看出,查询条件仅仅考虑了非关键字数据密码,没有联合关键字进行筛选.明确了该方法执行的过程后,设计者应该重新编写方法完成记录在数据表中的查询.设计后的方法采用了HQL语言编写,通过比较每一个字段值,获得最终的查询结果,代码如下:
设计者可以查看日志文件中生成的SQL语句,同时完成了对两个字段的过滤.
⑶跟踪attachDirty()方法的执行策略
attachDirty()方法可以调用saveOrUpdate()函数将传入的对象持久化并保存.如果对象未保存(Transient状态),调用save方法保存;如果对象已保存(Detached 状态),调用update方法将对象与Session重新关联.在跟踪这个方法的执行过程时,dao.attachDirty(user)需准备两种参数,例如:
① user:“植物”,“plant”(这条记录在数据表中不存在)
② uaer:“计算机”,“world”(数据表中主键值存在,但密码不同)
在执行第一种参数时,日志文件显示:1 insertions,0 updates,0 deletions to 1
objects,并执行了插入语句;在执行第二种参数时,日志文件显示:0 insertions,1 updates,0 deletions to 1 objects,并执行了更新语句,修改了主键值是“计算机”的记录的密码.对于Hibernate实体对象的生命周期中三个主要的存在状态一定要把握清楚,才能更好地利用Hibernate的特点来进行软件的开发工作[5].
4 小结
在Hibernate开发中,恰当地设置Log4j日志功能,可以记录DAO层方法的执行过程,为程序调试提供了有力的支持.如果需要了解DAO方法的执行细节,可以根据日志记录进行跟踪.开发者根据需要,只要正确配置log4j.properties文件,执行程序后分析有效的日志记录,就可以全面掌握底层的数据操作,理解代码的执行过程,有利于编写并完善程序代码和处理逻辑.
参考文献:
[1]肖文,等.基于J2EE的日志管理中间件的设计和实现[J].计算机应用与研究,2004,(10):173-175.
[2](美)Bruce Eckel.陈昊鹏,饶若楠译.Java编程思想[M].北京:机械工业出版社,2007.645-650.
[3]林建素,孟康健.Eclipse开发学习笔记[M].北京:电子工业出版社,2008.270 -273.
[4]夏文忠.Log4J在学生管理系统中的开发与应用[J].电脑编程技巧与维护,2009,(1):34 -36.
[5]陈天河.Struts、Hibernate、Spring集成开发宝典[M].北京:电子工业出版社,2007:390-396.。