1. 程式人生 > >【轉】Spring 中配置sessionFactory及用法(JAVA後端)

【轉】Spring 中配置sessionFactory及用法(JAVA後端)

Spring 中配置sessionFactory及用法

方法一:

1、在Spring的applicationContext.xml中配置bean

 <!-- 啟用註解注入  -->
      <context:annotation-config />
      <!-- spring掃描的包 -->
      <context:component-scan base-package="com.iven"/> 
     
      <!-- 配置資料來源 -->
      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" >
       <property name="driverClassName" value="com.mysql.jdbc.Driver" />     
       <property name="url" value="jdbc:mysql://172.25.9.99:3306/fzghc" />
       <property name="username" value="root"></property>
       <property name="password" value="123456"></property>       
      </bean>     
      
       <!-- 配置Spring的SessionFactory -->
      <bean id="sessionFactory

"        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="annotatedClasses">
            <list>
                <value>com.iven.entity.User</value>
                <value>com.iven.entity.Repairs</value>

            </list>
        </property>       
        <property name="hibernateProperties">
            <value>
             hibernate.dialect=org.hibernate.dialect.MySQLDialect
    <!-- hibernate.dialect=org.hibernate.dialect.SQLServerDialect -->
    hibernate.show_sql=true    
            </value>
        </property>       
      </bean>
     
      <!-- 新增事務管理 -->
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
      </bean>
     
      <tx:annotation-driven transaction-manager="transactionManager"/>

  <!-- 新增事務管理 -->
      
      <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
      </bean>      
      <tx:annotation-driven transaction-manager="transactionManager"/>
    
      

      <bean id="txManager"       class="org.springframework.orm.hibernate4.HibernateTransactionManager">
         <property name="sessionFactory" ref="sessionFactory"></property>
      </bean>
      
      <tx:advice  id="txAdvice" transaction-manager="txManager">
         <tx:attributes>
            <!-- all methods starting with 'get' are read-only -->
            <tx:method name="queryByUsername" read-only="true"/>   
            <!-- other methods use the default transaction settings (see below) -->
            <tx:method name="*" />   
           
          </tx:attributes>
      </tx:advice>

      
      <aop:config>
        <aop:pointcut expression="execution(* com.iven.dao.*.*(..))"           id="fooServiceOperation"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>

      </aop:config>

2、新增類BaseSessionFactoryImpl用於獲取Session,類BaseSessionFactoryImpl的內容如下:

public class BaseSessionFactoryImpl {

 @Resource(name="sessionFactory")
 private SessionFactory sessionFactory=null;
 public Session getSession(){
  return sessionFactory.getCurrentSession();
 }
}

3、在Dao層獲取Session,

public class UserDaoImplextends BaseSessionFactoryImpl
{

 public User queryByUsername(String userName) {    
     User user=null;
     String sql="select user from User user where user.userName="+userName;
     try {
       user=(User) getSession().get(User.class, 1);   
     } catch (Exception e) {
      e.printStackTrace();
     }     
    return user;
 }

}

4.重點注意事項

   SessionFactory的getCurrentSession並不能保證在沒有當前Session的情況下會自動建立一個新的,這取決於CurrentSessionContext的實現,SessionFactory將呼叫CurrentSessionContext的currentSession()方法來獲得Session。

   在Spring中,如果我們在沒有配置TransactionManager並且沒有事先呼叫SessionFactory.openSession()的情況直接呼叫getCurrentSession(),那麼程式將丟擲“No Session found for current thread”異常。

   如果配置了TranactionManager並且通過@Transactional或者宣告的方式配置的事務邊界,那麼Spring會在開始事務之前通過AOP的方式為當前執行緒建立Session,此時呼叫getCurrentSession()將得到正確結果。

然而,產生以上異常的原因在於Spring提供了自己的CurrentSessionContext實現,如果我們不打算使用Spring,而是自己直接從hibernate.cfg.xml建立SessionFactory,並且為在hibernate.cfg.xml
中設定current_session_context_class為thread,也即使用了ThreadLocalSessionContext,那麼我們在呼叫getCurrentSession()時,如果當前執行緒沒有Session存在,則會建立一個繫結到當前執行緒。

Hibernate在預設情況下會使用JTASessionContext,Spring提供了自己SpringSessionContext,因此我們不用配置current_session_context_class,當Hibernate與Spring整合時,將使用該SessionContext,故此時呼叫getCurrentSession()的效果完全依賴於SpringSessionContext的實現。

在沒有Spring的情況下使用Hibernate,如果沒有在hibernate.cfg.xml中配置current_session_context_class,有沒有JTA的話,那麼程式將丟擲"No CurrentSessionContext configured!"異常。此時的解決辦法是在hibernate.cfg.xml中將current_session_context_class配置成thread。

在Spring中使用Hibernate,如果我們配置了TransactionManager,那麼我們就不應該呼叫SessionFactory的openSession()來獲得Sessioin,因為這樣獲得的Session並沒有被事務管理。

至於解決的辦法,可以採用如下方式:
1. 在spring 配置檔案中加入

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

並且在處理業務邏輯的類上採用註解


@Service
public class CustomerServiceImpl implements CustomerService {
@Transactional
public void saveCustomer(Customer customer) {
customerDaoImpl.saveCustomer(customer);
}
...
}
另外在 hibernate 的配置檔案中,也可以增加這樣的配置來避免這個錯誤:

< property name="current_session_context_class">thread</property>