エンティティをリポジトリに保存しようとしていますが、まったく機能しません。リポジトリは自動接続されており、実行時に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();
}
...
}
手始めに、実際には、非稼働テストケースで2つの異なるEntityManager
に取り組んでいます。
EntityManager
Springによってテストに自動配線されます(これはシングルトンであり、とにかく回避する必要があります)、その他はEntityManager
は、ApplicationConfigurationで構成されたEntityManagerFactory
によって作成されます。同時に、Hibernate EntityManagers
の構成により、前述の2 SessionFactory
と並行して別のセッションも実行されます。さらに、HibernateTransactionManager
が構成されているため、@Transactional
によって作成されたすべてのトランザクションは、SessionFactory
によって作成されたHibernateのセッションにバインドされ、リポジトリで使用されるEntityManager
には確実にそれについて知る方法はありません。これが、リポジトリがデータを永続化しようとしたときにTransactionRequiredException
がスローされた理由です。
これを修正するには、HibernateのSessionFactory
を削除して、トランザクションマネージャをJpaTransactionManager
に切り替えることを検討してください。次に、リポジトリの@Transactional
は、新しいトランザクションを作成し、それをSpringが認識している既存のEntityManager
にバインドする効果があります。
補足として、このクラスのインスタンスはSpringによってインスタンス化および管理されないため、TestClassの@Transactional
はまったく役に立ちません。これを機能させるには、トランザクションテストクラスの適切な構成をここで説明するように提供する必要があります。 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing。 html 。
お役に立てれば。