我有GenericService
类,它封装了子类的crud方法:
public abstract class GenericService<D extends GenericDao<T, I>, T extends DomainObject<I>, I> {
public I save(T t) {
return getDao().save(t);
}
...........................
}
班级AnswerService
延伸GenericService
。它会自动装配AnswerDao
并声明为@Service
和@Transactional
弹簧组件。
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class AnswerService extends GenericService<AnswerDao, Answer, Long> {
@Autowired
private AnswerDao answerDao;
@Override
public void setDao(AnswerDao d) {
this.answerDao = d;
}
@Override
public AnswerDao getDao() {
return answerDao;
}
................................
}
AnswerDao
扩展了GenericDao
,它实现了方法save
。
public abstract class GenericDaoHibernate<T extends DomainObject<I>, I extends Serializable> implements GenericDao<T, I> {
private Class<? extends T> entityClass;
private SessionFactory sessionFactory;
public GenericDaoHibernate(Class<? extends T> entityClass) {
this.entityClass = entityClass;
}
public GenericDaoHibernate() {
}
@Autowired
private void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
Assertor.assertNotNull(sessionFactory);
}
public Session currentSession() {
return getSessionFactory().getCurrentSession();
}
@SuppressWarnings("unchecked")
@Override
public I save(T entity) {
// Transaction transaction = currentSession().beginTransaction();
I id = (I) currentSession().save(entity);
// transaction.commit();
return id;
}
当我在save
上调用GenericService
方法时,我希望spring为hibernate Session创建事务,但是没有创建事务,我在GenericDaoHibernate.save
方法中得到了这个错误:
org.hibernate.HibernateException: save is not valid without active transaction
我的服务层的spring配置文件是:
<!-- Hibernate 4 SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"
p:dataSource-ref="dataSource" p:packagesToScan="com.javahelp.domain.impl">
<property name="configLocations">
<array>
<value>classpath:META-INF/hibernate/hibernate.cfg.xml</value>
</array>
</property>
</bean>
<!-- A transaction manager for working with Hibernate session methods.
Without this transaction manager none method of hibernate session works -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- enable scanning for @Transactional annotation -->
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- autodetect all spring @Service beans in package com.javahelp.service
(service layer) -->
<context:component-scan base-package="com.javahelp.service" />
因此,当我不依赖于Spring @Transactional支持并通过org.hibernate.Session
开始/提交事务时,一切正常,我没有错误。
为什么spring不为GenericSerice调用的方法提供事务?
BTW,GenericService和AnswerService没有接口。
修改即可。这是HibernateTransactionManager.doGetTransaction
方法返回的事务:
txObject HibernateTransactionManager$HibernateTransactionObject (id=190)
connectionHolder null
newSession false
newSessionHolder false
previousIsolationLevel null
savepointAllowed false
sessionHolder null
我也改变了我的服务以使用接口,但它没有帮助。
答案 0 :(得分:7)
不知道根本原因,但从我的休眠配置中删除以下属性为我解决了这个问题。
<prop key="hibernate.current_session_context_class">thread</prop>
在此forum
上找到答案 1 :(得分:1)
getCurrentSession()
:获得当前会话。
创建一个与上下文会话不同的新会话
openSession()
:返回:创建的会话。
答案 2 :(得分:0)
我在我的entitymanager中使用org.springframework.orm.jpa.JpaTransactionManager作为我的TransactionManager和Hibernate适配器。
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="packagesToScan" value="domain"/>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
<entry key="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver" />
<entry key="hibernate.show_sql" value="false" />
<entry key="hibernate.multiTenancy" value="SCHEMA" />
<entry key="hibernate.multi_tenant_connection_provider" value-ref="mySQLMultiTenantConnectionProvider" />
<entry key="hibernate.tenant_identifier_resolver" value-ref="tenantIdentifierResolver" />
</map>
</property>
</bean>
我建议更改此配置。
但是如果你不这样做,请尝试在方法doGetTransaction中调试HibernateTransactionManager,看看会发生什么。
答案 3 :(得分:0)
您应该告诉哪些方法或类需要Spring提供跨国支持。 @Transnational Annotation(可以在方法或类级别指定)保证带注释的方法和类的跨国行为,但不保证整个应用程序的跨国行为。
答案 4 :(得分:-1)
也为您的dao方法添加@Transactional注释。