TA的每日心情 | 开心 2021-3-12 23:18 |
---|
签到天数: 2 天 [LV.1]初来乍到
|
- 在前两章我为大家详细分析了JAR包的选择和必须的配置文件,那么这一章,我就对例子的
- 层次结构进行说明,并实现除WEB层的功能代码。
- 第三部分:建立框架代码[/b]
- 工程结构[/b]
- [img]http://img.javaxxz.com/2014/11/4/000022343.jpg[/img]
- 大家可以看到,本例一共分为:dao、entity、service、web四层。另外在这些层次下,还以业务功能再进行分包,
- 这样做是为了方便在以后的功能扩展中,能更好的管理和维护代码。如果将所有类都直接集中在这4个包下面,随着类的增加,
- 会越来越难以维护,而且查找起来也很费劲。
- HibernateDao[/b]
- 在本例中,我是通过继承Spring提供的HibernateDaoSupport来实现持久层的基类。同时引入泛型参数,
- 封装了一些基本操作方法。
- [img]http://img.javaxxz.com/2014/11/4/000022609.jpg[/img]
- 这是HibernateDao的部分代码,引入的这个泛型参数,其实就是实体类(User、Role)。通过传递这个实体类,
- 在构造方法中利用反射特性将它从JVM中取出来。
- [img]http://img.javaxxz.com/2014/11/4/000023093.jpg[/img]
- 这里的getClass()方法是获得继承HibernateDao的类(UserDao、RoleDao)
- getGenericSuperclass()方法就是通过这些继承了HibernateDao的类,来得到父类(父类就是HibernateDao)的泛型。
- 注意这个方法的返回值为Type,这是一个类型接口。请参考API。
- 因为在继承HibernateDao
- 的时候,会给它加一个泛型参数。比如,User、Role实体类。因此超类是参数化类型,所以返回的
- Type 对象包含所使用的实际类型参数。这里返回的Type对象是ParameterizedType接口的实现类ParameterizedTypeImpl,
- 所以要将返回类型转型为ParameterizedType。
- getActualTypeArguments()方法是ParameterizedType接口中的,它的作用就是获得实际类型参数
- Type 对象的数组,因为我们这里只定义了一个泛型参数,数组里面也只有一个值,所以需要在数组下标处填0。
- 然后最后一步转型千万别忘记了,因为这个方法返回的可是一个Type数组喔。
- 如果对于这部分的说明还有点不理解的话,请到时候有了代码,设个断点跟踪一下,就会全部清楚了。关于java反射,
- 它已经超出本文的范围。大象只对本例中用到的部分进行讲解。
- 使用这种写法,是方便我们进行类型转换与类型检查。另外还可以简化某些方法的写法。
- 比如:createCriteria(Criterion...
- criterions)这个方法。参数是Criterion类型的可变参数,它是用来设置查询条件。如果要进行对象化查询,
- 那么最简单的写法就可以直接写成createCriteria()。另外还有重载的方法,可以根据传入class类型来创建自定义查询。
- dao[/b]
- 持久层的Dao类是根据实体类定义,一般是一个实体类就会有一个对应的Dao类。当然这要跟业务需求来设计,
- 不是绝对的。另外你也可以为了简便而去掉dao层,将持久化操作与业务逻辑全部写在service层。
- [img]http://img.javaxxz.com/2014/11/4/000023203.jpg[/img]
- 这些定义的方法是供service层调用,在业务层,将不会看到一行与持久层有关的代码,降低藕合性是这样做的目的。
- @Repository注解的作用就是标注这个UserDao是一个持久层组件。
- 还记得前一章讲到的扫描器吗?component-scan
- 它就是用来将标有@Repository,@Service这样的注解类扫描到Spring的容器里,并且同时对标有@Autowired
- 注解的Bean启用了自动注入功能。这就是Spring从2.5开始提供的新特性。我们使用注解的方法,
- 就可以告别那繁琐的配置文件定义。
- entity[/b]
- 关于实体的定义就是使用JPA注解,关于这部分,我以前写过一篇文章专门讲这个,
- 如果有不清楚的朋友可以先参考一下。学习JPA――Hibernate
- Annotation使用实例
- 本例中,我有两点要讲下。
- 第一、管理主键的表generator_table去掉原来单独定义的那个ID主键,把g_key设为主键,
- 整个表将只有两个字段,g_key和g_value。
- 第二、在User实体中,我将角色ID(role_id)与角色实体(Role)做了一个多对一关联。
- 这一点是原来文章中没有讲过的。
- [img]http://img.javaxxz.com/2014/11/4/000023359.jpg[/img]
- 请一定注意role_id是user表的字段。我在本例中设定的是一个角色可以对应多个人员,所以这个role_id
- 存的就是role表id的值。fetch
- = FetchType.[i]LAZY[/i]指定采用延迟检索,如果当你取得了User对象,但又不想取Role中的信息,这时,
- User对象中的role属性是代理状态。
- Role对象中的值都是空的。只有当你使用role.id或role.name进行取值的时候,hibernate才会去数据库中查找对应的记录,
- 因此在一定程度上降低了资源消耗。不过这里有点要注意,采用延迟检索的时候,
- 需要加上前一篇讲到的OpenSessionInViewFilter过滤器。否则会遇到session关闭的异常。
- service[/b]
- [img]http://img.javaxxz.com/2014/11/4/000023531.jpg[/img]
- @Service表示这是业务层组件。在业务层需要对UserDao加上@Autowired注解,大象在这里将业务层的方法名与持久
- 层的方法名定义为一样的,是我的一种习惯,大家可以按自己的想法来做。
- 测试[/b]
- 既然有了这么多代码,那就来测试一下吧,看看有没有问题。
- [img]http://img.javaxxz.com/2014/11/4/000023734.jpg[/img]
- 好吧,为了照顾那些坚定的JUnit拥护者,再写一个JUnit测试。本例使用junit-4.4.jar
- [img]http://img.javaxxz.com/2014/11/4/000023859.jpg[/img]
- [img]http://img.javaxxz.com/2014/11/4/000024000.jpg[/img]
- @BeforeClass注解的方法表示在类实例化之前,也就是在类的构造方法执行之前就会执行。
- 而且使用这个注解的方法必须是static void
- @Test标明这是测试方法,方法名不用像以前那样必须按照规则进行命名,可以自由定义。
- 上图显示大象使用JUnit方式测试也通过了(如果不会通过我写它干嘛?嘿嘿)。
- 假如我将张三改成张四,再来看看测试结果。
- [img]http://img.javaxxz.com/2014/11/4/000024171.jpg[/img]
- 这个截图可以很明显的说明所有东西。
- 这一篇是给大家讲怎么用代码来实现除web层之外的全注解步骤。当然,我主要是讲思路,其实思路比代码重要得多。
- 这一个系列的最后,我会放上所有源码供大家下载。现在这样慢慢分析,是想给大家讲道理。我们应该努力提升自己的境界与层次,
- 而不要只把眼光放在代码上面。
- 下一章将会着重介绍web层,以及struts2的注解插件struts2-convention。那么,我们下次继续。
- 本文为菠萝大象原创,如要转载请注明出处。
复制代码 |
|