我们沿用Spring+Hibernate+DWR的例子,做一个Ajax+Struts2.0+Spring+Hibernate整合,许多步骤大体相似,
我就直接搬过来了:
首先,建一个web project,然后添加对hibernate和spring的支持,我们使用的是hibernate3.2和spring2.0,然后导入xwork-2.0.3.jar struts2-core-2.0.8.jar struts2-spring-plugin-2.0.8.jar ognl-2.6.11.jar freemarker-2.3.8.jar commons-logging-api-1.1.jar和commons-pool-1.3.jar(不知道myeclipse怎么搞的,添加Spring功能支持的时候就有了commons-dbcp.jar,居然没有其依赖的commons-pool-x.jar,只好单独添加了,另外,需要将Spring2.0 AOP Liberaries里的asm2.2.3.jar删除,因为好像和Hiberate中的生成代理用的asm.jar冲突,我把Spring2.0 AOP Liberaries排到最后仍然有冲突,所以只好删掉了,不知道大家遇到过这种情况么)。
我们使用myeclise自带的Derby数据库,在里面建一个表BOOK:
ID bigint primary key,autoincrement
NAME varchar(20)
ISBM varchar(20)
AUTHOR varchar(15)
然后利用myeclipse的hibernate反向工程生成领域模型:Book.java, DAO:BookDAO.jar, Book 的映射文件Book.hbm.xml:
生成的代码及配置文件如下:
Book.java:
package edu.jlu.fuliang.domain;


/** *//**
* Book generated by MyEclipse Persistence Tools
*/


public class Book implements java.io.Serializable {

// Fields

private long id;
private String name;
private String isbm;
private String author;

// Constructors


/** *//** default constructor */

public Book() {
}


/** *//** minimal constructor */

public Book(String name, String isbm) {
this.name = name;
this.isbm = isbm;
}


/** *//** full constructor */

public Book(String name, String isbm, String author) {
this.name = name;
this.isbm = isbm;
this.author = author;
}

// Property accessors


public long getId() {
return this.id;
}


public void setId(long id){
this.id = id;
}


public String getName() {
return this.name;
}


public void setName(String name) {
this.name = name;
}


public String getIsbm() {
return this.isbm;
}


public void setIsbm(String isbm) {
this.isbm = isbm;
}


public String getAuthor() {
return this.author;
}


public void setAuthor(String author) {
this.author = author;
}

}
BookDAO.java:
package edu.jlu.fuliang.dao;

import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.LockMode;
import org.springframework.context.ApplicationContext;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import edu.jlu.fuliang.domain.Book;


/** *//**
* Data access object (DAO) for domain model class Book.
*
* @see edu.jlu.fuliang.domain.Book
* @author MyEclipse Persistence Tools
*/


public class BookDAO extends HibernateDaoSupport ...{
private static final Log log = LogFactory.getLog(BookDAO.class);
// property constants
public static final String NAME = "name";
public static final String ISBM = "isbm";
public static final String AUTHOR = "author";


protected void initDao() ...{
// do nothing
}


public void save(Book transientInstance) ...{
log.debug("saving Book instance");

try ...{
getHibernateTemplate().save(transientInstance);
log.debug("save successful");

} catch (RuntimeException re) ...{
log.error("save failed", re);
throw re;
}
}


public void delete(Book persistentInstance) ...{
log.debug("deleting Book instance");

try ...{
getHibernateTemplate().delete(persistentInstance);
log.debug("delete successful");

} catch (RuntimeException re) ...{
log.error("delete failed", re);
throw re;
}
}


public Book findById(Long id) ...{
log.debug("getting Book instance with id: " + id);

try ...{
Book instance = (Book) getHibernateTemplate().get(
"edu.jlu.fuliang.domain.Book", id);
return instance;

} catch (RuntimeException re) ...{
log.error("get failed", re);
throw re;
}
}


public List findByExample(Book instance) ...{
log.debug("finding Book instance by example");

try ...{
List results = getHibernateTemplate().findByExample(instance);
log.debug("find by example successful, result size: "
+ results.size());
return results;

} catch (RuntimeException re) ...{
log.error("find by example failed", re);
throw re;
}
}


public List findByProperty(String propertyName, Object value) ...{
log.debug("finding Book instance with property: " + propertyName
+ ", value: " + value);

try ...{
String queryString = "from Book as model where model."
+ propertyName + "= ?";
return getHibernateTemplate().find(queryString, value);

} catch (RuntimeException re) ...{
log.error("find by property name failed", re);
throw re;
}
}


public List findByName(Object name) ...{
return findByProperty(NAME, name);
}


public List findByIsbm(Object isbm) ...{
return findByProperty(ISBM, isbm);
}


public List findByAuthor(Object author) ...{
return findByProperty(AUTHOR, author);
}


public List findAll()...{
log.debug("finding all Book instances");

try ...{
String queryString = "from Book";
return getHibernateTemplate().find(queryString);

} catch (RuntimeException re) ...{
log.error("find all failed", re);
throw re;
}
}


public Book merge(Book detachedInstance) ...{
log.debug("merging Book instance");

try ...{
Book result = (Book) getHibernateTemplate().merge(detachedInstance);
log.debug("merge successful");
return result;

} catch (RuntimeException re) ...{
log.error("merge failed", re);
throw re;
}
}


public void attachDirty(Book instance) ...{
log.debug("attaching dirty Book instance");

try ...{
getHibernateTemplate().saveOrUpdate(instance);
log.debug("attach successful");

} catch (RuntimeException re) ...{
log.error("attach failed", re);
throw re;
}
}


public void attachClean(Book instance) ...{
log.debug("attaching clean Book instance");

try ...{
getHibernateTemplate().lock(instance, LockMode.NONE);
log.debug("attach successful");

} catch (RuntimeException re) ...{
log.error("attach failed", re);
throw re;
}
}


public static BookDAO getFromApplicationContext(ApplicationContext ctx) ...{
return (BookDAO) ctx.getBean("BookDAO");
}
}
Book.hbm.xml:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="edu.jlu.fuliang.domain.Book" table="BOOK" schema="CLASSICCARS">
<id name="id" type="long">
<column name="ID" />
<generator class="identity"></generator>
</id>
<property name="name" type="string">
<column name="NAME" length="20" not-null="true" />
</property>
<property name="isbm" type="string">
<column name="ISBM" length="20" not-null="true" unique="true" />
</property>
<property name="author" type="string">
<column name="AUTHOR" length="15" />
</property>
</class>
</hibernate-mapping>
下面我们配置一下Spring,我们把applicationContext.xml分成了三个,分别是applicationContext-db.xml,applicationContext-dao.xml,applicationContext-service.我们看看如何配置:
applicationContext-db.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="org.apache.derby.jdbc.ClientDriver">
</property>
<property name="url"
value="jdbc:derby://localhost:1527/myeclipse;create=true">
</property>
<property name="username" value="classiccars"></property>
<property name="password" value="myeclipse"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.DerbyDialect
</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>edu/jlu/fuliang/domain/Book.hbm.xml</value></list>
</property>
</bean>
</beans>

applicationContext-dao.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="bookDAO" class="edu.jlu.fuliang.dao.BookDAO">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>

</beans>
接下来我们来写我们的Service层:
BookManageService.java:
package edu.jlu.fuliang.service;
import java.util.List;

import edu.jlu.fuliang.domain.Book;


public interface BookManageService ...{
public List<Book> getAllBooks();
public List<Book> getBookByName(String name);
public void updateBook(Book book);
public void addBook(Book book);
public void deleteBook(long id);
public Book getBookById(Long id);
}

BookManageServiceImpl.java:
package edu.jlu.fuliang.serviceImpl;

import java.util.List;

import edu.jlu.fuliang.dao.BookDAO;
import edu.jlu.fuliang.domain.Book;
import edu.jlu.fuliang.service.BookManageService;


public class BookManageServiceImpl implements BookManageService...{
private BookDAO bookDAO;
@Override

public void addBook(Book book) ...{
bookDAO.save(book);
}

@Override

public void deleteBook(long id) ...{
Book book = bookDAO.findById(id);
bookDAO.delete(book);
}

@Override

public List<Book> getAllBooks() ...{
return bookDAO.findAll();
}

@Override

public List<Book> getBookByName(String name) ...{
return bookDAO.findByName(name);
}

@Override

public void updateBook(Book book) ...{
bookDAO.attachDirty(book);
}

public void setBookDAO(BookDAO bookDAO)...{
this.bookDAO = bookDAO;
}

@Override

public Book getBookById(Long id) ...{
return bookDAO.findById(id);
}
}
然后写一个struts的Action,他完全是一个POJO:
package edu.jlu.fuliang.action;

import java.util.List;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.Preparable;

import edu.jlu.fuliang.domain.Book;
import edu.jlu.fuliang.service.BookManageService;


public class BookAction implements Preparable...{
private BookManageService bookManageService;
private List<Book> books;
private Book book;
private Long id;

public String execute()...{
this.books = bookManageService.getAllBooks();
return Action.SUCCESS;
}

public String save()...{
this.bookManageService.addBook(book);
return execute();
}

public void prepare()throws Exception...{
if(id != null)
book = bookManageService.getBookById(id);
}

public String remove()...{
bookManageService.deleteBook(id);
return execute();
}

public List<Book> getBooks() ...{
return books;
}

public void setBooks(List<Book> books) ...{
this.books = books;
}

public Book getBook() ...{
return book;
}

public void setBook(Book book) ...{
this.book = book;
}

public Long getId() ...{
return id;
}

public void setId(Long id) ...{
this.id = id;
}

public void setBookManageService(BookManageService bookManageService) ...{
this.bookManageService = bookManageService;
}
}

然后我们来配置Service、事务以及struts的action:
applicationContext-service.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="bookManageServiceTarget" class="edu.jlu.fuliang.serviceImpl.BookManageServiceImpl">
<property name="bookDAO">
<ref bean="bookDAO"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="bookManageService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="target">
<ref bean="bookManageServiceTarget"/>
</property>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
/* configure struts action as bean in spring*/
<bean id="bookAction" scope="prototype" class="edu.jlu.fuliang.action.BookAction">
<property name="bookManageService">
<ref bean="bookManageService"/>
</property>
</bean>
</beans>
配置struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!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.objectFactory" value="spring"/>
<constant name="struts.devMode" value="true"/>
<package name="book" extends="struts-default">
<action name="list" method="execute" class="bookAction">
<result>list.jsp</result>
<result name="input">list.jsp</result>
</action>
<action name="remove" method="remove" class="bookAction">
<result>list.jsp</result>
<result name="input">list.jsp</result>
</action>
<action name="save" method="save" class="bookAction">
<result>list.jsp</result>
<result name="input">list.jsp</result>
</action>
</package>
</struts>
配置WEB-INF/web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<filter>
<filter-name>struts</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
</web-app>
配置一下log:
# This is the configuring for logging displayed in the Application Server
# log4j.rootCategory=INFO, stdout,logfile
log4j.rootCategory=DEBUG, A1

#console configure
log4j.appender.A1 = org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout = org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern = %-4r [%t] %-5p %c %x - %m%n

#stdout configure
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p [%c] - <%m>%n

#logfile configure
log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logfile.File=log4j.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern= %d %p [%c] - <%m>%n

# Control logging for other open source packages
# Changing the log level to DEBUG when debug
log4j.logger.org.springframework=ERROR
log4j.logger.org.springframework.web.context.support.XmlWebApplicationContext=INFO
log4j.logger.org.hibernate=ERROR
log4j.logger.org.hibernate.cfg.HbmBinder=INFO
log4j.logger.org.hibernate.SQL=ERROR
log4j.logger.org.hibernate.cache=ERROR
log4j.logger.org.hibernate.transaction=INFO
log4j.logger.net.sf.ehcache=ERROR
log4j.logger.org.apache.struts=ERROR
log4j.logger.com.htxx.service.dao=INFO
log4j.logger.org.apache.commons=INFO
log4j.logger.org.directwebremoting=INFO
写两个页面index.jsp,list.jsp,使用了Ajax--dojo::
index.jsp:

<%...@ taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<s:head theme="ajax" debug="true"/>

<script type="text/javascript">...

dojo.event.topic.subscribe("/save", function(data, type, request) ...{

if(type == "load") ...{
dojo.byId("id").value = "";
dojo.byId("name").value = "";
dojo.byId("isbm").value = "";
dojo.byId("author").value = "";
}
});


dojo.event.topic.subscribe("/edit", function(data, type, request) ...{

if(type == "before") ...{
var id = data.split("_")[1];
var tr = dojo.byId("row_"+id);
var tds = tr.getElementsByTagName("td");

dojo.byId("id").value = id;
dojo.byId("name").value = dojo.string.trim(dojo.dom.textContent(tds[0]));
dojo.byId("isbm").value = dojo.string.trim(dojo.dom.textContent(tds[1]));
dojo.byId("author").value = dojo.string.trim(dojo.dom.textContent(tds[1]));
}
});
</script>
</head>
<body>
<s:url action="list" id="descrsUrl"/>

<div style="width: 300px;border-style: solid">
<div style="text-align: right;">
<s:a theme="ajax" notifyTopics="/refresh">Refresh</s:a>
</div>
<s:div id="books" theme="ajax" href="%{descrsUrl}" loadingText="Loading..." listenTopics="/refresh"/>
</div>

<br/>

<div style="width: 300px;border-style: solid">
<p>Book Data</p>
<s:form action="save" validate="true">
<s:textfield id="id" name="person.id" cssStyle="display:none"/>
<s:textfield id="name" label="Name" name="book.name"/>
<s:textfield id="isbm" label="ISBN" name="book.isbm"/>
<s:textfield id="author" label="Author" name="book.author"/>
<s:submit theme="ajax" targets="books" notifyTopics="/save"/>
</s:form>
</div>
</body>
</html>
list.jsp:

<%...@ taglib prefix="s" uri="/struts-tags"%>
<p>Books</p>
<s:if test="books.size > 0">
<table>
<s:iterator value="books">
<tr id="row_<s:property value="id"/>">
<td>
<s:property value="name" />
</td>
<td>
<s:property value="isbm" />
</td>
<td>
<s:property value="author"/>
</td>
<td>
<s:url id="removeUrl" action="remove">
<s:param name="id" value="id" />
</s:url>
<s:a href="%{removeUrl}" theme="ajax" targets="books">Remove</s:a>
<s:a id="a_%{id}" theme="ajax" notifyTopics="/edit">Edit</s:a>
</td>
</tr>
</s:iterator>
</table>
</s:if>
在浏览器中输入地址,我们就可以在一个页面进行CRUD操作了.