jackyrong

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
 

spring,hibenate,再搭配一个X(就是本文标题中的+x),已经几乎横扫目前的JAVA应用界,好象目前
一讲JAVA应用开发,都必须要懂这三样东西的。最近花了些时间来学习之,发现其实还是有不少模式和规律可以找到的,
现将心得小结之,总结这些带规律的“板斧”类东西,呵呵。

以一个最简单的一对多例子来讲解。比如有目录category,产品类product,目录和产品的关系是一对多关系。于是咱们先来搞个
PO(下面的代码都只是写重点部分,其他的就省略了,学过或看过的,一看就明,只起到提点作用)


1、建好基础:MODEL层
category.java

public class category
{
.......id,description之类的属性

private Set products;                 //用集合来表示产品

public Set getProducts()
 {
  return products;
 }

 /**
  * @param products The products to set.
  */
 public void setProducts(Set products)
 {
  this.products = products;
 }

}
product实体
public class Product
{
......
private Category category;
public Category getCategory()
 {
  return category;
 }

 /**
  * @param category The category to set.
  */
 public void setCategory(Category category)
 {
  this.category = category;
 }


}

之后我们马上搞映射文件了
catagory.hbm.xml中,要特别注意设置为
<set cascade="none" name="products" inverse="true" order-by="name asc">
   <key column="CATEGORY_ID" />
   <one-to-many class="cn.liao.model.Product" />
  </set>

而products.hbm.xml中,特别注意设置为
<many-to-one column="CATEGORY_ID" name="category"/>

好了,model层搞好了,我们放到cn.liao.model这个包下,这个包我们专放model层的东西

2、接下来,我们来搞持久层了,其实持久层的话,之前我们用传统的JDBC去玩的,现在换了hibernate而已,注意在这层里,我们要把PO持久保存到数据库了,和PO打交道了,接受来自业务层的对象了,这里等于临门一脚了,所以一般我们用DAO模式去搞的,比如搞个工厂之类的东西,可扩展性好,下面的例子里,只是简单给出接口,然后再实现之,实现时,通过getHibernateTemplate()得到spring中所定义的操作模版

Icategory.java(category的DAO接口)
public interface CategoryDao
{
 // 保存商品分类
 public Category saveCategory( Category category );
 // 修改商品分类
 public Category updateCategory( Category category );
 // 得到所有的商品分类
 public List getAllCategorys();
 // 得到某个商品分类的信息
 public Category getCategory( String categoryId );
 // 删除某个商品分类的信息
 public void deleteCategory( Category category );
}

而实现呢,我们命名一个叫categoryDaoHibernateImpl的类(注意我们为了规范,一般用impl做名字的后缀)


import org.springframework.orm.hibernate3.support.HibernateDaoSupport;i
mport cn.liao.dao.CategoryDao;
import cn.liao.model.Category;

public class CategoryDaoHibernateImpl
   extends HibernateDaoSupport
   implements CategoryDao
{

 public Category saveCategory(Category category)
 {
  this.getHibernateTemplate().save( category );
  this.getHibernateTemplate().flush();
  return category;
 }

 public List getAllCategorys()
 {
  String sql = "from Category c order by c.name";
  return this.getHibernateTemplate().find( sql );
 }

 public void deleteCategory(Category category)
 {
  this.getHibernateTemplate().delete( category );
 }

 public Category getCategory(String categoryId)
 {
  Category category = (Category)this.getHibernateTemplate()
   .get( Category.class, categoryId );
  return category;
 }

 public Category updateCategory(Category category)
 {
  this.getHibernateTemplate().update( category );
  this.getHibernateTemplate().flush();
  return category;
 }

}

呵呵,看到了吧,我们在这里,继承了HiberanteDaoSupport,又把很多东西简单化了,完全就是get呀,update呀,delete等傻瓜方法了,
那个sessionfactory哪去了?我们等阵注入给它。注意,这时我们的持久层搞好了,我们把它放到cn.liao.dao包里去,方便管理

3、好了,接下来我们来搞业务层。业务逻辑层是很关键的,它要进行一些实际的运算之类的,处理后再把对象传给持久层进行保存。
为了解藕合,我们依然用接口式编程。比如对category类,如果要增,删,改,查的话,我们依然定义IcategoryService接口:

public  Interface IcategorySerivce
{

 // 保存商品分类信息
 public Category saveCategory( Category category ) throws  xxxexcepiton;
 // 修改商品分类信息
 public Category updateCategory( Category category ) throws xxxexception;
 // 得到所有的商品分类信息
 public List getAllCategorys();
 // 得到某个商品分类的信息
 public Category getCategory( String categoryId ) throws xxxexception;
 // 删除某个商品分类的信息
 public void deleteCategory( String categoryId ) throws xxxexception;
}


}

接下来,真正实现这个业务接口的实现类为
public class CategoryServiceImpl implements CategoryService
{

//要用到DAO层的对象了
private CategoryDao categoryDao;

 public CategoryDao getCategoryDao()
 {
  return categoryDao;
 }

 

 public void setCategoryDao(CategoryDao categoryDao)
 {
  this.categoryDao = categoryDao;
 }




// 保存商品分类信息
 public Category saveCategory( Category category ) throws  xxxexcepiton
{


try
  {

//比如这里再进行一些商业逻辑计算
。。。。。。。。

//调用持久层去保存对象了
   Category c = this.getCategoryDao().saveCategory( category );
   return c;
  }
  catch   (....)
{

}


.........//其他如此类推

}
  注意的是,我们在这里要用到的是DAO层的categoryDao对象了,但我们并不在这里硬编码,而是依靠spring里进行注入


4、好了,我们现在来搞前端的控制层了(controller)了。我们这里用jsf+spring+hibernate的,
这里我们先提供一个基类baseaction,提取大家都要用到的一些东西,减少在开发时的代码量,其实换了structs的话,也可以先搞个baseaction的,让它继承自Action。我们的这个JSF的baseaction这样搞

public class BaseBean
{
 

 protected ServiceLocator serviceLocator;


public ServiceLocator getServiceLocator()
 {
  return this.serviceLocator;
 }

 public void setServiceLocator(ServiceLocator newServiceLocator)
 {
    this.serviceLocator = newServiceLocator;

  this.init();
 }
protected void init()
 {
 }
}


注意,这里的 ServiceLocator 类,我们接下来会编写,我们再这里,依然是接口编程
public interface ServiceLocator

{

    public ICategoryService getCategoryService();

    public IUserService getUserService();

    。。。。。这里可能还有很多其他的服务

}

记得吧,IcategoryService就是我们刚才已经做好了的处理目录类的业务逻辑接口,这里,还存在很多其他业务相关的逻辑接口的,可以一一列出,这个接口的目的是定义了所有业务层对象实例的方法。

然后又是对其的一个实现类,命名为ServiceLocatorImpl

public class ServiceLocatorImpl implements ServiceLocator {

 

private ApplicationContext appContext;

 

       public ServiceLocatorImpl() {

         //这里先获得ServletContext

              ServletContext context = FacesUtils.getServletContext();

 

              this.appContext = WebApplicationContextUtils

                            .getRequiredWebApplicationContext(context);

       }

 

      

       public Object lookupService(String serviceBeanName) {

              return appContext.getBean(serviceBeanName);

       }

 

      

       public CategoryService getCategoryService() {

              return (CategoryService) lookupService(“categoryservice”);

       }

}
 
这里,首先得到getServletContext对象的实例,然后通过springWebApplicationContextUtils类的getRequiredWebApplicationContext得到applicationcontext对象的实例,最后通过ApplicationContext对象的实例得到这些业务方法类的实例

    这个时候,我们把这些业务层的所有东西,都放到一个统一的包里,比如
cn.liao.services
或者叫cn.liao.business

 

 

   好了,我们最后看下JSF里的前置bean如何写法,JSF里,其实就是把actionformaction都结合在一起了,用javabean的形式来表达,大概构造为:

    public class CategoryBean extends BaseBean

{

 。。。。。一系列的SETGET方法

 

//增加产品的action

public String createAction()

    {

try

           {

                  this.getServiceLocator().getCategoryService().saveCategory( category );

 

 }

return        SUCCESS

catch (…..)

{

};

}
 private Category convertToCategory()

       {

              Category category = new Category();

              category.setId( this.id );

              category.setName( this.name );

              category.setDescription( this.description );

              return category;

       }

 在上面的代码中,首先用convertToCategory(),构造出了Category 对象,十分简单,都是用set 的方法(前台的JSF会帮你自动绑定好)。接着在createaction里,就用
this.getServiceLocator().getCategoryService().saveCategory( category );
来调用业务层的方法了,调用成功的话返回字符串success,这个success是在JSF的配置文件里去配置去导航的。

5、我们接着要写JSFfaces-managed-beans.xml,这个是其配置前置BEAN的文件,可以看做是一个粘合剂
<managed-bean>

        <description>

           Service locator of the business services

        </description>

        <managed-bean-name>serviceLocatorBean</managed-bean-name>

        <managed-bean-class>

           cn.liao.services.ServiceLocatorImpl

        </managed-bean-class>

        <managed-bean-scope>application</managed-bean-scope>

    </managed-bean>

 

<managed-bean>

        <description>

           Backing bean that contains category information.

        </description>

        <managed-bean-name>categoryBean</managed-bean-name>

        <managed-bean-class>

           cn.liao.services.CategoryBean

        </managed-bean-class>

        <managed-bean-scope>request</managed-bean-scope>

        <managed-property>

           <property-name>id</property-name>

           <value>#{param.categoryId}</value>

        </managed-property>

        <managed-property>

           <property-name>serviceLocator</property-name>

           <value>#{serviceLocatorBean}</value>

        </managed-property>

    </managed-bean>
  

 

   在上面的配置文件中,首先指出了serviceLocatorBean这个BEAN的实际位置是代表cn.liao.services.ServiceLocatorImpl,接下来我们配置categoryBean

了,由于在categorybean里,需要获得id号,所以用#{param.categoryId}的形式就可以实现了,象需要servicelocator,也在这里通过<value>#{serviceLocatorBean}</value>注入进去了

 

    而在面对最终用户的V层,这里就不详细阐述了,只是提点一下,V层其实和STRUCTS差不多,只不过换了JSF的一些标签,而比如在象提交按钮这里,可以这样写
<h:commandButton value="#{msgs.create}"

                                action="#{categoryBean.createAction}"/>

这里,留意action="#{categoryBean.createAction}",记得吧,categoryBean就是我们刚才写好的前置控制器的javabean,而这里是调用了其中的createAction方法(见前面的代码)。

    我们还要配置faces-navigation.xml文件,这个文件主要是JSF里配置页面的导航,还记得之前我们那个提交成功后的那个success么,其实是来自下面的定义
<navigation-rule>

        <from-view-id>/category/categoryCreate.jsp</from-view-id>

        <navigation-case>

           <description>Create Category Success</description>

           <from-outcome>success</from-outcome>

           <to-view-id>/category/categoryCreate.jsp</to-view-id>

        </navigation-case>

这里,<from-view-id>是说当从/category/categoryCreate.jsp页面进来的请求作如何的处理,<from-outcome>success</from-outcome>就是success了,当success时,要跳转到另外的V层的categorycreate.jsp

 

6、最后的SPRING大组装
   
一切都搞好了,就要把它们装配起来,下面给出applicationcontext.xml文件
<beans>

 

    <!-- ============ Start of PERSISTENCE DEFINITIONS =========== --> 

   

    <!-- DataSource Definition -->

 

//设置datasource

    <bean id="dataSource"

          class="org.springframework.jdbc.datasource.DriverManagerDataSource">

        <property name="driverClassName">

           <value>org.gjt.mm.mysql.Driver</value>

        </property>

        <property name="url">

           <value>jdbc:mysql://localhost:3306/show?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;autoReconnectForPools=true</value>

        </property>

        <property name="username">

           <value>root</value>

        </property>

        <property name="password">

           <value>xxxxx</value>

        </property>

    </bean>

 

//springhibernate的结合

    <!-- Hibernate SessionFactory Definition -->

    <bean id="sessionFactory"

        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

        <property name="mappingResources">

           <list>

               <value>cn/hxex/library/model/Category.hbm.xml</value>

              

           </list>

        </property>   

      

        <property name="hibernateProperties">

           <props>

               <prop key="hibernate.dialect">

                   org.hibernate.dialect.MySQLDialect

               </prop>

               <prop key="hibernate.show_sql">true</prop>

               <prop key="current_session_context_class">thread</prop>

               <prop key="hibernate.cache.provider_class">

                   org.hibernate.cache.EhCacheProvider

               </prop>

               <prop key="connection.pool_size">10</prop>

 

//这里设置hbm2ddlauto,则只需要之前在MYSQL里建好数据库,不需要建表,其他都自动在运行时生成表了

               <prop key="hibernate.hbm2ddl.auto">update</prop>

           </props>

        </property>

      

        <property name="dataSource">

           <ref bean="dataSource"/>

        </property>

    </bean>

   

    <!-- Spring Data Access Exception Translator Defintion -->

    <bean id="jdbcExceptionTranslator"

        class="org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator">

        <property name="dataSource"><ref bean="dataSource"/></property>

    </bean>

   

    <!-- Hibernate Template Defintion -->

    <bean id="hibernateTemplate"

        class="org.springframework.orm.hibernate3.HibernateTemplate">

        <property name="sessionFactory"><ref bean="sessionFactory"/></property>

        <property name="jdbcExceptionTranslator">

           <ref bean="jdbcExceptionTranslator"/>

        </property>

    </bean>

 

    <!-- Category DAO Definition: Hibernate implementation -->

    <bean id="categoryDao"

        class="cn.hxex.library.dao.hibernate.CategoryDaoHibernateImpl">

        <property name="hibernateTemplate">

           <ref bean="hibernateTemplate"/>

        </property>

    </bean>

 

 

   //对事务的定义

    <bean id="transactionManager"

        class="org.springframework.orm.hibernate3.HibernateTransactionManager">

        <property name="sessionFactory">

           <ref local="sessionFactory"/>

        </property>

    </bean>

 

 

    <bean id="categoryServiceTarget"

        class="cn.liao.service.CategoryServiceImpl">

        <property name="categoryDao">

           <ref local="categoryDao"/>

        </property>

    </bean>

   

 

    <bean id="categoryService"

    class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

        <property name="transactionManager">

           <ref local="transactionManager"/>

        </property>

        <property name="target"><ref local="categoryServiceTarget"/></property>

        <property name="transactionAttributes">

           <props>

               <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>

               <prop key="save*">PROPAGATION_REQUIRED</prop>

               <prop key="update*">PROPAGATION_REQUIRED</prop>

               <prop key="delete*">PROPAGATION_REQUIRED</prop>

           </props>

        </property>

    </bean>

    </beans>

 

posted on 2006-08-30 17:57  jackyrong的世界  阅读(1545)  评论(1编辑  收藏  举报