您的位置:首页 > 编程语言 > Java开发

spring+hibernate+其他应用组装心得小结

2006-08-30 17:57 513 查看
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对象的实例,然后通过spring的WebApplicationContextUtils类的getRequiredWebApplicationContext得到applicationcontext对象的实例,最后通过ApplicationContext对象的实例得到这些业务方法类的实例

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

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

public class CategoryBean extends BaseBean

{

。。。。。一系列的SET,GET方法

//增加产品的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、我们接着要写JSF的faces-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&characterEncoding=utf8&autoReconnect=true&autoReconnectForPools=true</value>

</property>

<property name="username">

<value>root</value>

</property>

<property name="password">

<value>xxxxx</value>

</property>

</bean>

//spring和hibernate的结合

<!-- 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>

//这里设置hbm2ddl为auto,则只需要之前在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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: