Spring整合Hibernate项目中访问数据库的三种方式比较

Spring+Hibernate DAO  持久层开发 ,Spring  用 Hibernate 访问数据库的三种 ⋯

DAO 开发
注:
(1)以下两者都需在 Spring X ML 配置文件中 ,注册 Bean(实现类 )来依赖注入 SessionFactory.
(2.1)Spring  中进行事务管理的通常方式是利用 AOP(面向切片编程) 的方式, 为普通 java 类封装事务控制,它是通过动态代理实现的,由于接口是延迟实例化的, spring 在这段时间内通过拦截器,加载事务切片。原理就是这样,具体细节请参考 jdk 中有关动态代理的文档。本文主要讲解如何在 spring 中进行事务控制。
(2.2)动态代理的一个重要特征是,它是针对接口的 ,所以我们的 DAO 要通过动态代理来让 spring 接管事务,就必须在 DAO 前面抽象出一个接口 . 当然如果没有这样的接口,那么 spring 会使用 CGLIB 来解决问题,但这不是 spring 推荐的方式 .
(一)直接使用 Hibernate API ( 不推荐使用 )

public class DaoImp implate Dao{
    private SessionFactory sessionFactory;
    private static String hql = "from User u where u.username=? ";
    public void setSessionFactory(SessionFactory sessionFactory){
        this.sessionFactory=sessionFactory;
    }
    public boolean isValidUser(String username) {
        try{
            List userList = sessionFactory.getCurrentSession().creatQuery(hql).setParameter(0,username).list();
        if (userList.size() > 0) {
            return true;
        }
        } catch (HibernateException ex){
            throw converHibernaterAccessException(ex);
        }
    }
}

优点 :与 Spring 框架完全分离
缺点 :(1)无法使用 Spring 框架封装所提供的额外功能 .如,直接使用 Hibernate API  需用 try...catch() 处理 HibernateException 异常.
(2)需在实现类中加入 setSessionFactory(SessionFactory sessionFactory) 属性,接收依赖注入的 SessionFactory.

(二)继承 Spring 的 HibernateDaoSupport  使用 HibernateTemplate ( 不推荐使用 getSession())

public class DaoImp extend HibernateDaoSupport implates Dao{
    private static String hql = "from User u where u.username=? ";
    public boolean isValidUser(String username) {
        List userList = getHibernateTemplate().find(hql,username);
    if (userList.size() > 0) {
        return true;
    }
    public boolean isValidUser(String username,String password) throw DataAccessException{
        Session session = getSession(); //不推荐使用 ,用完后需手动关闭
        String[] userlist=new String[2];
        userlist[0]=username;
        userlist[1]=password;
        try{
            List userList = session.find(hql,userlist); //Hibernate 语句;
            session.close();
            if (userList.size() > 0) {
            return true;
        } catch (HibernateException ex){
            throw converHibernaterAccessException(ex);
        }
    }
}

特点 :对 HibernateTemplate 没有提供的功能 ,可以直接调用 HibernateDaoSuppor 对象的 getSession()方法 (极其不推荐使用 )得到Session 对象实例用 try{ Hibernate API }catch (HibernateException ex )操作 .

(三)对 HibernateTemplate  没有提供的功能 , 还可以用 HibernateCallback  回调的方法管理数据库 .(极其推荐 )

/**
* 使用 hql 语句进行操作
* @param hql HSQL 查询语句
* @param offset 开始取数据的下标
* @param length 读取数据记录数
* @return List 结果集
*/
public List getListForPage ( final String hql , final int offset , final int length ) {
    List list = getHibernateTemplate().executeFind (new HibernateCallback ( ) {
        public Object doInHibernate ( Session session ) throws HibernateException,SQLException{
            Query query = session.createQuery ( hql ) ;
            query.setFirstResult ( offset ) ;
            query.setMaxResults ( length ) ;
            //query.setCacheable(false);
            // for (int i =  0; i < values.length; i++) {
            // query.setParameter(i, values[i]);
            // }
            List list = query.list ( ) ;
            return list ;
        }
    });
    return list ;
}

spring+hibernate 架构中 Dao 访问数据库的几种方法
在 spring+hibernate 的架构中,访问数据库有几种方法,按 spring 依赖注入来区分有 3 种,在这之前先再来了解一下 spring 的依赖注入, spring 主要的两大核心就是 IOC(控制反转)和 AOP(面向切面编程), 控制反转就是控制转移 ,从以往由 Bean 去控制要调用的接口或其他资源转移给容器,由容器来寻找并实例化要调用的接口 ,也可以解释成依赖注入 ,即在 spring 配置文件中把要调用的接口、设置、构造子配置给 Bean 。这边是以依赖注入来区分为 sessionFactory 、hibernateTemplate 、jdbcTemplate ,本质上划分只有
hibernateTemplate 和 jdbcTemplate 这两种。

1、注入 sessionFactory
在 spring 配置文件中,对 Dao 注入 sessionFactory ,即:

<bean id="classDao" class="cn.jmu.data.dao.impl.ClassImpl">
    <property name="sessionFactory">
        <ref local="sessionFactory" />
    </property>
</bean>


这边 sessionFactory 依赖注入的不是给 Dao 层中的类,而是给 HibernateDaoSupport ,见 spring 源文件 org/springframework/orm/hibernate3/support/HibernateDaoSupport.java 里面,就有sessionFactory 的 set、get 操作:
 

//源码
public final void setSessionFactory(SessionFactory sessionFactory) {
    this.hibernateTemplate = 
        createHibernateTemplate(sessionFactory);//通过 sessionFactory 来生成 hibernateTemplate
}
public final SessionFactory getSessionFactory() {
    return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
}

所以在 Dao 层中类继承 HibernateDaoSupport ,即可通过 this.getHibernateTemplate() 来对数据库进行操作,
更新数据: this.getHibernateTemplate().update(bo);
查询数据: this.getHibernateTemplate().find(bo);
添加数据: this.getHibernateTemplate().save(bo) ;
删除数据: this.getHibernateTemplate().delete(bo);
从上面可以看出 spring+hibernate 的强大威力, 存取数据不用像以往 jdbc 那样,要写一大串 try,catch语句,还要连接数据库,用完再关闭数据库连接,而用一条语句就可以搞定。这里 sessionFactory 由 spring 自动自动连接、关闭,当然你也可以手动来连接、关闭,如下面采用的方法:

Session session=this.getHibernateTemplate().getSessionFactory().openSession();
Transaction tx=session.beginTransaction();
/*-------------- 查询数据 ------------------------*/
String str="hql";
Query query=session.createQuery(str);
List list=query.list();
/*-------------- 删除数据 ------------------------*/
session.load(bo,ID);
session.delete(bo);
/*-------------- 添加数据 ------------------------*/
session.save(bo);
/*-------------- 修改数据 -----------------------*/
session.load(bo,ID);
session.update(bo);
/*--------------end---------------------------*/
tx.commit();
session.close();

初学 Hebernate 的人对这些代码应该很熟悉, 没有 spring 提供 hibernateTemplate, 在单单的 Hibernate中就得用这种方面去访问存取数据了。
2、注入 hibernateTemplate
这种方法本质跟上面注入 sessionFactory 一样,只不过再进行一层包装,这样最大的好处就是 Dao中的类就不用再继承 HibernateDaoSupport (在 java 中是单继承的,这唯一一次的继承就被HibernateDaoSupport 剥夺去就岂不可惜?)不过在这之前要先要配置好 hibernateTemplate ,即:

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
        <ref bean="sessionFactory"/>
    </property>
</bean>

再对要用到 hibernateTemplate 的 Dao 进行注入依赖,即:

<bean id="ClassDao" class="cn.jmu.data.dao.impl.ClassImpl">
    <property name="hibernateTemplate">
        <ref bean="hibernateTemplate"/>
    </property>
</bean>

在 Dao 层的类就要添加 hibernateTemplate 对象,来对应配置文件中所注入的依赖:

private HibernateTemplate hibernateTemplate;
public HibernateTemplate getHibernateTemplate() {
    return hibernateTemplate;
}
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
}

hibernateTemplate 对数据的增删查给就跟上面的一样,即:
更新数据: hibernateTemplate().update(bo);
查询数据: hibernateTemplate().find(bo);
添加数据: hibernateTemplate().save(bo) ;
删除数据: hibernateTemplate().delete(bo);


3、注入 jdbcTemplate

如果对以前的 jdbc 的 SQL 还念念不忘,又对 Hibernate 的 HQL 没有好感的话,就可以采用 jdbcTemplate 来增删查改数据库了。在某些情况下采用 jdbcTemplate 还比较方便,甚至还能提高查询效率。在这之前也要像注入 hibernateTemplate 那样,先配置好 jdbcTemplate :

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource">
        <ref bean="dataSource" />
    </property>
</bean> 

如果 jdbcTemplate 和 hibernateTemplate 配置时都指向同一个 dataSource ,那就可以共用同一个事务了。再对要用到 jdbcTemplate 的Dao 进行注入依赖,即:

<bean id="classDao" class="cn.jmu.data.dao.impl.ClassImpl">
    <property name="jdbctemplate">
        <ref bean="jdbcTemplate" />
    </property>
</bean>

在 Dao 层的类就要添加 jdbctemplate 对象,来对应配置文件中所注入的依赖:

protected JdbcTemplate jdbctemplate;
public JdbcTemplate getJdbctemplate() {
    return jdbctemplate;
}
public void setJdbctemplate(JdbcTemplate jdbctemplate) {
    this.jdbctemplate = jdbctemplate;
}

现在就可以通过 jdbctemplate 存取数据了:

查询数据 :
/*------------ 查询单列 -------------------*/
String SQL= "select name from table";
List list= jdbctemplate.queryForList(SQL);
/*------------ 查询多列 ------------------*/
Hashtable hash = new Hashtable();
jdbctemplate.query(SQL,new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
    hash.put(rs.getString(1),rs.getString(2));
}
});
/*---------- 查询后填充到 vo 里面 -----------*/
String SQL="select * from table where id=?";
String[] obj = new String[1];
obj[0] = N;
VO vo= new VO(); //这边暂用 VO 来表示, VO 的本质不是这样的
List list = jdbcTemplate.query(SQL,obj,vo);
VO 要实现 RowMapper 接口中的 mapRow 方法,把结果集填充到 bo 里面: class VO implements
RowMapper{
    public Object mapRow(ResultSet rs, int index) throws SQLException {
    Bo bo = new Bo();
    bo.setProperty(rs.getString(1));
    bo.setProperty(rs.getString(2));
    bo.setProperty(rs.getString(3));
    return bo;
}
}/*---------------- 更新数据 ------------------*/
String SQL="update table set name=?";
String[] obj=new String[1];
obj[1]="new name";
jdbcTemplate.update(SQL,obj);
/*---------------- 删除数据 ------------------*/
String SQL="delete from table where id='"+ID+"'";
jdbcTemplate.execute(SQL);
/*---------------- 添加数据 ------------------*/
String SQL="insert into table (property1,property2) values ('"+property1+"','"+property1+"')";
jdbcTemplate.execute(SQL);

 

 

 

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值