我们沿用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操作了.
原贴地址:
http://blog.youkuaiyun.com/fuliangliang/archive/2007/09/26/1801178.aspx