【问题标题】:Spring + Hibernate don't open automatically the sessionSpring + Hibernate 不会自动打开会话
【发布时间】:2013-03-09 19:04:46
【问题描述】:

我正在使用以下架构在 Spring 应用程序中开发 Hibernate DAO:

我有一个 PersonDAO 接口,我在其中声明了我想要的 CRUD 方法,然后我创建了一个具体的类 PersonDAOImpl 来实现这个接口,这个:

package org.andrea.myexample.HibernateOnSpring.dao;

import org.andrea.myexample.HibernateOnSpring.entity.Person;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional
public class PersonDAOImpl2 {

    // Factory per la creazione delle sessioni di Hibernate:
        private static SessionFactory sessionFactory;

        // Metodo Setter per l'iniezione della dipendenza della SessionFactory:
        public void setSessionFactory(SessionFactory sessionFactory) {
            this.sessionFactory = sessionFactory;
            System.out.println("Ho iniettato la SessionFactory: " + sessionFactory);

        }

        /** CREATE CRUD Operation:
         * Aggiunge un nuovo record rappresentato nella tabella rappresentato
         * da un oggetto Person
         */
        @Transactional(readOnly = false)
        public Integer addPerson(Person p) {

            System.out.println("Inside addPerson()");
            System.out.println("Connessione aperta: " + sessionFactory.getCurrentSession().isOpen());
            System.out.println("E' connesa:" + sessionFactory.getCurrentSession().isConnected());

            Integer personID = personID = (Integer) sessionFactory.getCurrentSession().save(p);

            return personID;

        }

}

然后我创建了一个包含 main() 方法的 MainApp 类来测试它是如何工作的。

问题是当我尝试在数据库中插入新记录时执行 MainApp 时,我在堆栈跟踪中收到以下错误消息:

INFO: Using DataSource [org.apache.commons.dbcp.BasicDataSource@446adaa2] of Hibernate SessionFactory for HibernateTransactionManager
Ho iniettato la SessionFactory: org.hibernate.internal.SessionFactoryImpl@34a8a14b
Contesto recuperato: org.springframework.context.support.ClassPathXmlApplicationContext@70501e4e: startup date [Sat Mar 09 10:02:37 CET 2013]; root of context hierarchy
Creato persona1: org.andrea.myexample.HibernateOnSpring.entity.Person@2d35bcd7
Exception in thread "main" java.lang.ClassCastException: org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl2$$EnhancerByCGLIB$$d0c4a932 cannot be cast to org.andrea.myexample.HibernateOnSpring.dao.PersonDAO
    at org.andrea.myexample.HibernateOnSpring.MainApp.main(MainApp.java:26)

似乎它没有找到 Session 对象,现在我有一个疑问:我知道 Spring 会自动为每个 @Transactional 方法打开和关闭 Session 但它似乎不起作用!!!

相反,如果我在调用该方法时显式打开一个新会话,它工作得很好……这样:

@Transactional(readOnly = false)
    public Integer addPerson(Person p) {

        System.out.println("Inside addPerson()");

        Session session = sessionFactory.openSession();

        Transaction tx = null;
        Integer personID = null;

        try {
            tx = session.beginTransaction();

            personID = (Integer) session.save(p);
            tx.commit();
        } catch (HibernateException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }

        return personID;

    }

但我认为我可以说Spring在进入方法时自动打开Session并在退出时关闭它

这是我的 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-3.1.xsd        
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd ">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/SpringTestDb" />
        <property name="username" value="root" />
        <property name="password" value="MY_DB_PSWD" />
        <property name="initialSize" value="2" />
        <property name="maxActive" value="5" />
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="packagesToScan" value="org.andrea.myexample.HibernateOnSpring.entity" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">false</prop>
            </props>
        </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="personDAOImpl" class="org.andrea.myexample.HibernateOnSpring.dao.PersonDAOImpl2" >
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Register @Autowired annotation -->
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
</beans>

有人可以帮助我吗?

Tnx

安德烈亚

【问题讨论】:

  • PersonDAOImpl2 是如何使用的

标签: java spring hibernate spring-mvc


【解决方案1】:

您需要为您的 DAO 使用接口或重新配置 proxy mechanism 以使用类。

【讨论】:

    【解决方案2】:

    您必须告诉 Spring 何时“打开”会话。 有现成可用的 Spring 实现,它在处理请求之前打开会话。

    <mvc:interceptors>
        <bean name="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
            <property name="sessionFactory">
                <ref local="sessionFactory"/>
            </property>
        </bean>
    </mvc:interceptors>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 2011-09-19
      • 2022-08-18
      • 2018-02-22
      • 2022-01-19
      • 2014-11-23
      相关资源
      最近更新 更多