2012-11-27 50 views
1

我正在更新我的舊程序到Spring 3.2和Hibernate 4,並遇到與sessionFactory(我之前使用hibernateTemplate)的一些困難。休眠4 - 調用DAO和初始化sessionFactory bean

  1. 我不認爲我訪問DAO的方法是做它的最佳方式,但我不明白怎麼回事,使其工作。如果我做了一個簡單的DAO對象創建(CSSDAO d = new CSSDAOImpl();),sessionFactory始終爲空。如果我按照以下的方式使用它,它就可以工作。調用DAO方法的正確方法是什麼? (請忽略控制器的MVC部分,我知道需要自己的工作)

  2. 我在DAO中的每個方法中打開一個新的會話。我知道這是不正確的,因爲我應該得到當前會議。但每次我嘗試獲得當前會話時,都會說不存在。會話如何第一次「初始化」?我以爲它會根據XML配置注入它,但這似乎並沒有在這裏做任何事情。有什麼想法嗎?

休眠-cfg.xml中

<?xml version="1.0" encoding="UTF-8"?> 


<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> 

    <bean id="myDataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver"></property> 
     <property name="url" value="jdbc:derby:C:\Users\Steven\MyDB"></property> 
    </bean> 

    <bean id="sessionFactory" 
     class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> 
     <property name="packagesToScan" value="net.form" /> 
     <property name="dataSource" ref="myDataSource"></property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.DerbyTenSevenDialect 
       </prop> 
       <prop key="hibernate.show_sql">true</prop> 
      </props> 
     </property> 
     <property name="annotatedClasses"> 
      <list> 
       <value>net.form.StyleChooser</value> 
      </list> 
     </property> 
    </bean> 

    <bean id="transactionManager" 
     class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

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

    <bean id="CSSDAO" class="dao.CSSDAOImpl"> 
     <property name="sessionFactory" ref="sessionFactory" /> 
    </bean> 

</beans> 

DAO:

package dao; 

import java.util.List; 

import org.hibernate.Session; 
import org.hibernate.SessionFactory; 
import org.hibernate.Transaction; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.transaction.annotation.Transactional; 

import net.form.StyleChooser; 

public class CSSDAOImpl implements CSSDAO { 

    private SessionFactory sessionFactory; 

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

    @Transactional 
    public List selectAllCSS() { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = session.beginTransaction(); 
     List l = session.createCriteria(StyleChooser.class).list(); 
     session.flush(); 
     tx.commit(); 
     return l; 
    } 

    @Transactional 
    public StyleChooser selectCSSById(Integer ID) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = session.beginTransaction(); 
     StyleChooser sc = (StyleChooser) session.get(StyleChooser.class, ID); 
     session.flush(); 
     tx.commit();   
     return sc; 
    } 

    @Transactional 
    public Integer insertCSS(StyleChooser insertCSS) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = session.beginTransaction(); 
     Integer id = (Integer) session.save(insertCSS); 
     session.flush(); 
     tx.commit(); 
     return id; 
    } 

    @Transactional 
    public void deleteCSS(Integer CSSId) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = session.beginTransaction(); 
     StyleChooser sc = (StyleChooser) session.get(StyleChooser.class, CSSId); 
     session.delete(sc); 
     session.flush(); 
     tx.commit(); 
    } 

    @Transactional 
    public void updateCSS(StyleChooser cssWithNewValues) { 
     Session session = sessionFactory.openSession(); 
     Transaction tx = session.beginTransaction(); 
     session.update(cssWithNewValues); 
     session.flush(); 
     tx.commit();   
    } 
} 

訪問DAO ...

package net.controllers; 

import java.util.List; 
import javax.servlet.http.HttpServletRequest; 
import net.form.StyleChooser; 
import org.springframework.beans.factory.BeanFactory; 
import org.springframework.beans.factory.xml.XmlBeanFactory; 
import org.springframework.core.io.FileSystemResource; 
import org.springframework.core.io.Resource; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.multiaction.MultiActionController; 
import dao.CSSDAOImpl; 

@Controller 
@RequestMapping("/stylechoosertable.html") 
public class IndexController extends MultiActionController { 

    Resource resource = new FileSystemResource(
      "C:/Users/Steven/Desktop/Programming/workspace/CSSGeneratorHibernate4/WebContent/WEB-INF/hibernate.cfg.xml"); 
    BeanFactory beanFactory = new XmlBeanFactory(resource); 
    CSSDAOImpl dao = (CSSDAOImpl) beanFactory.getBean("CSSDAO"); 

    @RequestMapping(method = RequestMethod.GET) 
    public ModelAndView showIndex(HttpServletRequest request) throws Exception { 
     List<StyleChooser> styleChooser = dao.selectAllCSS(); 
     return new ModelAndView("stylechoosertable", "styleChooser", styleChooser); 
    } 
} 

回答

3

很少觀察:

  1. 在你的檢索方法,交易不應該被用來也就是說,它們應該是非事務性的。

  2. 在您的配置中添加<tx:annotation-driven transaction-manager="transactionManager"/>以識別事務註釋。

  3. 如果使用@Transactional註釋,則不需要使用編程事務。將@Transactional註釋中的propagation屬性添加爲@Transactional(propagation=Propagation.REQUIRED),並將事務管理保留爲Hibernate。

  4. 您第一次需要打開會話,如果沒有關閉,您可以下次使用同一會話。爲了獲得session,更好地使用下面的實用程序方法:

    private Session getSession(SessionFactory sessionFactory){ 
    Session session = null; 
    try{ 
        session = sessionFactory.getCurrentSession(); 
    }catch(HibernateException hex){ 
        hex.printStackTrace(); 
    } 
    if(session == null && !session.isClosed()){ 
        session = sessionFactory.openSession(); 
    } 
    } 
    

這樣,您將獲得會話(如果可用)和開路,否則打開一個新的會話。

+0

感謝您的回答。所以我需要從方法中刪除事務行,並通過Transactional註釋將事務留在休眠狀態,對嗎?爲什麼我必須開新會議?我認爲配置會通過注入創建sessionFactory和會話?情況並非如此嗎?最後,應如何準確訪問DAO(問題1) – user1795832

+0

@ user1795832:1.正確。只要確保配置正確並且事務按預期工作即可。 2.您只創建會話工廠。您需要使用會話工廠獲取/創建會話。 3.請參閱https://community.jboss.org/wiki/GenericDataAccessObjects獲取DAO訪問模式。 –

+0

好,太棒了。但是每次調用getSession時我都會遇到異常,所以在任何情況下,sessionFactory中的當前會話都不存在。這是爲什麼?會話一旦退出事務邊界就會被破壞嗎?另外,對於deleteCSS和updateCSS方法,我還必須調用flush()才能使查詢通過,但我不必爲insertCSS。那裏有任何想法? PS對不起,當我出於某種原因將它放在那裏時,我會一直刪除@YOUR USER NAME,所以不確定是否收到通知。 – user1795832