[英]Saving entity in repository does not work SPRING
I'm trying to save entity in repository but it does not work at all. 我正在尝试在存储库中保存实体,但它根本不起作用。 Repository is Autowired and in runtime I use saveAndFlush to save entity. 存储库是自动装配的,在运行时我使用saveAndFlush来保存实体。 I'm using PostgreSQL. 我正在使用PostgreSQL。 Above test methods I added comments with explanation what is going on. 在上面的测试方法中,我添加了评论并解释了发生了什么。 I expected that method saveAndFlush should work but it did not. 我期望saveAndFlush方法可以工作,但它没有。 I can not find why. 我找不到原因。
@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 interface file 存储库接口文件
@Repository
@Transactional
public interface MyRepository extends JpaRepository<MyData, Long> {}
MyData file 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 file 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();
}
...
}
For starter, you're actually working on 2 different EntityManager
in your non-working test case: 对于初学者,您实际上在非工作测试用例中处理2个不同的EntityManager
:
EntityManager
autowired into your test by Spring (this one is singleton and should be avoided anyway) ,other is EntityManager
自动连接到您的测试由Spring(这个人是独立的,并无论如何都应该避免),另一种是 EntityManager
created by the EntityManagerFactory
configured in your ApplicationConfiguration. 由ApplicationConfiguration中配置的EntityManager
创建的EntityManagerFactory
。 At the same time, you also have another Session running along side the aforementioned 2 EntityManagers
due to your configuration of Hibernate SessionFactory
. 同时,由于您配置了Hibernate SessionFactory
,您还可以在前面提到的2个EntityManagers
旁边运行另一个Session。 Additionally, because of the configured HibernateTransactionManager
, all transactions created by @Transactional
are bound to the Hibernate's Session created by SessionFactory
and the EntityManager
used by your Repository certainly has no way to know about it. 另外,由于配置了HibernateTransactionManager
,由@Transactional
创建的所有事务都绑定到由SessionFactory
创建的Hibernate会话,并且您的Repository使用的EntityManager
当然无法知道它。 This is why TransactionRequiredException
was thrown when your Repository tried to persist data. 这就是当您的存储库尝试保留数据时抛出TransactionRequiredException
原因。
To fix it, you may consider removing the Hibernate's SessionFactory
and switch the transaction manager to a JpaTransactionManager
. 要修复它, 您可以考虑删除Hibernate的SessionFactory
并将事务管理器切换到JpaTransactionManager
。 Then, @Transactional
on your Repository will have the effect of creating a new transaction and binding it to the existing EntityManager
that is known to Spring. 然后,您的Repository上的@Transactional
将具有创建新事务并将其绑定到Spring已知的现有EntityManager
的效果。
One side note is that the @Transactional
on your TestClass doesn't help at all as the instance of this class is not instantiated and managed by Spring. 一方面注意,TestClass上的@Transactional
根本没有帮助,因为Spring没有实例化和管理此类的实例。 To make this work, a proper configuration of transactional test class needs to be provided as described here: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html . 为了使其工作,需要提供正确的事务测试类配置,如下所述: http : //docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html 。
Hope this helps. 希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.