【问题标题】:No EntityManager with actual transaction available for current thread没有可用于当前线程的具有实际事务的 EntityManager
【发布时间】:2018-04-14 19:28:42
【问题描述】:

运行sampleTest() 方法时,this.itemRepository.deleteAll() 会出现此错误。

@ExtendWith(SpringExtension.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@SpringBootTest
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Rollback(false)
public class ScheduleTests {

    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleTests.class);

    @Autowired
    private ScheduleRepository scheduleRepository;

    @Autowired
    private ItemRepository itemRepository;

    @Autowired
    private ItemQualifierRepository itemQualifierRepository;

    @Autowired
    private MappingRepository mappingRepository;

    @BeforeAll
    public void setUp() {
        restoreInitialData();
        LOGGER.info("Initial data restored");
    }

    @Test
    public void sampleTest() {
        File feed = new File("target/test-classes/TestFeedOK.json");
        Feed.ingest(feed);
        LOGGER.info("Feed {} ingested", feed.getName());
    }

    private void restoreInitialData() {
        this.itemRepository.deleteAll();
        this.mappingRepository.deleteByTableName("event");
    }
}

restoreInitialData()添加@Transactional注解并不能解决问题-https://stackoverflow.com/a/32552558/3536552

你知道怎么解决吗?

【问题讨论】:

  • 你有没有尝试让整个班级@Traansactional
  • @pvpkiran 是的,我试过了,但没有帮助
  • 您使用的是哪个版本的 Spring Boot。因为在最新版本中 AutoConfigureTestDatabase 已弃用
  • @pvpkiran 我用2.0.0.M5
  • 我认为问题是restoreInitialData 是从设置中调用的,这是一个@BeforeAll 方法。可能是春天还没有介入创建交易。只需将其更改为@BeforeEach 并检查并使用@Transactional。只是猜测

标签: java spring hibernate spring-boot


【解决方案1】:

我认为问题是 restoreInitialData 是从 setup 调用的,这是一个 @BeforeAll 方法。 Spring 那时还没有介入创建事务。只需将其更改为@BeforeEach 并检查并使用@Transactional。 如果您希望某事只执行一次。试试这个方法

private static boolean setUpIsDone = false;
.....
public void setUp() {
    if (setUpIsDone) {
        return;
    }
    // do the setup
    setUpIsDone = true;
}

【讨论】:

  • 恐怕不行。
【解决方案2】:

默认情况下,Spring 提供了InterfaceClass 的实现,但在测试环境中,spring 希望您提供它的实现。所以使用下面的代码来提供EntityManager的实现。

PersistenceJPAConfig.java

import java.util.Properties;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class PersistenceJPAConfig {

    @Autowired
    private Environment environment; 

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan(new String[] { "com.example.db.model" });

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalProperties());
        return em;
    }

    @Bean
    public DataSource dataSource() {
        String driverClassName = environment.getProperty("spring.datasource.driverClassName");
        String url = environment.getProperty("spring.datasource.url");
        String username = environment.getProperty("spring.datasource.username");
        String password = environment.getProperty("spring.datasource.password");

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;
    }

    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);

        return transactionManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
        return new PersistenceExceptionTranslationPostProcessor();
    }

    Properties additionalProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.id.new_generator_mappings","false");
        return properties;
    }
}

【讨论】:

    猜你喜欢
    • 2017-10-09
    • 1970-01-01
    • 2018-01-23
    • 2016-02-20
    • 2017-06-01
    • 1970-01-01
    • 2017-09-10
    • 2015-11-23
    相关资源
    最近更新 更多