Java 除非在DAO内部,否则事务不工作

Java 除非在DAO内部,否则事务不工作,java,spring,transactions,annotations,dao,Java,Spring,Transactions,Annotations,Dao,我对事务有一个问题,即用@Transactional注释调用DAO的服务会引发一个异常,表明会话未打开。我能让它工作的唯一方法是用@Transactional注释DAO。到底会发生什么 这是我想做但不起作用的事情: class CustomerService { private CustomerDao dao; @Transactional public void foo() { int customerId = dao.getCustomer("fre

我对事务有一个问题,即用@Transactional注释调用DAO的服务会引发一个异常,表明会话未打开。我能让它工作的唯一方法是用@Transactional注释DAO。到底会发生什么

这是我想做但不起作用的事情:

class CustomerService {
    private CustomerDao dao;

    @Transactional
    public void foo() {
        int customerId = dao.getCustomer("fred");
    }
}

class CustomerDao {
    private HibernateTemplate hibernateTemplate;

    public int getCustomer(String name) {
        String sql = "SELECT {m.*} from Customers {m} where name=:name";
        Query qry = getSession().createSQLQuery(sql).addEntity("m", Customer.class);
        qry.setParameter("name", name);
        qry.setCacheable(false);
        List<Customer> list = qry.list();
        return list.iterator().next().getId();
    }

    private Session getSession() {
        return hibernateTemplate.getSessionFactory().getCurrentSession();
    }
}
spring文件如下所示:

<context:annotation-config />
<import resource="classpath:db-spring-conf.xml"/>
<bean id="allServices" class="myPackage.AllServices" />

以及db spring配置:

<bean id="editorDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="${versioning.db}" />
    <property name="username" value="${versioning.user}" />
    <property name="password" value="${versioning.pass}" />
</bean>

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

<bean id="editorSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="editorDatasource"/>
    <property name="exposeTransactionAwareSessionFactory">
        <value>true</value>
    </property>
    <property name="annotatedClasses">
        <list>
            <value>myPackage.Order</value>
        </list>
    </property> 
    <property name="mappingResources">
        <list>
            <value>mappings/customer.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
            <!-- Enable Query Cache -->
            <prop key="hibernate.cache.use_query_cache">false</prop>
            <!-- Enable 2nd Level Cache -->
            <prop key="hibernate.cache.use_second_level_cache">false</prop>
            <prop key="hibernate.connection.autocommit">false</prop>
            <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop>
        </props>
    </property>
</bean>

<bean id="editorHibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="editorSessionFactory"/>
</bean>

<bean id="editorTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="editorSessionFactory" />
</bean>

<!-- DAOs -->
<bean id="customerDao" class="myPackage.CustomerHibernateDao" />
<bean id="orderDao" class="myPackage.OrderHibernateDao" />

真的
我的包裹,订单
映射/customer.hbm.xml
org.hibernate.dialogue.mysqldialogue
真的
验证
假的
假的
假的
org.springframework.orm.hibernate3.SpringSessionContext

我现在已经将CustomerService的实例化移到了Spring配置文件中,一切都很顺利。是否所有使用@Transactional的类都必须在上下文文件中?此外,为了使其正常工作,我必须为CustomerService创建一个接口,以防止加载上下文文件时出现异常-
无法生成类的CGLIB子类

,因此,您确定了问题的原因-Spring的
@事务性
支持是一个方面,Spring中的方面仅应用于Spring contrainer管理的组件(虽然它是,但对于复杂情况来说它是一个高级特性)

如果您不喜欢用XML声明服务,可以查看delcare Spring托管组件的其他选项:

  • (从Spring 3.x开始)

关于CGLIB代理的问题,请参阅-可能在类路径中没有CGLIB实现。

可能事务方面未应用于
CustomerService
。显示它是如何配置的。请显示您的spring xml配置
<context:annotation-config />
<import resource="classpath:db-spring-conf.xml"/>
<bean id="allServices" class="myPackage.AllServices" />
<bean id="editorDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="${versioning.db}" />
    <property name="username" value="${versioning.user}" />
    <property name="password" value="${versioning.pass}" />
</bean>

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

<bean id="editorSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="editorDatasource"/>
    <property name="exposeTransactionAwareSessionFactory">
        <value>true</value>
    </property>
    <property name="annotatedClasses">
        <list>
            <value>myPackage.Order</value>
        </list>
    </property> 
    <property name="mappingResources">
        <list>
            <value>mappings/customer.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
            <!-- Enable Query Cache -->
            <prop key="hibernate.cache.use_query_cache">false</prop>
            <!-- Enable 2nd Level Cache -->
            <prop key="hibernate.cache.use_second_level_cache">false</prop>
            <prop key="hibernate.connection.autocommit">false</prop>
            <prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop>
        </props>
    </property>
</bean>

<bean id="editorHibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory" ref="editorSessionFactory"/>
</bean>

<bean id="editorTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="editorSessionFactory" />
</bean>

<!-- DAOs -->
<bean id="customerDao" class="myPackage.CustomerHibernateDao" />
<bean id="orderDao" class="myPackage.OrderHibernateDao" />