CodeDevMaster 2022-08-11 16:35 采纳率: 100%
浏览 128
已结题

Srping Boot集成Hibernate,使用SessionFactory对象进行数据库操作,事务配置及事务不生效的问题

发生背景

Srping Boot集成Hibernate,使用SessionFactory对象进行数据库操作

问题

事务配置及事务不生效的问题

相关代码

pom.xml

   <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.8.RELEASE</version>
        <relativePath/> 
    </parent>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>

HibernateConfig配置

@Configuration
@Slf4j
public class HibernateConfig {
    @Autowired
    private DataSource dataSource;

    /**
     * 配置会话工厂
     */
    @Bean
    public LocalSessionFactoryBean sessionFactoryBean() {
        LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
        // 设置数据源
        sessionFactoryBean.setDataSource(dataSource);
        // entity包路径
        sessionFactoryBean.setPackagesToScan("cn.ybzy.demo.entity");
          // 配置hibernate属性
        Properties properties = new Properties();
        // sql方言
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        // 自动创建|更新|验证数据库表结构
        properties.setProperty("hibernate.hbm2ddl.auto", "update");
        // 输出sql到控制台
        properties.setProperty("hibernate.show_sql", "true");
        // 打印漂亮的sql
        properties.setProperty("hibernate.format_sql", "true");
        properties.setProperty("hibernate.current_session_context_class", "org.springframework.orm.hibernate5.SpringSessionContext");
        sessionFactoryBean.setHibernateProperties(properties);

        return sessionFactoryBean;
    }


    /**
     * 配置事务管理器
     */
    @Bean
    public HibernateTransactionManager transactionManager() {
        HibernateTransactionManager transactionManager = new HibernateTransactionManager();
        // 设置 sessionFactory
        transactionManager.setSessionFactory(sessionFactoryBean().getObject());
        return transactionManager;
    }
}

Dao层

@Repository
public class MyUserDaoImpl implements IMyUserDao {
    @Autowired
    private SessionFactory sessionFactory;

    Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }


//    @Autowired
//    private EntityManagerFactory entityManagerFactory;
//
//        Session getCurrentSession() {
//            return entityManagerFactory.unwrap(SessionFactory.class).getCurrentSession();
//    }

    @Override
    public void saveUser(User user) {
        getCurrentSession().save(user);
    }
}

Service层

@Transactional(rollbackFor = Exception.class)
@Service
public class UserServiceImpl implements UserService {
    
     @Autowired
     private IMyUserDao userDao;

    @Override
    public void saveUser(User user) {
        userDao.saveUser(user);
        int a=1/0;
    }
}
运行结果及报错内容

1.当service层使用@Transactional(rollbackFor = Exception.class)注解。数据查询正常,但是插入事务是生效的。报错如下,

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Aug 11 16:18:12 CST 2022
There was an unexpected error (type=Internal Server Error, status=500).
org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder
java.lang.ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder
    at org.springframework.orm.hibernate5.HibernateTransactionManager.doGetTransaction(HibernateTransactionManager.java:407)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:347)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:574)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:361)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy77.saveUser(Unknown Source)
    at cn.ybzy.demo.controller.Controller.insert(Controller.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)

2.当service层不使用@Transactional(rollbackFor = Exception.class)注解。数据插入、查询正常,但插入若异常事务不生效。

我的解答思路和尝试过的方法

出现org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder错误。使用
@SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class})可解决,但是事务失效。

如果service层类或方法不使用@Transactional(rollbackFor = Exception.class)注解,则事务不生效,但是异常报错更加正常

Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Thu Aug 11 16:21:47 CST 2022
There was an unexpected error (type=Internal Server Error, status=500).
/ by zero
java.lang.ArithmeticException: / by zero
    at cn.ybzy.demo.service.impl.UserServiceImpl.saveUser(UserServiceImpl.java:25)
    at cn.ybzy.demo.controller.Controller.insert(Controller.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
我想要达到的结果

事务生效且报错信息正常。

There was an unexpected error (type=Internal Server Error, status=500).
/ by zero
java.lang.ArithmeticException: / by zero
    at cn.ybzy.demo.service.impl.UserServiceImpl.saveUser(UserServiceImpl.java:25)
    at cn.ybzy.demo.controller.Controller.insert(Controller.java:31)
  • 写回答

1条回答 默认 最新

  • a1767028198 2022-08-11 18:46
    关注

    java.lang.ClassCastException: org.springframework.orm.jpa.EntityManagerHolder cannot be cast to org.springframework.orm.hibernate5.SessionHolder
    ,你这配置又是各处粘贴复制来的吧

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 8月21日
  • 已采纳回答 8月13日
  • 修改了问题 8月11日
  • 创建了问题 8月11日

悬赏问题

  • ¥20 keepalive配置业务服务双机单活的方法。业务服务一定是要双机单活的方式
  • ¥50 关于多次提交POST数据后,无法获取到POST数据参数的问题
  • ¥15 win10,这种情况怎么办
  • ¥15 如何在配置使用Prettier的VSCode中通过Better Align插件来对齐等式?(相关搜索:格式化)
  • ¥100 在连接内网VPN时,如何同时保持互联网连接
  • ¥15 MATLAB中使用parfor,矩阵Removal的有效索引在parfor循环中受限制
  • ¥20 Win 10 LTSC 1809版本如何无损提升到20H1版本
  • ¥50 win10 LTSC 虚拟键盘不弹出
  • ¥30 微信小程序请求失败,网页能正常带锁访问
  • ¥15 Matlab求解微分方程,如何用fish2d进行预优?