Spring启动hibernate没有事务正在进行中

时间:2018-06-01 19:37:25

标签: java spring hibernate spring-boot jpa

我正在使用spring boot,它完美地让我成为实体经理。我决定从实体管理器测试获取会话工厂并将其用作示例。但我得到了下一个问题:javax.persistence.TransactionRequiredException: no transaction is in progress

属性

spring.datasource.url= jdbc:postgresql://localhost:5432/ring
spring.datasource.username=postgres
spring.datasource.password=root

spring.jpa.show-sql = false
spring.jpa.properties.hibernate.format_sql=false

#Note: The last two properties on the code snippet above were added to suppress an annoying exception
# that occurs when JPA (Hibernate) tries to verify PostgreSQL CLOB feature.
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false

spring.jpa.properties.hibernate.current_session_context_class = org.springframework.orm.hibernate5.SpringSessionContext

服务类

package kz.training.springrest.service;

import kz.training.springrest.entity.User;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;

@Service
public class UserService {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void insertUser(User user) {
        SessionFactory sessionFactory = entityManager.unwrap(Session.class).getSessionFactory();
        Session session = sessionFactory.getCurrentSession();
        session.save(user);
    }

}

转轮

package kz.training.springrest.run;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication
@EntityScan("kz.training.springrest.entity")
@EnableTransactionManagement
@ComponentScan(basePackages="kz.training.springrest")
public class SpringrestApplication {

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

你有任何想法如何解决它?

2 个答案:

答案 0 :(得分:7)

我不太明白为什么你要使你的服务方法如此不必要地复杂化。你应该只是这样做

@Transactional
public void insertUser(User user) {
  entityManager.persist( user );
}

如果您需要访问本机Hibernate Session,您可以直接打开并直接使用Session,如下所示:

@Transactional
public void doSomethingFancyWithASession() {
  Session session = entityManager.unwrap( Session.class );
  // use session as needed
}

这里的概念是Spring使用EntityManager注释为您提供了一个功能齐全的@PersistenceContext实例。该实例将安全地用于您的spring bean正在执行的当前线程。

其次,通过使用@Transactional,这会导致Spring的事务管理自动确保EntityManager绑定到事务,无论是RESOURCE_LOCAL还是{ {1}}事务基于您的环境配置。

由于呼叫JTA,您已遇到问题。

正在发生的事情是Spring创建了#getCurrentSession(),然后当你调用EntityManager时在你的方法中,你要求Hibernate创建一个没有绑定到由#getCurrentSession()注释启动的交易。简而言之,它基本上类似于以下内容:

@Transactional

所以按照我上面提到的范例,你应该不再遇到问题。如果您正确允许Spring为您注入EntityManager entityManager = entityManagerFactory.createEntityManager(); entityManager.getTransaction().begin(); Session aNewSession = entityManager.unwrap( Session.class ) .getFactory() .getCurrentSession(); // at this point entityManager is scoped to a transaction // aNewSession is not scoped to any transaction // this also likely uses 2 connections to the database which is a waste 实例,则永远不需要在Spring环境中调用#getCurrentSession()#openSession()

答案 1 :(得分:0)

将Spring Boot应用程序部署到WebLogic Server时,我也遇到同样的错误。 (即使我直接通过Eclipse(或部署到Tomcat)运行它,也可以正常工作。)

我通过向UserService添加@EnableTransactionManagement解决了这个问题。