當您將bean定義爲原型範圍時,會爲每個需要注入的地方創建一個新實例。所以每個DAO都會得到一個不同的Session實例,但是DAO中所有方法的調用最終都會使用同一個會話。由於會話不是線程安全的,因此不應該在多個線程之間共享,這將是一個問題。
對於大多數情況,會話應該是事務範圍,即當事務開始時打開新會話,然後在事務完成後自動關閉。在少數情況下,可能需要擴展才能請求範圍。
如果你想避免使用SessionFactory.currentSession - 那麼你將需要定義你自己的範圍實現來實現它。
這是使用代理已經爲JPA實現的東西。在JPA的情況下,注入EntityManager而不是EntityManagerFactory。有一個新的@PersistenceContext註釋,而不是@Autowired。代理在初始化期間被創建並注入。當調用任何方法時,代理將獲得實際的EntityManager實現(使用與SessionFactory.getCurrentSession類似的東西)並委託給它。
類似的事情也可以爲Hibernate實現,但額外的複雜性是不值得的。在內部調用SessionFactory.getCurrentSession()的BaseDAO中定義getSession方法要簡單得多。使用這個會話的代碼和注入會話是一樣的。
一個案例閱讀[文檔](http://docs.jboss.org/hibernate/orm/3.5/javadoc/org/hibernate/Session.html),它說'如果會話引發異常,交易必須被回滾並丟棄該會話。在發生異常之後,會話的內部狀態可能與數據庫不一致。' –
您最好注入'javax.persistence.EntityManager',但爲此,您必須堅持使用JPA。 – Lion