首先,建一个web project,然后添加对hibernate和spring的支持,我们使用的是hibernate3.1和spring2.0,然后导入dwr.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:
生成的代码及配置文件如下:
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(Long id, String name, String isbm) { this.id = id; this.name = name; this.isbm = isbm; } /** *//** full constructor */ public Book(Long id, String name, String isbm, String author) { this.id = id; 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; } public String toString(){ return "[id=" + id + ",name=" + name + ",isbm=" + isbm + ",author=" + author + "]"; } }
edu.jlu.fuliang.dao.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(java.lang.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="java.lang.Long"> <column name="ID" /> <generator class="identity" /> </id> <property name="name" type="java.lang.String"> <column name="NAME" length="20" not-null="true" /> </property> <property name="isbm" type="java.lang.String"> <column name="ISBM" length="20" not-null="true" unique="true" /> </property> <property name="author" type="java.lang.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> <prop key="hibernate.show_sql"> true </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层: edu.jlu.fuliang.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); } edu.jlu.fuliang.service.impl.BookManageServiceImpl.java: package edu.jlu.fuliang.serviceImpl; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.jlu.fuliang.dao.BookDAO; import edu.jlu.fuliang.domain.Book; import edu.jlu.fuliang.service.BookManageService; public class BookManageServiceImpl implements BookManageService{ private static final Log log = LogFactory.getLog(BookManageServiceImpl.class); 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) { log.info(book); bookDAO.attachDirty(book); } public BookDAO getBookDAO() { return bookDAO; } public void setBookDAO(BookDAO bookDAO) { this.bookDAO = bookDAO; } } 然后我们来配置Service和事务: 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="sessionFactory"/> </bean> <bean id="bookManageService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="transactionManager"/> <property name="target" ref="bookManageServiceTarget"/> <property name="transactionAttributes"> <props> <prop key="add*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> </beans> 最后我们来把dwr整合进来: 我们在web.xml添加ContextLoaderListener来加载applicationContext-db.xml,applicationContext-dao.xm,applicationContext-service.xml,以及配置DwrServlet: 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"> <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> <servlet> <servlet-name>dwr-invoker</servlet-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-pattern> </servlet-mapping> </web-app>在dwr.xml中配制bean的创建方式,类型转换,以及Service要暴露的接口: <dwr> <allow> <convert converter="bean" match="edu.jlu.fuliang.domain.Book"/> <create creator="spring" javascript="BookManageService" > <param name="beanName" value="bookManageService"/> <include method="getAllBooks"/> <include method="getBookByName"/> <include method="updateBook"/> <include method="addBook"/> <include method="deleteBook"/> </create> </allow> </dwr>
最后,我们编写jsp页面index.jsp: <html> <head><title>DWR test</title> <script type='text/javascript' src='/DWRTest/dwr/interface/BookManageService.js'></script> <script type='text/javascript' src='/DWRTest/dwr/engine.js'></script> <script type='text/javascript' src='/DWRTest/dwr/util.js'></script> <script type="text/javascript"> var bookCache = ...{}; var currentBook = null; function loadAllBooks(){ BookManageService.getAllBooks(handleGetAllBooks,handleGetAllBooksError); } function handleGetAllBooks(books){ dwr.util.removeAllRows("booksBody",{ filter:function(tr) ...{ return (tr.id != "pattern"); }}); var book,id; for(var i = 0; i < books.length; i++){ book = books[i]; id = book.id; dwr.util.cloneNode("pattern", { idSuffix:id }); dwr.util.setValue("t_name" + id, book.name); dwr.util.setValue("t_isbm" + id, book.isbm); dwr.util.setValue("t_author" + id,book.author); $("pattern" + id).style.display = "block"; bookCache[id] = book; } } function handleGetAllBooksError(msg){ alert("Error: " + msg); } function addBook(){ var book = ...{name:null,isbm:null,author:null}; dwr.util.getValues(book); dwr.engine.beginBatch(); BookManageService.addBook(book); loadAllBooks(); dwr.engine.endBatch(); } function editBook(btId){ currentBook = bookCache[btId.substring(4)]; dwr.util.setValues(currentBook); } function updateBook(){ var book = {id:null,name:null,isbm:null,author:null}; dwr.util.getValues(book); book.id = currentBook.id; BookManageService.updateBook(book,handleUpdateBook,handleUpdateBookError); } function handleUpdateBook(){ alert("Update book successfully!"); loadAllBooks(); } function handleUpdateBookError(msg){ alert("Error: " + msg); } function deleteBook(btId){ var i = confirm("Are you sure to delete the book?"); if(i == true) BookManageService.deleteBook(btId.substring(6),handleDeleteBook,handleDeleteBookError); } function handleDeleteBook(){ alert("The book has been delete successfully!"); loadAllBooks(); } function handleDeleteBookError(msg){ alert("Error: " + msg); } </script> </head> <body onload="loadAllBooks()"> <div> <h2>Add book</h2> <table> <tr> <td>Name:</td><td><input type="text" id="name"></td> </tr> <tr> <td>ISBN:</td> <td><input type="text" id="isbm"></td> </tr> <tr> <td>Author:</td> <td><input type="text" id="author"></td> </tr> <tr> <td colspan="2"> <input type="button" id="add" value="Add" onclick="addBook()"> <input type="button" id="update" value="Update" onclick="updateBook()"> </td> </tr> </table> </div> <hr> <div id="list"> <table border="1"> <thead> <tr> <th>Name</th> <th>ISBN</th> <th>Author</th> <th>Action</th> </tr> </thead> <tbody id="booksBody"> <tr id="pattern" style="display:none;"> <td> <span id="t_name"></span> </td> <td> <span id="t_isbm"></span> </td> <td> <span id="t_author"></span> </td> <td> <span id="action"> <input id="edit" type="button" value="Edit" onclick="editBook(this.id)"/> <input id="delete" type="button" value="Delete" onclick="deleteBook(this.id)"/> </span> </td> </tr> </tbody> </table> </div> </body>