gpt4 book ai didi

java - 在存储库中保存实体不起作用 SPRING

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:55:36 34 4
gpt4 key购买 nike

我正在尝试将实体保存在存储库中,但它根本不起作用。存储库是 Autowiring 的,在运行时我使用 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));
}
}

存储库接口(interface)文件

@Repository
@Transactional
public interface MyRepository extends JpaRepository<MyData, Long> {}

我的数据文件

@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;
}
}

应用配置文件

@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:

  1. EntityManager 由 Spring 自动连接到您的测试中(这个是单例的,无论如何都应该避免),其他是
  2. EntityManager 由您的 ApplicationConfiguration 中配置的 EntityManagerFactory 创建。

与此同时,由于您配置了 Hibernate SessionFactory,您还有另一个 session 与上述 2 个 EntityManagers 一起运行。此外,由于配置了 HibernateTransactionManager,所有由 @Transactional 创建的事务都绑定(bind)到由 SessionFactoryEntityManager 创建的 Hibernate session 被你的 Repository 使用,当然没有办法知道它。这就是当您的 Repository 尝试保留数据时抛出 TransactionRequiredException 的原因。

要修复它,您可以考虑删除 Hibernate 的 SessionFactory 并将事务管理器切换为 JpaTransactionManager。然后,存储库上的 @Transactional 将产生创建新事务并将其绑定(bind)到 Spring 已知的现有 EntityManager 的效果。

需要注意的是,您的 TestClass 上的 @Transactional 根本没有帮助,因为此类的实例不是由 Spring 实例化和管理的。为了使这项工作正常进行,需要按照此处所述提供事务测试类的正确配置:http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html .

希望这对您有所帮助。

关于java - 在存储库中保存实体不起作用 SPRING,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30122829/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com