Struts 2与Hibernate整合

一、输入界面:input.jsp与控制器
<%@ page c language="java"%>

<%@ taglib prefix="s" uri="/struts-tags"%>
<HTML>
<HEAD>
<TITLE>
添加新家长</TITLE>
</HEAD>
<BODY>
<s:form action="add.action">
<s:textfield name="name" label="
父亲名字:"/>
<s:textfield name="gender" label="
性别:"/>
<s:textfield name="sonName" label="
儿子名:"/>
<s:textfield name="sonAge" label="
儿子年龄:"/>
<s:submit value="
提交"/>
</s:form>
</BODY>
</HTML>

struts 2
配置文件:struts.xml
<?xml version="1.0" encoding="GBK"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.i18n.encoding" value="GBK"/>
<constant name="struts.custom.i18n.resources" value="messageResource"/>

<package name="lee" extends="struts-default">
  <action name="add" class="org.yeeku.action.AddPersonAndSon">
   <result>welcome.html</result>
  </action>
</package>

</struts>

Action类(控制器):

package org.yeeku.action;
import com.opensymphony.xwork2.ActionSupport;
import javax.servlet.http.*;
import org.yeeku.service.*;
import org.yeeku.factory.*;

public class AddPersonAndSon extends ActionSupport
{
        private String name;
        private String gender;
        private String sonName;
        private int sonAge;
       
    public String execute()throws Exception
    {
        String[] sonNames = {sonName};
        int[] sonAges = {sonAge};
        //
通过业务逻辑工厂取得业务逻辑组件
        PersonService ps = (PersonService)AppFactory.instance().getApp("personService");        //
调用业务逻辑方法处理用户请求
        ps.createPersonAndSon(name , gender , sonNames , sonAges);
        return SUCCESS;               
    }
        public void setName(String name)
        {
                this.name = name;
        }
        public String getName()
        {
                 return this.name;
        }
        public void setGender(String gender)
        {
                this.gender = gender;
        }
        public String getGender()
        {
                 return this.gender;
        }
        public void setSonName(String sonName)
        {
                this.sonName = sonName;
        }
        public String getSonName()
        {
                 return this.sonName;
        }
        public void setSonAge(int sonAge)
        {
                this.sonAge = sonAge;
        }
        public int getSonAge()

{
                 return this.sonAge;
        }
}
我们并不在Struts 2Action中调用Hibernate APIAction也不直接依赖于任何业务逻辑组件,而只是依赖于业务逻辑工厂类,面向业务逻辑组件接口编程。这个过程是如何实现的请继续往下看。运行图:

      
所填数据将会保存到数据库struts2hibernate中,这个数据库请事先在MYSQL中创建。

 

从数据中可以看到刚提交的数据:

 

二、持久层设计
包括Hibernate持久化访问所需的POHibernate映射文件。
父亲实体类代码:
package org.yeeku.model;

import java.util.*;

public class Person{       

private int id;       

private String name;       

private String gender;   

private Set< Son> sons = new HashSet< Son>();        

public Person()        {        }                       

public void setId(int id) {              

     this.id = id;       

  }       

public void setName(String name) {            

this.name = name;       

}       

public void setGender(String gender) {     

           this.gender = gender;     

    }   

public void setSons(Set sons)    {    

this.sons = sons;  

}       

public int getId() {      

          return (this.id);     

    }       

 public String getName() {      

          return (this.name);       

  }       

 public String getGender() {         

        return (this.gender);       

  }

 

public Set< Son> getSons()

    {

        return this.sons;

    }

}

对应的映射文件:Person.hbm.xml

 

<?xml version="1.0" encoding="GBK"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.yeeku.model">

<!-- 每个class元素映射一个持久化类 -->

<class name="Person" table="person">

  <id name="id">

    <generator class="identity"/>

  </id>

  <property name="name"/>

  <property name="gender"/>

  <set name="sons" inverse="true">

    <key column="person_id"/>

    <one-to-many class="Son"/>

  </set>

</class>

</hibernate-mapping>

 

上面的Person实体存在一个一对多的关联实体:Son,代码如下:

 

 

package org.yeeku.model;

import java.io.Serializable;

public class Son implements Serializable

{

    private int id;

    private String sonName;

    private int sonAge;

    private Person parent;

   

    public Son()

    {

    }

       

    public Son(String sonName , int sonAge)

    {

        this.sonName = sonName;

        this.sonAge = sonAge;

    }

        public void setSonName(String sonName) {

                this.sonName = sonName;

        }

        public void setSonAge(int sonAge) {

                this.sonAge = sonAge;

        }

    public void setId(int id)

    {

        this.id = id;

    }

    public void setParent(Person p)

    {

        this.parent = p;

    }

        public String getSonName() {

                return (this.sonName);

        }

        public int getSonAge() {

                return (this.sonAge);

        }

    public int getId()

    {

        return id;

    }

    public Person getParent()

    {

        return parent;

    }

}

 

对应的映射文件:Son.hbm.xml

<?xml version="1.0" encoding="GBK"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.yeeku.model">

  <!-- 每个class元素映射一个持久化类 -->

  <class name="Son" table="son">

   <id name="id">

    <generator class="identity"/>

   </id>

  <property name="sonName"/>

  <property name="sonAge"/>

  <many-to-one name="parent" column="person_id" not-null="true"/>

</class>

</hibernate-mapping>

 

 

 

最后是Hibernate配置文件:hibernate.cfg.xml,指定了数据库连接信息和连接池等。

 

<?xml version="1.0" encoding="GBK"?>

<!DOCTYPE hibernate-configuration PUBLIC

"-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

 

<hibernate-configuration>

 

<session-factory>

 

<!-- Database connection settings -->

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<property name="connection.url">jdbc:mysql://localhost/struts2hibernate</property>

<property name="connection.username">root</property>

<property name="connection.password"></property>

 

<!-- C3P0 connection pool -->

<property name="hibernate.c3p0.max_size">500</property>

<property name="hibernate.c3p0.min_size">2</property>

<property name="hibernate.c3p0.timeout">5000</property>

<property name="hibernate.c3p0.max_statements">100</property>

<property name="hibernate.c3p0.idle_test_period">3000</property>

<property name="hibernate.c3p0.acquire_increment">2</property>

<property name="hibernate.c3p0.validate">true</property>

 

<!-- SQL dialect -->

<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

 

<!-- Echo all executed SQL to stdout -->

<property name="show_sql">false</property>

 

<!-- Drop and re-create the database schema on startup -->

<property name="hbm2ddl.auto">update</property>

 

<mapping resource="Person.hbm.xml"/>

<mapping resource="Son.hbm.xml"/>

 

</session-factory>

 

</hibernate-configuration>

 

 

三、DAO层设计

由两个DAO组件和一个DAO工厂组成,两个DAO组件的代码大致相同,这里以Person实体对应的DAO组件为例来介绍DAO组件

的实现。

 

1Dao接口

 

package org.yeeku.dao.base;

 

public interface Dao

{

}

 

2PersonDao接口

package org.yeeku.dao;

import org.hibernate.Session;

import org.yeeku.model.*;

import org.yeeku.dao.base.Dao;

 

import java.util.*;

 

public interface PersonDao extends Dao {

//包括四个CRUD操作

void save(Session sess , Person p);

void delete(Session sess , Person p);

void delete(Session sess , int id);

void update(Session sess , Person p);

}

 

 

3Dao组件的实现类PersonDaoImpl.java

 

 

package org.yeeku.dao.impl;

import org.hibernate.Session;

import org.yeeku.model.*;

import org.yeeku.dao.*;

import java.util.*;

public class PersonDaoImpl implements PersonDao

{

    public void save(Session sess , Person p)

    {

        sess.save(p);

    }

    public void delete(Session sess , Person p)

    {

        sess.delete(p);

    }

    public void delete(Session sess , int id)

    {

        sess.delete(sess.get(Person.class , new Integer(id)));

    }

    public void update(Session sess , Person p)

    {

        sess.update(p);

    }

}

4DAO工厂

DAO工厂是一个简单的工厂类,该工厂类使用XML文件管理DAO组件,采用XML配置文件管理DAO组件可以让DAO工厂灵活

管理所有DAO组件,避免每次增加DAO组件时都要修改代码。这种DAO组件配置文件的代码结构如下:(daoContext.xml

 

<?xml version="1.0" encoding="GBK"?>

<daoContext>

  <dao id="sonDao" class="org.yeeku.dao.impl.SonDaoImpl"/>

  <dao id="personDao" class="org.yeeku.dao.impl.PersonDaoImpl"/>

</daoContext>

 

可以看出在其中配置了两个DAO组件,因为每个DAO组件在JAVA EE应用中仅需要一个实例就足够了,因此DAO工厂类提供一个

缓存池来缓存每一个DAO实例,并负责在应用启动时创建所有的DAO组件。代码如下:

 

package org.yeeku.factory;

import org.yeeku.dao.base.Dao;

import org.yeeku.dao.*;

import org.yeeku.dao.impl.*;

import org.yeeku.consttool.*;

import org.dom4j.*;

import org.dom4j.io.*;

import java.util.*;

import java.io.*;

public class DaoFactory

{

    private Map daoMap = new HashMap();

    private static DaoFactory df;

    private DaoFactory()throws Exception

    {

        Document doc = new SAXReader().read(new File(ConstantsUtil.realPath + "//daoContext.xml"));

        Element root = doc.getRootElement();

        List el =  root.elements();

        for (Iterator it = el.iterator();it.hasNext() ; )

        {

            Element em = (Element)it.next();

            String id = em.attributeValue("id");

            String impl = em.attributeValue("class");

            Class implClazz = Class.forName(impl);//通过反射,根据类名创建DAO组件的实例

            Dao d = (Dao)implClazz.newInstance();

            daoMap.put(id , d); //将创建的组件放入缓存池中          

        }

    }

 

 

public static DaoFactory instance()throws Exception

    {

        if (df == null)

        {

            df = new DaoFactory();

        }

        return df;

    }

    public Dao getDao(String id)

    {

        return daoMap.get(id);

    }

}

系统每增加一个DAO组件时,无需要修改任何代码,仅仅需要在daoContext.xml文件中增加配置即可。

 

四、业务逻辑层设计

 

  业务逻辑组件代码无需与DAO实现类耦合,业务逻辑组件的代码面向DAO组件的接口编程,将业务逻辑组件和DAO组件的耦合

降低到接口层次,业务逻辑层组件设计与DAO层的设计思路大致相同,只是DAO组件实现的是数据库访问功能,而业务逻辑

组件实现的是业务逻辑功能。

 

1、业务逻辑组件接口代码

 

package org.yeeku.service;

import org.yeeku.exception.PersonException;

public interface PersonService {//增加父亲和多个子女

  void createPersonAndSon(String name , String gender , String[] sonName , int[] sonAge) throws PersonException;

}

 

2、业务逻辑组件的实现类

package org.yeeku.service.impl;

import org.yeeku.service.*;

import org.yeeku.dao.*;

import org.yeeku.factory.*;

import org.yeeku.model.*;

import org.yeeku.tools.*;

import org.yeeku.exception.PersonException;

import org.hibernate.Session;

import org.hibernate.Transaction;

public class PersonServiceImpl implements PersonService{   

public void createPersonAndSon(String name , String gender , String[] sonName , int[] sonAge)        throws PersonException    {       

try        {   //业务逻辑组件依赖于DAO工厂,从工厂中取出两个DAO组件

PersonDao pd = (PersonDao)DaoFactory.instance().getDao("personDao");           

SonDao sd = (SonDao)DaoFactory.instance().getDao("sonDao");

 

            //使用HibernateUtil打开Hibernate Session           

Session s = HibernateUtil.currentSession();            

Transaction tx = s.beginTransaction();           

Person p = new Person();           

p.setName(name);           

p.setGender(gender);               

pd.save(s , p);           

for (int i = 0 ; i < sonName.length  ; i++ )            {               

Son son = new Son(sonName , sonAge);               

son.setParent(p);               

sd.save(s, son);           

}           

tx.commit();            

HibernateUtil.closeSession();       

}       

catch (Exception e) {           

e.printStackTrace();            

throw new PersonException("业务异常");      

}   

}

}

 

 

本实例中的业务逻辑组件也采用XML配置文件进行管理,业务逻辑组件工厂一样根据XML配置文件来加载系统中的业务逻辑组件。

业务逻辑组件的配置文件如下:(appContext.xml

 

<?xml version="1.0" encoding="GBK"?>

<appContext>

  <app id="personService" class="org.yeeku.service.impl.PersonServiceImpl"/>

</appContext>

 

业务逻辑组件工厂根据该文件来初始化所有业务逻辑组件,并将业务逻辑组件放入缓存池中,让控制器Action仅依赖于业务逻辑组件工厂,与业务逻辑组件的耦合降低到接口层次。业务逻辑组件的工厂类代码如下:

 

package org.yeeku.factory;

import org.yeeku.dao.base.Dao;

import org.yeeku.dao.*;

import org.yeeku.dao.impl.*;

import org.yeeku.service.*;

import org.yeeku.service.impl.*;

import org.yeeku.consttool.*;

import org.dom4j.*;

import org.dom4j.io.*;

import java.util.*;

import java.io.*;

public class AppFactory

{

    private Map appMap = new HashMap();

    private static AppFactory df;

    private AppFactory()throws Exception

    {

        Document doc = new SAXReader().read(new File(ConstantsUtil.realPath + "//appContext.xml"));

        Element root = doc.getRootElement();

        List el =  root.elements();

        for (Iterator it = el.iterator();it.hasNext() ; )

        {

            Element em = (Element)it.next();

            String id = em.attributeValue("id");

            String impl = em.attributeValue("class");

            Class implClazz = Class.forName(impl);//用反射根据类名创建业务逻辑组件

            Object d = implClazz.newInstance();

            appMap.put(id , d);  //将业务逻辑组件放入缓存池中         

        }

    }

    public static AppFactory instance()throws Exception

    {

        if (df == null)

        {

            df = new AppFactory();

        }

        return df;

    }

    public Object getApp(String id)//根据业务逻辑组件的ID获取业务逻辑组件

    {

        return appMap.get(id);//直接从缓存池中取出业务逻辑组件

    }

}

 

系统每增加一个业务组件时,无需要修改任何代码,仅仅需要在appContext.xml文件中增加配置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值