无法获得正确的会话工厂

时间:2015-06-11 18:37:56

标签: spring hibernate

我在旁边使用hibernate配置会话工厂和hibernate事务管理器,下面提到的是apllication-context文件---

<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    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
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">

    <beans profile="nondev,dev">

        <context:annotation-config />
        <context:component-scan base-package="com.woodmac" />

        <import resource="classpath:spring/applicationContext-soap.xml" />
        <import resource="classpath:spring/applicationContext-cache.xml" />
        <import resource="classpath:spring/applicationContext-mail.xml" />
        <import resource="classpath:spring/applicationContext-batchJobs.xml" />


        <bean name="ecommSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="ecommDataSource" />
            <property name="hibernateProperties" ref="hibernateProperties" />
            <property name="packagesToScan" value="com.woodmac" />
        </bean>

        <bean name="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="hibernateProperties" ref="hibernateProperties" />
            <property name="packagesToScan" value="com.woodmac" />
        </bean>

        <bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
            <property name="properties">
                <props>
                    <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                    <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                    <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                    <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>
                    <prop key="hibernate.connection.release_mode">after_statement</prop>
                </props>
            </property>
        </bean>

        <!-- 
            Source: http://static.springsource.org/spring/docs/3.0.0.RC3/reference/html/ch12s03.html

            A DataSource is part of the JDBC specification and is a generalized connection factory. It allows a container or a 
            framework to hide connection pooling and transaction management issues from the application code. 

            NOTE: DriverManagerDataSource 
            class is not an actual connection pool; it does not actually pool Connections. It just serves as simple replacement for a 
            full-blown connection pool, implementing the same standard interface, but creating new Connections on every call. -->
        <!-- 
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
            <property name="driverClass" value="${jdbc.driverClassName}" />
            <property name="jdbcUrl" value="${jdbc.url}" />
            <property name="user" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />

            <property name="minPoolSize" value="${hibernate.c3p0.minPoolSize}" />
            <property name="maxPoolSize" value="${hibernate.c3p0.maxPoolSize}" />
            <property name="maxIdleTime" value="${hibernate.c3p0.idleTestPeriod}" />

            <property name="maxConnectionAge" value="${hibernate.c3p0.maxConnectionAge}" />
            <property name="maxStatements" value="${hibernate.c3p0.max_statement}" />

            <property name="testConnectionOnCheckout" value="${hibernate.c3p0.testConnectionOnCheckout}" />
            <property name="preferredTestQuery" value="${hibernate.c3p0.preferredTestQuery}" />
            <property name="debugUnreturnedConnectionStackTraces" value="${hibernate.c3p0.debug}" />
        </bean>
        -->

        <!-- This bean is the Spring Hibernate transaction manager that will handle transaction related boilerplate code and wiring 
            for us. We needed to define the session factory that the transaction manager will use to create sessions -->
        <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
            p:sessionFactory-ref="sessionFactory" depends-on="sessionFactory">
        </bean>

        <!-- This bean is the spring hibernate transaction manager for new session factory -->
        <bean id="ecommTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
            p:sessionFactory-ref="ecommSessionFactory" depends-on="sessionFactory">
        </bean>


        <!-- Transaction Management tx:annotation-driven element defines that we are declaring transactions using annotations in 
            our classes. -->
        <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />

        <!-- Transaction management for the ecommerce transactions  -->
        <tx:annotation-driven transaction-manager="ecommTransactionManager" proxy-target-class="true" />

        <!-- the transactional advice (i.e. what 'happens'; see the <aop:advisor/> bean below) -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- the transactional semantics... -->
            <tx:attributes>
                <!-- all methods starting with 'get', 'select', 'find' are read-only -->
                <tx:method name="get*" read-only="true" propagation="SUPPORTS" />
                <tx:method name="select*" read-only="true" propagation="SUPPORTS" />
                <tx:method name="find*" read-only="true" propagation="SUPPORTS" />
                <tx:method name="fetch*" read-only="true" propagation="SUPPORTS" />
                <!-- other methods use the default transaction settings -->
                <tx:method name="*" propagation="REQUIRED" />
            </tx:attributes>
        </tx:advice>
    </beans>

    <!-- Note: Only use the DriverManagerDataSource class should only be used for testing purposes since it does not provide 
        pooling and will perform poorly when multiple requests for a connection are made. -->
    <beans profile="dev-notinuse">
        <!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" p:driverClassName="${jdbc.driverClassName}"
            p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}">
        </bean>  -->
        <!-- <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiName" value="${portal.ds.jndi}"/>
        </bean> -->
    </beans>

    <beans profile="nondev, dev">
        <jee:jndi-lookup id="ecommDataSource" jndi-name="${ecommerce.ds.jndi}" lookup-on-startup="true" lazy-init="false" expected-type="javax.sql.DataSource" proxy-interface="javax.sql.DataSource"/>
        <jee:jndi-lookup id="dataSource" jndi-name="${portal.ds.jndi}" lookup-on-startup="true" lazy-init="false" expected-type="javax.sql.DataSource" proxy-interface="javax.sql.DataSource"/>
    </beans>
</beans>

现在在我编写的测试DAO中调用存储过程---

package com.woodmac.component.event.dao.impl;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;

import oracle.jdbc.OracleTypes;

import org.hibernate.Session;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.woodmac.component.event.dao.IEventDAO;
import com.woodmac.generic.dao.impl.EcommDaoImpl;

/**
 * The Class EventDAOImpl.
 */
@Component
@Qualifier("eventDAO")
@Transactional
@DependsOn("ecommSessionFactory")
public class EventDAOImpl extends EcommDaoImpl implements IEventDAO{

    public Integer callSqlBlock(){

        Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
        final Integer outputValue =1;
        session.doWork(new Work() {
                                        @Override
                                        public void execute(Connection conn)
                                                throws SQLException {
                                              CallableStatement stmt = conn.prepareCall("? = call test(?)");
                                              stmt.registerOutParameter(1, OracleTypes.INTEGER);
                                              stmt.setString(2, "callIndex");
                                              stmt.execute();
                                              Integer output = stmt.getInt(1);
                                              System.out.println("outputValue is"+outputValue); 
                                           }
                        });
        return outputValue;
}
}

但不幸的是,这给了我一个与预期不同的会话工厂,这是我得到的连接字符串是另一个模式,因此我得到一个糟糕的SQL异常。

我在哪里出错?

1 个答案:

答案 0 :(得分:1)

那么你所说的是getHibernateTemplate()返回一个错误会话工厂的模板?您正在创建2个会话工厂,但没有明确说明哪个会被分配给EventDAOImpl实例。

@DependsOn仅声明该对象将在 ecommSessionFactory之后由Spring 创建,这并不意味着它将被赋予该对象。

See here

Beans on which the current bean depends. Any beans specified are guaranteed to be created by the container before this bean. Used infrequently in cases where a bean does not explicitly depend on another through properties or constructor arguments, but rather depends on the side effects of another bean's initialization. May be used on any class directly or indirectly annotated with Component or on methods annotated with Bean.

我在我的XML文件中创建EventDAOImpl并指定要在XML中注入的SessionFactory bean(ecommSessionFactory或sessionFactory,我不确定你想要哪个)。像这样:

<bean name="eventDAO" class=".....EventDaoImpl">
            <property name="hibernateTemplate" ref="whicheverOneItShouldBe" />