【问题标题】:Bad configuration of hibernate for spring application?春季应用程序的休眠配置错误?
【发布时间】:2013-12-04 07:59:07
【问题描述】:

我在 Spring 应用程序中遇到了休眠问题。我觉得肯定是配置不好。

hibernate.cfg.xml

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/cloud_app?autoReconnect=true</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.release_mode">after_transaction</property>
        <property name="show_sql">true</property>

    ...

persistanceContext.xml

<bean id="dataSource" destroy-method="close"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver" />
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/cloud_app" />
        <property name="user" value="root" />
        <property name="password" value="root" />
        <property name="debugUnreturnedConnectionStackTraces" value="true" />
        <property name="unreturnedConnectionTimeout" value="20" />
        <property name="minPoolSize" value="5" />
        <property name="initialPoolSize" value="10" />
        <property name="maxPoolSize" value="50" />
        <property name="maxStatements" value="50" />
        <property name="idleConnectionTestPeriod" value="120" />
        <property name="maxIdleTime" value="1200" />
    </bean>

    <!-- Hibernate -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
        </property>
        <property name="configurationClass">
            <value>org.hibernate.cfg.AnnotationConfiguration</value>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- Transaction manager -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

当我在我的应用程序中使用sessionFactory.getCurrentSession() 时,它仍然会抛出异常

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

但是当我使用sessionFactory.openSession() 时,它解决了问题,但又产生了另一个问题。所以我的问题是,我怎样才能达到一种状态——整个应用程序的一个会话。当我打电话给sessionFactory.getCurrentSession() 时,会话将存在。 我很困惑,我阅读了很多线程如何解决它,但没有成功。

更新 当我得到一些对象然后我尝试改变它时

Opportunity opportunity = opportunityDao.get(idOpportunity);
opportunity.setOrder(order);
opportunityDao.edit(opportunity);

来自get 方法的代码

public T get(Integer id) {
    T object = (T) sessionFactory.getCurrentSession().get(clazz, id);
    return object;
}

来自edit 方法的代码

public void edit(T object) {
    this.sessionFactory.getCurrentSession().update(object);
}

它把我扔了org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions

【问题讨论】:

    标签: java spring hibernate hibernate-session


    【解决方案1】:

    几件事

    1. 您的 hibernate.connection.* 属性没有用,因为您在 Spring 应用程序中注入了 DataSource
    2. dialect和show_sql的其他属性已经在spring配置中设置好了,总之(由于1和2)可以删除hibernate.cfg.xml文件。
    3. 使用AnnotationSessionFactoryBean 便利类。

    把这个留给你

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.bytecode.use_reflection_optimize">false</prop>
            </props>
        </property>
        <property name="packagesToScan" value="your.package.with.entities.here" />
    </bean>
    

    这至少可以清理您的配置(并将所有内容都移到一个文件中)。

    您遇到的问题是由于交易配置不当造成的。你有方法,HibernateTransactionManager,但没有配置的时间/地点。我希望&lt;tx:annotation-driven /&gt; 或&lt;tx:advice /&gt; 与&lt;aop:config /&gt; 一起启用事务。

    我建议阅读 Spring 参考指南中的 transaction chapter,有关 hibernate 的更多信息阅读 the hibernate section。

    【讨论】:

    • 谢谢,它部分解决了问题。我可以使用getCurrentSession() 对实体进行操作。但是还有另一个问题,我认为它与多个打开的会话有关。请看更新。
    • 这与错误的交易设置有关。您的服务层应该是事务层而不是 dao。所以基本上获取/修改/更新的方法应该是事务性的。
    • 很奇怪,因为在webapp上下文中设置了,并且每个调用dao方法的服务都有@Service注解。
    • 您的建议是正确的。我启用了事务,但 OSIV 过滤器不起作用。我必须将它设置为拦截器 - 它解决了所有问题。
    • @Service 与@Transactional 无关。不要使用 OSIVF 或 OSIVI,只需使用 @Transactional 注释您的服务(正如我在之前的评论中提到的)。
    猜你喜欢
    • 2018-04-25
    • 1970-01-01
    • 2011-07-18
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-24
    相关资源
    最近更新 更多