Java 在存储库中保存实体不起作用 SPRING
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30122829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Saving entity in repository does not work SPRING
提问by Marcin Lagowski
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. I'm using PostgreSQL. Above test methods I added comments with explanation what is going on. I expected that method saveAndFlush should work but it did not. I can not find why.
我正在尝试将实体保存在存储库中,但它根本不起作用。存储库是自动装配的,在运行时我使用 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 interface file
存储库接口文件
@Repository
@Transactional
public interface MyRepository extends JpaRepository<MyData, Long> {}
MyData file
我的数据文件
@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
应用配置文件
@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();
}
...
}
采纳答案by Phoenix VN
For starter, you're actually working on 2 different EntityManager
in your non-working test case:
首先,您实际上EntityManager
在非工作测试用例中处理2 个不同的测试用例:
EntityManager
autowired into your test by Spring (this one is singleton and should be avoided anyway) ,other isEntityManager
created by theEntityManagerFactory
configured in your ApplicationConfiguration.
EntityManager
由 Spring 自动连接到您的测试中(这个是单例的,无论如何都应该避免),另一个是EntityManager
由EntityManagerFactory
您的 ApplicationConfiguration 中的配置创建。
At the same time, you also have another Session running along side the aforementioned 2 EntityManagers
due to your configuration of Hibernate SessionFactory
. 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. This is why TransactionRequiredException
was thrown when your Repository tried to persist data.
同时,EntityManagers
由于您的 Hibernate 配置,您还有另一个 Session 与上述 2 一起运行SessionFactory
。此外,由于配置了HibernateTransactionManager
,所有创建的事务@Transactional
都绑定到创建的 Hibernate 会话,SessionFactory
并且EntityManager
您的 Repository 使用的当然无法知道它。这就是为什么TransactionRequiredException
在您的存储库尝试保留数据时抛出的原因。
To fix it, you may consider removing the Hibernate's SessionFactory
and switch the transaction manager to a 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.
要修复它,您可以考虑删除 HibernateSessionFactory
并将事务管理器切换到JpaTransactionManager
. 然后,@Transactional
在您的 Repository 上将创建一个新事务并将其绑定EntityManager
到 Spring 已知的现有事务。
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. 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.
一方面要注意的是,@Transactional
您的 TestClass 上的 根本没有帮助,因为此类的实例不是由 Spring 实例化和管理的。为了完成这项工作,需要提供事务测试类的正确配置,如下所述:http: //docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html。
Hope this helps.
希望这可以帮助。