appfuse源码分析一(持久层)
 

2008-12-23 作者:刘文涛 来源:blogjava.net

 

此主题 涉及到 加下有这么四个包 :

一 :在org.appfuse下有这么一个类Constants.java,它是一个存储常量的类,

如果我们在程序中有一些常量需要改变名称,而这个常量分布在不同的类里,如果我们要修改它,就是一项很大的工程。而且重新编译也会遇到很多问题。我们通过建立一个常量类,如果我们需要修改,只需要在这里修改。然后把这个类编译其他代码不需要改变。

他里边的属性都是静态的,例如 : 

public   static   final  String BUNDLE_KEY  =   " ApplicationResources " ;

二 :在org.appfuse.dao下有四个接口。

1 Dao
2 LookupDao
3 RoleDao
4 UserDao

1 :Dao:

1 List getObjects(Class clazz)     返回数据库中与此类对应的表的所有值
2 Object getObject(Class clazz, Serializable id)    返回与此类对应的表的主键值为id的数据
3 void  saveObject(Object o)    保存此对象
4 void  removeObject(Class clazz, Serializable id)    根据id值(主键)删除此对象

后三个接口继承了第一个接口。

2 :LookupDao:

1 List getRoles()     返回role表中的所有数据

3 :  RoleDao:

1 Role getRoleByName(String rolename)
2 List getRoles(Role role)
3 void  saveRole(Role role)
4 void  removeRole(String rolename)

4 :UserDao:

1 User getUser(Long userId);
2 UserDetails loadUserByUsername(String username)  throws  UsernameNotFoundException
3 List getUsers(User user)
4 void  saveUser(User user)
5 void  removeUser(Long userId)

三  :  org.appfuse.dao.hibernate 此包下有四个类 :

1 BaseDaoHibernate  extends  HibernateDaoSupport  implements  Dao
2 LookupDaoHibernate  extends  BaseDaoHibernate  implements  LookupDao
3 RoleDaoHibernate  extends  BaseDaoHibernate implements RoleDao
4 UserDaoHibernate  extends  BaseDaoHibernate  implements  UserDao, UserDetailsService

1 :  BaseDaoHibernate:

1 List getObjects(Class clazz)     返回数据库中与此类对应的表的所有值
2 Object getObject(Class clazz, Serializable id)    返回与此类对应的表的主键值为id的数据
3 void  saveObject(Object o)    保存此对象
4 void  removeObject(Class clazz, Serializable id)    根据id值(主键)删除此对象

后三个类继承了第一个类。

2 :LookupDaoHibernate :

1 List getRoles()     返回role表中的所有数据

3 :RoleDaoHibernate :

1 Role getRoleByName(String rolename)
2 List getRoles(Role role)
3 void  saveRole(Role role)
4 void  removeRole(String rolename)

4 :UserDaoHibernate :

1 User getUser(Long userId);
2 UserDetails loadUserByUsername(String username)  throws  UsernameNotFoundException
3 List getUsers(User user)
4 void  saveUser(User user)
5 void  removeUser(Long userId)

他继承接口UserDetailsService并实现了它的唯一方法loadUserByUsername(String username).

5 :还有一个名为applicationContext-hibernate.xml的文件。

它是spring的配置文件。里边定义了与hibernate相关的的六个bean:

1 sessionFactory
2 transactionManager
3 dao
4 loopupDao
5 userDao
6 roleDao.

此文件只是整个spring配制文件的一部分。它配置了与hibernate相关的一些配置.

spring它是一种j2ee架构级框架,有人把它叫做胶水代码,通过它可以把项目的不同部分组合在一起,(有点类似于工厂类的作用),但是它有以下优点.

1 .它可以把不同的开发框架整合在一起.
2 .通过xml来配置组件之间调用关系.不需要硬编码.组件之间是松偶合的.
3 .它是面向接口编程的,调用getBean()方法得到的都是接口.
4 .提供aop支持.可以方便的进行面向方面编程.

5.1 : sessionFactory有三个属性:

1  :  < property name = " dataSource "  ref = " dataSource " />

dataSource:它指明此SessionFactory所依赖的数据源,数据源的相关定义在名为dataSource的bean中.

2  :  < property name = " mappingResources " > ..

mappingResources定义了hibernate映射文件,这些映射文件指明类与数据库中表的对应关系.

3  :  < property name = " hibernateProperties " > .

hibernateProperties指明数据库类型.

5.2 : transactionManager  : 事务管理bean

transactionManager  用来管理数据库事务.它只有一个属性sessionFactory.指明此事务bean依赖的sessionFactory.

< bean id = " transactionManager "   class = " org.springframework.orm.hibernate3.HibernateTransactionManager " >
    
< property name = " sessionFactory "  ref = " sessionFactory " />
</
bean >

5.3 : dao

名为dao的bean的具体实现类为org.appfuse.dao.hibernate.BaseDaoHibernate.它依赖sessionFactory,

< bean id = " dao "   class = " org.appfuse.dao.hibernate.BaseDaoHibernate " >
    
< property name = " sessionFactory "  ref = " sessionFactory " />
</
bean >

需要注意的是在程序中如果要调用这个bean 得到的是BaseDaoHibernate的接口.

Dao dao  =  (Dao)ctx.getBean( " dao " );

LookupDao,userDao,roleDao与dao类似.

四 :org.appfuse.model 此包下有5个类。

除了LabelValue外其他几个都是与数据库中的表相关的pojo对象

此包中的LabelValue和struts包中的org.apache.struts.utils.LabelValueBean除了类名之外,其他都一样。

address,Role和User这三个类都是从BaseObject继承下来的。

1 :BaseObject:

public   abstract   class  BaseObject  implements  Serializable 

它是一个抽象类,里边有3个抽象方法toString(),equals(Object o), hashCode().

2 :Address: 

public   class  Address  extends  BaseObject  implements  Serializable

 它继承BaseObject实现Serializable. 在类的上方有Xdoclet的struts标记

@struts.form include - all = " true "   extends = " BaseForm "

表示它是一个form继承于BaseForm。

它有五个与地址相关的属性,每个属性有对应的get和set方法.而每个get方法的前面有Xdoclet的hibernate标记.

@hibernate.property column = " address "  not - null = " false "  length = " 150 "

表明类的此属性与数据库表之间的对应关系以及数据库此字段的特性,如长度,是否为空等 。

@struts.validator type = " required "  

表示此字段做为struts 的form字段需要验证。验证类型为required.在getPostalCode()前边有 :

@struts.validator type = " required "
@struts.validator type
= " mask "  msgkey = " errors.zip "
@struts.validator
- var name = " mask "  value = " ${zip} "  

它的意思为在struts的form中此字段验证规则为required,而且还要和自定义的zip规则相匹配。如果出错,提示错误信息,注意address这个类并没有和数据库中的一个具体的表对应,它作为user表的一部分.俗称  :组件映射。

3 :User :

public   class  User  extends  BaseObject  implements  Serializable, UserDetails

它继承BaseObject实现Serializable和UserDetails接口。

在它的类的声明前面有XDoclet标记:

@struts.form include - all = " true "   extends = " BaseForm "
@hibernate.
class  table = " app_user "

具体含义同上。

这个类需要注意的是以下几点:

3.1 :

1 Address address  =   new  Address();
2
3 /**
4  * @hibernate.component
5   */

6 public  Address getAddress()  {
7      return  address;
8 }

把address作为它的一个属性address类的属性最终映射成表User的字段。

3.2 :

1 protected  String password; 
2  
3   /**
4   * @hibernate.property column="password" not-null="true"
5    */

6   public  String getPassword()  {
7        return  password;
8  }

3.3 :

1 /**
2  * @hibernate.set table="user_role" cascade="save-update" lazy="false"
3  * @hibernate.collection-key column="user_id"
4  * @hibernate.collection-many-to-many class="org.appfuse.model.Role" column="role_id"
5   */

6 public  Set getRoles()  {
7      return  roles;
8 }

3.4。它继承实现了接口UserDetails的getAuthorities()方法 :

1 /**
2  *  @see  org.acegisecurity.userdetails.UserDetails#getAuthorities()
3   */

4 public  GrantedAuthority[] getAuthorities()  {
5      return  (GrantedAuthority[]) roles.toArray( new  GrantedAuthority[ 0 ]);
6 }

返回roles强制转换为类型为GrantedAuthority的数组。

此外它还继承实现了UserDetails的

1 getUsername()
2 getPassword()
3 isEnabled()
4 isAccountNonExpired()
5 isAccountNonLocked()
6 isCredentialsNonExpired()

3.5。它继承实现了BaseObject的equals(),hashCode(),toString().

4 :Role:

public   class  Role  extends  BaseObject  implements  Serializable, GrantedAuthority

它继承BaseObject实现Serializable和GrantedAuthority接口。

因为appfuse使用了基于spring 的acegi安全框架,所以要实现GrantedAuthority的唯一方法: getAuthority()

在此类的前边有两条Xdoclet标记:

@struts.form  extends = " BaseForm "
@hibernate.
class  table = " role "

第1条表示它是一个struts的form.

第2条表示此类与数据库中的一个名为role的表对应。

它有如下属性。

    private Long id;
    private String name;
    private String description;

类似于address它的每个属性的get方法前边都有一些与struts或hibernate相关的XDoclet标记。需要注意的是以下几点:

4.1 :

/**
 * @hibernate.id column="id" generator-class="increment" unsaved-value="null"
 
*/

public  Long getId()  {
    
return  id;
}

4.2 :

public  String getAuthority()  {
    
return  getName();
}

实现GrantedAuthority的 getAuthority()方法就是返回 getName();

五 :appfuse 涉及到的 hibernate配置文件

1 :appfuse的hibernate配置文件中主键生成方式 选择了 :

< generator  class = " native " ></ generator >

它表示 :根据底层数据库的能力选择identity, sequence 或者hilo中的一个。

2 :User.hbm.xml 中 有这样的配置 :

< version name = " version "  column = " version "  type = " java.lang.Integer " />

对应表 app_user中 对应 有 一个 version 字段 (int 11) ;

含义 :

<version>元素是可选的,表明表中包含附带版本信息的数据。 这在你准备使用 长事务(long transactions)的时候特别有用。
版本号必须是以下类型:long, integer, short, timestamp或者calendar

3 :关于多对多 User.hbm.xml  与 Role.hbm.xml

首先 User.java中 有 :

    protected Set roles = new HashSet();
    
    
public Set getRoles() {
        
return roles;
    }

    
    
public void setRoles(Set roles) {
        
this.roles = roles;
    }

    
    
public void addRole(Role role) {
        getRoles().add(role);
    }


    
/**
     * Convert user roles to LabelValue objects for convenience.  
     */

    
public List getRoleList() {
        List userRoles = 
new ArrayList();
        
if (this.roles != null{
            
for (Iterator it = roles.iterator(); it.hasNext();) {
                Role role = (Role) it.next();
                
// convert the user's roles to LabelValue Objects
                userRoles.add(new LabelValue(role.getName(),
                                             role.getName()));
            }

        }

        
return userRoles;
    }

在User.hbm.xml中 有 下列配置 :

        <set name="roles" table="user_role" lazy="false" cascade="save-update">
            <key column="user_id"></key>
            <many-to-many 
class="org.appfuse.model.Role" column="role_id" outer-join="auto"/>
        </set>

在Role.java 没有任何相关属性。在 Role.hbm.xml中没有任何相关配置 。

详细说明一下 User.hbm.xml中相关的属性含义 :

3.1 : cascade(级联) (可选): 指明哪些操作会从父对象(User)级联到关联的对象(Role)。   本例中当 save或update时 级联。
              cascade="all|none|save-update|delete|all-delete-orphan"

3.2 : lazy (可选 - 默认为 proxy): 默认情况下,单点关联是经过代理的。
       lazy="true"指定此属性应该在实例变量第一次被访问时应该延迟抓取(fetche lazily)(需要运行时字节码的增强)。 
       lazy="false"
指定此关联总是被预先抓取。
 
      本例中 关联是被 预先抓取 的。

3.3 : outer-join(可选 - 默认为auto): 即外连接抓取

3.4 : fetch (可选 - 默认为 select): 
      在外连接抓取(outer-join fetching)和序列选择抓取(sequential select fetching)两者中选择其一。

3.5 : optimistic-lock (可选 - 默认是 true):表明更新此组件是否需要获取乐观锁。
      换句话说,当这个属性变脏时,是否增加版本号(Version)

3.6 :

<property name="enabled" type="yes_no" column="account_enabled"></property>

这里面 数据库 的 account_enabled 字段 类型 是 :char(1)的。

User.java类中 enable 属性是 boolean型的 :

protected boolean enabled;

火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织