我在程序里也是使用 DAO 模式来封装数据库操作的,这两天仔细的看了这里的文章,也
修改了我的 DAO 的设计,把我的思路和大家共享下:
先介绍下代码(为了方便理解,我把 对参数的检查和异常处理 的相关部分去掉了):
帐户类,一个 PO:
代码
- Account {
- String username;
- String password;
- }
DAO 接口
代码
- interface AccountDAO {
- public void addAccount( Account account );
- public void updateAccount( Account account );
- public void removeAccount( String username );
- public Account findByUsername( String username );
- }
AccountDAO 的实现
代码
- class AccountDAOHibernate {
- public void addAccount( Account account ) {
- HibernateUtil.add( account );
- }
- public void updateAccount( Account account ) {
- HibernateUtil.update( account );
- }
- public void removeAccount( String username ) {
- HibernateUtil.remove( Account.class, username );
- }
- public Account findByUsername( String username ) {
- account = (Account) HibernateUtil.findById( Account.class, username );
- }
- }
HibernateUtil 是对 Hibernate 的基本 crud 操作的封装
我参考了 poll 的实现
代码
- class HibernateUtil {
- public static void add( Object object ) throws HibernateException {
- Session s = HibernateSessionFactory.currentSession();
- s.save( object );
- s.flush();
- }
- public static void update( Object object ) throws HibernateException {
- Session s = HibernateSessionFactory.currentSession();
- s.saveOrUpdate( object );
- s.flush();
- }
- public static void remove(Class clazz, String id) throws HibernateException {
- Session s = HibernateSessionFactory.currentSession();
- Object object = s.load(clazz, id);
- s.delete( object );
- s.flush();
- }
- public static Object findById( Class clazz, String id ) throws HibernateException {
- Object obj = null;
- Session s = HibernateSessionFactory.currentSession();
- obj = s.load( clazz, id );
- s.flush();
- return obj;
- }
- }
HibernateSessionFactory 使用 ThreadLocal 做 Session 管理,实现和 hibernate 网站上的一样
参考:http://hibernate.bluemars.net/42.html
代码
- class HibernateSessionFactory {
- public static final ThreadLocal session = new ThreadLocal();
- private static SessionFactory sessionFactory;
- private static Configuration conf;
- public static void init() {
- conf = new Configuration().configure();
- sessionFactory = conf.buildSessionFactory();
- }
- public static Session currentSession() {
- Session s = (Session) session.get();
- if (s == null) {
- s = sessionFactory.openSession();
- session.set(s);
- }
- return s;
- }
- public static void closeSession() {
- Session s = (Session) session.get();
- session.set(null);
- if (s != null) s.close();
- }
- }
说明:
1.DAO 模式的目的是为了把数据库操作封装在 DAO 层下
Session 应该被封装在 DAO 层里
2.何时关闭 Session:
由于使用了 ThreadLocal 来管理 Session,我没有在 DAO 的方法里关闭 Session
这样,同一个 thraed 里的各个 DAO 方法可以访问到 同一个 Session,可以利用
Hibernate 的 lazy load 功能。
在 web 应用程序里可以使用 HibernateFilter 来处理 Session 的关闭:
参考:http://hibernate.bluemars.net/110.html
代码
- public class HibernateFilter implements Filter {
- public void init(FilterConfig filterConfig) throws ServletException {
- HibernateSessionFactory.init();
- }
- public void doFilter( ... ) {
- try{
- filterChain.doFilter( servletRequest, servletResponse );
- } finally {
- try {
- HibernateSessionFactory.closeSession();
- } catch (HibernateException e) {
- log.error( "Error closing current session " + e );
- }
- }
- }
- public void destroy() {
- }
- }
3.对 Transaction 的处理
不在 DAO 层处理 Transaction
如果确实需要 Transaction ,在上一层,比如业务层里的 Session Bean 里来做。