【问题标题】:Questions regarding Spring boot and JPA关于 Spring Boot 和 JPA 的问题
【发布时间】:2018-05-08 02:17:03
【问题描述】:

我正在使用 Spring Boot、Spring MVC 和 Hibernate 开发一个项目。我遇到了这个问题,这已经花了我 2 天的时间。

我的项目是对 Twitter 的模仿。当我开始做这个项目时,我使用 JPA 来获取 Hibernate Session。这是我的 BaseDaoImpl 类中的代码:

@Autowired
private EntityManagerFactory entityManagerFactory;

public Session getSession(){

return entityManagerFactory.createEntityManager().unwrap(Session.class);

}

在我的服务类中,我使用了@Transactional 注释:

@Service("userServ")
@Transactional(propagation=Propagation.REQUIRED, readOnly=false,rollbackFor={Exception.class, RuntimeException.class})
public class UserServImpl implements IUserServ {}

最后,我的主要课程的概述:

@SpringBootApplication
@EnableTransactionManagement
@EntityScan(basePackages = {"edu.miis.Entities"})
@ComponentScan({"edu.miis.Controllers","edu.miis.Service","edu.miis.Dao"})
@EnableAutoConfiguration
@Configuration
public class FinalProjectSpringbootHibernateDruidApplication {

    public static void main(String[] args) {
        SpringApplication.run(FinalProjectSpringbootHibernateDruidApplication.class, args);
    }



}

当我使用此设置时,一切似乎都很好 - 直到我能够提升到我开始添加“发布”功能的程度。我可以将帖子和 cmets 添加到数据库中。但是,我很多次都无法做到这一点。每次我添加最多 4 个帖子时,程序就会停止运行 - 没有异常,没有错误 - 页面只是卡在那里。

我在网上查了一下,发现问题可能是由于 entityManagerFactory 造成的。有人告诉我 entityManagerFactory.createEntityManager().unwrap(Session.class) 打开新的 Hibernate 会话,而不是返回现有会话的传统 sessionFactory.getCurrentSession()

所以我开始研究它。我将我的 Dao 配置更改为:

@Autowired
    private EntityManagerFactory entityManagerFactory;
public Session getSession(){

        Session session = entityManagerFactory.unwrap(SessionFactory.class).getCurrentSession();

        return session;
    }

我的想法是使用自动装配的 EntityManagerFactory 返回一个 Hibernate SessionFactory,以便随后可以使用 getCurrentSession 方法。

但后来我遇到了问题:

由于我配置了这个设置,任何涉及从控制器输入到 service-dao-database 的操作都会调用异常:No Transaction Is In Progress

但奇怪的是:虽然系统因为没有可见的事务在进行而崩溃,但 Hibernate 仍然会生成新的 SQL 语句,并且数据仍然会同步到数据库中。

谁能帮我解决这个问题?

衷心感谢!

【问题讨论】:

  • 我进行了一些测试。这是我所做的:我删除了@Transactional 注释,并切换回 entityManager.unwrap。你知道吗?如果没有注释,事务仍然会被提交。我认为现在很清楚问题在于我根本没有使用 spring 事务管理器来管理休眠会话。
  • 但还是没有进展
  • 不要使用Session,只需使用Entitymanager。尝试使用普通的休眠会使事情变得过于复杂并且不会添加任何东西(通常是 JPA 的当前状态)。只需使用 JPA API 并删除您的 hack。
  • 您能说得更具体些吗?我不完全知道如何使用 JPA api...
  • 你可以google一下spring boot jpa教程。 baeldung 有一个很好的教程。

标签: java spring hibernate spring-mvc spring-boot


【解决方案1】:

关注@M。 Deinum的建议,我终于解决了这个问题。

The reason why the @Transactional annotation didn't work in my code in the first place, was because in my original code, I used plain Hibernate features - Session, SessionFactory, getCurrentSession() etc. 

In order for these features to work, I need to specifically configure the transaction manager into a Hibernate Transaction Manager (under default setting, Spring boot autowires a JPA transaction manager).

But the problem is: most of methods that were used to support Hibernate features are now deprecated. Now, the JPA method is the mainstream.

Use EntityManager instead of Session/
Use EntityManager.persist instead of Session.save
Use EntityManager.merge instead of Session.update
Use EntityManager.remove instead of Session.remove.


That's all.

Thanks!

【讨论】:

    猜你喜欢
    • 2017-02-02
    • 2021-06-15
    • 2019-02-24
    • 2020-01-04
    • 1970-01-01
    • 2020-10-19
    • 2023-03-28
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多