Hibernate--與Spring整合及增刪改查

BtWangZhi發表於2017-08-13

1 因公司為求穩定,使用的是Spring2.5+Hibernate3,自己整合了一下,對Spring的理解又更深了一步。
使用到的架包:
這裡寫圖片描述
通過jpa fact根據表結構生成實體

@Entity
@Table(name="user")
@NamedQuery(name="User.findAll", query="SELECT u FROM User u")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;
    private UserPK id;
    private String name;
    private String pwd;
//省略get set方法
@Embeddable
public class UserPK implements Serializable {
    //default serial version id, required for serializable classes.
    private static final long serialVersionUID = 1L;
    private int id;
    private int no;
//省略get set方法

Hibernate配置檔案hibernate.cfg.xml

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
<session-factory>
    <!-- Spring與Hibernate整合是資料庫相關資訊交給Spring去完成 -->
    <!-- 配置資料庫資訊 -->
    <!-- <property name="connection.driver_class">
        com.mysql.jdbc.Driver
    </property>
    <property name="connection.url">
        jdbc:mysql://localhost:3306/hibernate?useSSL=false
    </property>
    <property name="connection.username">root</property>
    <property name="connection.password">123123</property>
    資料庫方言
    <property name="dialect">
        org.hibernate.dialect.MySQLDialect
    </property> -->

    <!-- 格式化輸出生成的SQL -->
    <property name="show_sql">true</property>
    <property name="format_sql">true</property>

    <!-- 採用配置檔案的形式則採用如下的方式 ,新增配置檔案的位置-->
    <!-- <mapping resource=""/> -->
    <!-- 如下是採用註解的方式 ,新增類名-->
    <mapping class="com.text.entity.User" />
</session-factory>
</hibernate-configuration>

資料來源資訊轉移到了Spring中。
資料持久化官方文件說明了三種方法,以下逐步說明

2 通過HibernateTemplate
HibernateTemplate相當於Hibernate中的Session,只不過和Spring整合後,Spring將其封裝了起來。通過Spring容器的配置,注入一個SessionFactory,其實就是資料來源相關資訊。

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <!-- <property name="mappingResources">
            <list>
                <value>com.text.entity.User</value>
            </list>
        </property> -->
        <property name="packagesToScan">
            <list>
                <value>com.text.entity.User</value>
            </list>
        </property>
        <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
        <!-- <property name="hibernateProperties" value="hibernate.dialect=org.hibernate.dialect.MySQLDialect"/> -->
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop>
                <!-- <prop key="current_session_context_class">thread</prop> -->
            </props>
        </property>
    </bean>

注入到資料層

<bean id="userDaoImpl" class="com.text.dao.impl.user.UserDaoImpl01">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

對應的程式碼,省略的介面。

public class UserDaoImpl01 implements UserDao01 {

    private HibernateTemplate hibernateTemplate;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.hibernateTemplate = new HibernateTemplate(sessionFactory);
    }

    public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

Spring容器在初始化的時候將會注入SessionFactory到配置了資料層中,這樣就可以在通過hibernateTemplate中的一系列方法來持久化資料了。如下的增刪改查:

/**
     * 新增,直接傳入物件進行更新
     */
    @Override
    public void insert01(final User user) {
        // TODO Auto-generated method stub
        this.getHibernateTemplate().execute(new HibernateCallback() {
            public Object doInHibernate(Session session) {
                session.saveOrUpdate(user);
                return null;
            }
        });
    }

    /**
     * 新增,通過執行SQL語句新增
     */
    public void insert02(final User user) {
        final StringBuffer sqlStr = new StringBuffer();
        // SessionFactory sessionFactory=hibernateTemplate.getSessionFactory();
        sqlStr.append("insert into user (id,no,name,pwd)");
        sqlStr.append("values(:id,:no,:name,:pwd)");

        this.hibernateTemplate.execute(new HibernateCallback() {
            @Override
            public Object doInHibernate(Session session)
                    throws HibernateException, SQLException {
                SQLQuery sqlQuery = session.createSQLQuery(sqlStr.toString());
                sqlQuery.setParameter("id", user.getId().getId());
                sqlQuery.setParameter("no", user.getId().getNo());
                sqlQuery.setParameter("name", user.getName());
                sqlQuery.setParameter("pwd", user.getPwd());
                sqlQuery.executeUpdate();// 執行
                session.flush();
                return null;
            }
        });
    }

    /**
     * 根據物件刪除,通過傳入物件刪除
     */
    @Override
    public void delete(User user) {
        // TODO Auto-generated method stub
        this.hibernateTemplate.delete(user);
    }

    /**
     * 根據物件更新,通過傳入物件進行更新
     */
    @Override
    public void update(User user) {
        // TODO Auto-generated method stub
        this.hibernateTemplate.update(user);
    }

    /**
     * HQL查詢
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<User> select01(String name) throws DataAccessException {
        // TODO Auto-generated method stub
        return (List<User>) this.hibernateTemplate.find(
                "from com.text.entity.User u where u.name=?", name);
    }

    /**
     * 分頁查詢,通過Criteria制定規則進行查詢
     */
    @SuppressWarnings("unchecked")
    @Override
    public List<User> select02(final String name) throws DataAccessException {
        return (List<User>) this.hibernateTemplate
                .execute(new HibernateCallback() {
                    @Override
                    public List<User> doInHibernate(Session session)
                            throws HibernateException, SQLException {
                        Criteria criteria = session.createCriteria(User.class);
                        criteria.add(Expression.eq("name", name));
                        criteria.setFirstResult(0);
                        criteria.setMaxResults(5);
                        return criteria.list();
                    }
                });
    }

測試:

public static void insert01(){
        BeanFactory beanFactor=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao01 userDao=(UserDao01) beanFactor.getBean("userDaoImpl01");

        User user02=new User();
        UserPK userPK02=new UserPK();
        userPK02.setId(2);
        userPK02.setNo(2);
        user02.setId(userPK02);
        user02.setName("111");
        user02.setPwd("1234");
        userDao.insert01(user02);
        System.out.println("run over");
    }

其他類似。

3 第二種方式是HibernateDaoSupport
需要在Spring的配置檔案中新增事務相關的配置。

<bean id="myTxManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

    <tx:annotation-driven transaction-manager="myTxManager"/>

HibernateDaoSupport 為一個虛基類,提供給子類SessionFacotory的set和get方法,使用到該虛基類的子類可直接在配置檔案中配置SessionFactory。

@Transactional
public class UserDaoImpl02 extends HibernateDaoSupport implements UserDao02{

    /**
     * 執行HQL 查詢
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<User> select03(){
        return this.getHibernateTemplate().find("from com.text.entity.User");
    }

    /**
     * 利用Session執行HQL查詢
     */
    @SuppressWarnings("unchecked")
    public List<User> select04(String name){
        Session session=getSession(false);//通常將false作為引數
        Query query=session.createQuery("from com.text.entity.User u where u.name=?");
        query.setString(0, name);
        return query.list();
    }
}

執行刪除語句:

SQLQuery sqlQuery=getSession().createSQLQuery(queryString.toString());
        sqlQuery.executeUpdate();

配置相關:

<!-- 繼承自HibernateDaoSupport -->
    <bean id="userDaoImpl02" class="com.text.dao.impl.user.UserDaoImpl02">
        <property name="sessionFactory" ref="mySessionFactory"/>
    </bean>

在之類中可直接通過由父類繼承來的方法getSession來獲取一個Session,即Hibernate中Session,通過該中的一系列方法來持久化資料。比如上面select04方法。
測試:

public static void select03(){
        //getUserDao();
        BeanFactory beanFactor=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDaoImpl02 daoImpl02=(UserDaoImpl02)beanFactor.getBean("userDaoImpl02");
        List<User> lstUser=daoImpl02.select03();
        for (User user : lstUser) {
            System.out.println(user.getName()+" "+user.getPwd());
        }
    }

3 直接使用注入的SessionFactory。

@Transactional
public class UserDaoImpl03 implements UserDao03 {

    private SessionFactory sessionFactory;

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /**
     * 通過當前Sesson物件執行HQL語句
     * 
     * @param name
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<User> select05(String name) {
        return this.sessionFactory.getCurrentSession()
                .createQuery("from com.text.entity.User u where u.name=?")
                .setParameter(0, name).list();
    }
}

測試:

public static void select05(){
        BeanFactory beanFactor=new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao03 userDao03=(UserDao03)beanFactor.getBean("userDao03");
        List<User> lstUser=userDao03.select05("dema");
        for (User user : lstUser) {
            System.out.println(user.getName()+" "+user.getPwd());
        }
    }

看文件只研究到這,未完待續。。。
附報錯及解決方案:

1報錯:No Hibernate Session bound to thread, and configuration does not allow 
creation of non-transactional one here
解決方案:
在application.xml中新增事務管理
<!-- - - - - - - spring 宣告式事務 - - - - - - - -->
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="myDataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>
同時在實現類中新增@Transactional註解
參考:
http://www.cnblogs.com/cnsdhzzl/p/6061171.html
http://bbs.csdn.net/topics/390866026

2報錯:java.lang.NoClassDefFoundError: org/aopalliance/intercept/MethodInterceptor
新增:aopalliance.jar

3報錯:com.sun.proxy.$Proxy11 cannot be cast to com.tex
解決方案:
BeanFactory beanFactor=new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao02 daoImpl02=(UserDao02)beanFactor.getBean("userDaoImpl02");
不能使用實現類,而應該是介面,具體和動態代理相關

附程式碼:http://download.csdn.net/download/btwangzhi/9932106,其實我是不想要積分的,但是CSDN積分下拉框沒有0積分,所以就1個積分了。

相關文章