Spring Hibernate:Generic Dao 添加原因 - org.hibernate.TransactionException:不支持嵌套事务
Posted
技术标签:
【中文标题】Spring Hibernate:Generic Dao 添加原因 - org.hibernate.TransactionException:不支持嵌套事务【英文标题】:Spring Hibernate : Generic Dao addition causes - org.hibernate.TransactionException: nested transactions not supported 【发布时间】:2013-05-10 03:57:04 【问题描述】:我的项目中有一个分层架构。
为了防止冗余,我创建了一个非常基本的通用 dao:
public interface GenericDAO
public <T> T getItemById(long id, Class<T> c);
public <T> int save(T... objectsToSave);
public <T> int saveOrUpdate(T... objectsToSave);
public <T> int delete(T... objectsToDelete);
.
.
现在我所有的其他 dao 都使用这个通用 dao 作为私有字段,以便使用它的基本方法: 即:
@Repository
public class UserDAOHibernateImpl implements UserDao
@Autowired
private GenericDAO dao;
@Override
public int deleteUser(User u)
return dao.delete(u);
.
.
.
我的服务是这样的:
@Service
public class UserServiceHibernateImpl implements UserService
@Autowired
private UserDao userDao;
@Transactional(readOnly = false)
public int deleteUser(User u)
return userDao.deleteUser(u);
.
.
.
问题是:
ApplicationContext ctx = new ClassPathXmlApplicationContext("root-context.xml");
UserServiceHibernateImpl d = ctx.getBean("userServiceHibernateImpl", UserServiceHibernateImpl.class);
User u = d.getUserById(1);
抛出异常:
Exception in thread "main" org.hibernate.TransactionException: nested transactions not supported
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:152)
at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1426)
at src.com.plantaware.model.dao.impl.hibernate.GenericDAOHibernateImpl.getItemById(GenericDAOHibernateImpl.java:80)
at src.com.plantaware.model.dao.impl.hibernate.GenericDAOHibernateImpl$$FastClassByCGLIB$$be31a192.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
删除
@Autowired
private GenericDAO dao;
我的服务将解决这个问题,但这意味着我必须在我的每个服务上使用冗余代码,这完全没有使用通用 dao 的意义。
任何想法为什么?
顺便说一句:我正在使用 CGLIB 代理,因为没有它我会得到“名为 'X' 的 Bean 必须是 Y 类型,但实际上是 [$Proxy] 类型”异常
谢谢..
【问题讨论】:
【参考方案1】:您正在将特定于 Spring 的声明式事务管理 (@Transactional
) 与特定于 Hibernate 的手动事务管理 (beginTransaction()
等) 混合在一起。
如果你使用@Transactional
,你不需要在你的DAO中调用beginTransaction()
等,因为Spring已经提供了必要的事务管理。从您的 DAO 中删除手动事务管理代码。
另请参阅:
11. Transaction Management【讨论】:
你的权利!虽然我没有提到它,但我有 session.beginTransaction();在我的道内。删除它解决了我的问题!谢谢!【参考方案2】:TransactionException: nested transactions not supported
意味着无论何时你开始一个事务,你都不能在其中开始另一个事务。你首先需要完成它。在这里,不要在 dao 中自动装配 dao
@Repository
public class UserDAOHibernateImpl implements UserDao
@Autowired
private GenericDAO dao; // this is not acceptable.
@Override
public int deleteUser(User u)
return dao.delete(u);
.
.
.
所有业务逻辑都必须在服务层内。 Dao 只针对 db 访问。将所有必要的 dao bean 放入您的服务中。
【讨论】:
那么我应该如何从 UserDAOHibernateImpl 内部调用 GenericDAO 呢?以上是关于Spring Hibernate:Generic Dao 添加原因 - org.hibernate.TransactionException:不支持嵌套事务的主要内容,如果未能解决你的问题,请参考以下文章
尝试使用 EhCache 使用 Spring 和扩展 Hibernate 的 JpaRepository 的自定义 GenericDao 接口