我正在尝试将实体保存在存储库中,但它根本不起作用。存储库是自动连线的,在运行时中,我使用saveAndFlush来保存实体。我正在使用PostgreSQL。在测试方法上方,我添加了注释并解释了发生的情况。我希望该方法saveAndFlush应该可以,但不能。我找不到原因。
@Transactional public class TestClass{ @Autowired private MyRepository repository; @Autowired private EntityManager entityManager; // Working version public void writingToRepositoryWorking() { entityManager.getTransaction().begin(); entityManager.persist(new MyData(99)); entityManager.getTransaction().commit(); } // not working and throws exception : // TransactionRequiredException: no transaction is in progress public void writingToRepositoryNotWorking() { repository.saveAndFlush(new MyData(99)); } // not working, no exception, no data in repository, // but auto generated ID is incremented public void writingToRepositoryNotWorkingToo() { repository.save(new MyData(99)); } }
存储库接口文件
@Repository @Transactional public interface MyRepository extends JpaRepository<MyData, Long> {}
MyData文件
@Entity(name = "myData") public class MyData { @Id @GeneratedValue(strategy = GenerationType.AUTO) long id; private int testValue; public MyData() { } public BugData(int testValue) { this.testValue = testValue; } public long getId() { return id; } public int getTestValue() { return testValue; } }
ApplicationConfiguration文件
@Configuration @EnableJpaRepositories("com.mypackage.app") @EnableTransactionManagement @PropertySource("classpath:application.properties") @EnableWebMvc class ApplicationConfiguration extends WebMvcConfigurationSupport { @Value("${jdbc.url}") private String KEY_JDBC_URL; @Value("${jdbc.username}") private String KEY_JDBC_USERNAME; @Value("${jdbc.password}") private String KEY_JDBC_PASSWORD; @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } @Bean @Autowired public LocalSessionFactoryBean sessionFactory(DataSource dataSource) { LocalSessionFactoryBean factory = new LocalSessionFactoryBean(); factory.setDataSource(dataSource); factory.setPackagesToScan("com.mypackage.app"); factory.setHibernateProperties(hibernateProperties()); return factory; } public Properties hibernateProperties() { Properties properties = new Properties(); properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect"); properties.setProperty("hibernate.show_sql", "true"); properties.setProperty("hibernate.hbm2ddl.auto", "update"); return properties; } @Bean @Autowired public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) { return new HibernateTransactionManager(sessionFactory); } @Bean public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("org.postgresql.Driver"); dataSource.setUrl(KEY_JDBC_URL); dataSource.setUsername(KEY_JDBC_USERNAME); dataSource.setPassword(KEY_JDBC_PASSWORD); return dataSource; } @Bean public EntityManagerFactory entityManagerFactory() { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource()); em.setPackagesToScan("com.mypackage.app"); em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); em.setJpaProperties(hibernateProperties()); em.afterPropertiesSet(); return em.getObject(); } @Bean public EntityManager entityManager(EntityManagerFactory entityManagerFactory) { return entityManagerFactory.createEntityManager(); } ... }
对于初学者,您实际上EntityManager在不工作的测试用例中使用两种不同的方法:
EntityManager
EntityManagerFactory
同时,EntityManagers由于Hibernate的配置,您还将在上述2旁边运行另一个Session SessionFactory。另外,由于配置了HibernateTransactionManager,所有由创建的事务@Transactional都绑定到由存储库创建SessionFactory和EntityManager使用的Hibernate会话,因此肯定无法了解它。这就是为什么TransactionRequiredException在您的存储库尝试保留数据时引发的原因。
EntityManagers
SessionFactory
HibernateTransactionManager
@Transactional
TransactionRequiredException
要解决此问题, 您可以考虑删除HibernateSessionFactory,并将事务管理器切换为JpaTransactionManager。然后,@Transactional在您的存储库上将具有创建新事务并将其绑定EntityManager到Spring已知的现有事务的作用。
JpaTransactionManager
值得一提的是,@Transactional您的TestClass上的完全没有帮助,因为此类的实例没有由Spring实例化和管理。为了使这项工作有效,需要按如下所述提供正确的事务测试类配置:http : //docs.spring.io/spring/docs/current/spring-framework- reference/html/testing.html。
希望这可以帮助。