ServletFilter+ThreadLocal+DAO,10分钟Hibernate再体验
Ibatis好像也有类似的功能工具包:当时没有理解
ServletFilter+ThreadLocal+DAO,10分钟Hibernate再体验
作者:xanada
整理人:smallduzi
版权声明:本文严禁转载,如有转载请求,请和作者联系
论坛上关于如何管理session的讨论已经很多了,但是因为没有一个完整的可以run的例子,很多人在这点上还是感到迷惑。今天有时间,就把自己做过的一个小例子贴出来,希望能节省后来者的学习时间。
这个例子实现了:
1. 用ThreadLocal管理session,保证了在一个thread中使用同一个session(connection)
2. 在ServletFilter中initSessionFactory和closeSession,保证一个应用中只有一个SessionFactory并做到了session-per-request, instead of session-per-operation
3. DAO的粗略实现
菜菜鸟可以先参考一下本人写的第一个例子,Tomcat+Mysql+UltraEdit,10分钟Hibernate初体验
1. 保证你的Mysql工作正常。
CREATE TABLE cat ( cat_id varchar(20) NOT NULL, name varchar(20) NOT NULL, sex char(1), weight float, PRIMARY KEY (cat_id) ); insert cat values('1', 'ada', 'F', 5); insert cat values('2', 'belinda', 'F', 10); commit;
2. 保证你的Tomcat工作正常。Then stop Tomcat。
在{TOMCAT_HOME}\conf\server.xml中加入:
<Context path="/hellohibernate" docBase="hellohibernate" reloadable="true"> <Resource name="jdbc/hellohibernate" scope="Shareable" type="javax.sql.DataSource"/> <ResourceParams name="jdbc/hellohibernate"> <parameter> <name>factory</name> <value>org.apache.commons.dbcp.BasicDataSourceFactory</value> </parameter> <!-- DBCP database connection settings --> <parameter> <name>url</name> <value>jdbc:mysql://localhost:3306/test</value> </parameter> <parameter> <name>driverClassName</name><value>com.mysql.jdbc.Driver</value> </parameter> <parameter> <name>username</name> <value>yourusername</value> </parameter> <parameter> <name>password</name> <value>yourpassword</value> </parameter> <!-- DBCP connection pooling options --> <parameter> <name>maxWait</name> <value>3000</value> </parameter> <parameter> <name>maxIdle</name> <value>100</value> </parameter> <parameter> <name>maxActive</name> <value>10</value> </parameter> </ResourceParams> </Context>
3. 将附件hellohibernate.zip更名为hellohibernate.war,扔到{TOMCAT_HOME}\webapps下,重新启动Tomcat。
4. 你会发现hellohibernate已经被自动部署了,copy下列文件到{TOMCAT_HOME}\webapps\hellohibernate\WEB-INF\lib下:
hibernate2.jar
log4j-1.2.8.jar
commons-collections-2.1.jar
commons-logging-1.0.3.jar
dom4j-1.4.jar
cglib-2.0-rc2.jar
odmg-3.0.jar
ehcache-0.6.jar
jta.jar
(其实我本可以把它们打包到war里面的,但是这样war文件就到了2M,现在才12K)
5. http://localhost:9090/hellohibernate/servlet/HelloHibernateServlet
参看HelloHibernateServlet.java,你会发现我们做了以下操作:
a. create了罗宾猫,得力猫和胖子猫
b. delete了阿达猫和柏林达猫
c. update了胖子猫
d. select了所有猫
6. 代码分析
web.xml
<filter> <filter-name>HelloHibernateFilter</filter-name> <filter-class>com.xanada.HelloHibernateFilter</filter-class> </filter> <filter-mapping> <filter-name>HelloHibernateFilter</filter-name> <url-pattern>/*</url-pattern> //Filter对所有的请求都响应 </filter-mapping>
Hello Hibernate Filter.java
//init在整个servlet的生命周期中只做一次,在这里它初始化了SessionFactory,从而保证了SessionFactory在整个进程中只有一个实例 public void init(FilterConfig filterConfig) throws ServletException { try { HibernateSessionFactory.init(); } catch (HibernateException e) { e.printStackTrace(); } } //session是从DAO中得到的,但是做完一个operation后并不close,而是在整个request完成后在doFilter的finally里面close public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException { try { chain.doFilter(req, res); } finally { try { HibernateSessionFactory.closeSession(); } catch (HibernateException e) { e.printStackTrace(); } } }
其实你若不愿用filter,完全可以把这两段代码放在相应的servlet.init()和servlet.execute()的finally里。
Hibernate Session Factory
//sessionFactory是一个singleton private static SessionFactory sessionFactory; //init在filter.init()中被调用 public static void init() throws HibernateException //currentSession被DAO中被调用 public static Session currentSession() throws HibernateException //closeSession在filter.doFilter()的finally中被调用 public static void closeSession() throws HibernateException
CatDAOImpl
//注意:这里的session用完之后并不close,而只flush一下 public void delCat(String strCatId) { try { Session s = HibernateSessionFactory.currentSession(); Object cat = s.load(Cat.class, strCatId); s.delete(cat); s.flush(); } catch (HibernateException e) { e.printStackTrace(); } }
CatDAO
//对Cat的CRUD的封装 public interface CatDAO { public void creatCat(Cat cat); public List readCats(); public void updateCat(Cat cat); public void delCat(String strCatId); }
这里只是对DAO做了最粗略的封装,实际应用中还要加一层DAOFactory。关于DAO pattern,可以在这里得到详细资料:http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html
Hope it's helpful, thanks.
2004/05/10 xanada