简短的问题:我怎么能(或者有可能)在Spring中没有被声明为bean的类中使用Spring的事务管理器?
细节...... 我有一个使用Spring 3和Hibernate 3.6的应用程序,以及两个这样的类:
public class FooManagerImpl implements FooManager {
@Override
@Transactional
public Foo getFoo(int id) {
Session s = sessionFactory.getCurrentSession();
// do some query
return foo;
}
}
FooManagerImpl
是一个Spring bean(见下文),但FooImpl
不是。 FooImpl
与第三个类Bar
有父/子关系,它也是一个实体(这是事情中断的地方)。
@Entity
@Table(name = "foo_table")
public class FooImpl implements Foo {
private List<Bar> bars;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SELECT)
@JoinColumn(name = "foo_id", referencedColumnName = "foo_id")
public List<Bar> getBar() {
return this.bars; // Bar is also an entity
}
public void addBar(Bar b) {
this.bar.add(b);
}
}
Spring配置的相关部分:
<tx:annotation-driven />
<jee:jndi-lookup id="fooDatasource" jndi-name="fooDatasource" />
<bean id="fooSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="fooDatasource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
<property name="packagesToScan">
<value>com.foo</value>
</property>
</bean>
<bean id="fooTransactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="fooSessionFactory" />
<qualifier value="ec" />
</bean>
<bean id="fooManager" class="com.foo.model.FooManagerImpl">
<property name="sessionFactory" ref="fooSessionFactory" />
</bean>
据我所知,在调用FooImpl.addBar(Bar)
时,Hibernate将尝试持久化更改,因为没有事务限制而失败。没有TX绑定,因为Spring不代理FooImpl
中的任何方法,因为它不是bean。这是正确的评估吗?有没有办法让这项工作成功?
我到目前为止找到的解决方案,但这似乎不太有用(或者我无法让它们工作):
设置AOP代理以插入事务性建议,例如here。但据我所知,这些代理仅在我将类定义为bean时才适用,对吗?
我想我也可以使用AspectJ,比如<tx:annotation-driven mode="aspectj"/>
,但这似乎要求我使用不同的类加载器,由于各种原因,我做不到(需要更改Tomcat,而不只是我的webapp ...我认为)。请参阅here。
我真的不想使用OpenSessionInView,因为我不太喜欢在服务层之外发生后端事务的想法。
所以,我很难过。有没有人有任何想法?我试过的其中一件事应该有效吗? (可能我搞砸了。)
提前致谢。
答案 0 :(得分:0)
不需要将实体(FooImpl)声明为spring bean。你需要这个
<bean id="fooSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="fooDatasource" />
<property name="annotatedClasses">
<list>
<value>com.foo.model.FooImpl</value> // Entity
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
</props>
</property>
<property name="packagesToScan">
<value>com.foo</value>
</property>
查看此example