Spring Data CRUD 存储库:save 方法不起作用

6 java spring jpa

这根本与 Spring Boot 无关。

我的英语还可以更好。

使用下面的 Spring Data 配置我尝试执行 DML 请求。

确切的CrudRepository#save方法。

然而,执行 Spring 的 CrudRepository#save 方法我接下来会得到:

  1. 仅选择按功能记录hibernate.show_sql
  2. 对于 hibernate.show_sql 日志记录,没有执行“插入”或“更新”语句。
  3. 数据库根本没有任何变化。

=================================================== ==

不确定,但看起来像是交易问题。

那个时候好像还没有交易,

因此事务外 CRUD Repos 无法执行 DML 请求,包括CrudRepository#save.

也许是配置有问题?请看一下,并随时询问任何其他信息。

更新: 下一个不良实践解决方法帮助我实现了“更新”语句的执行。

//(autowired, shared entity manager)
entityManager.joinTransaction();
repository.save(user);
Run Code Online (Sandbox Code Playgroud)

然而,这仍然是一种不好的做法。在这种情况下,Spring 的目的就失去了。无论如何,我需要使用基于声明性代码的事务管理。问题仍然存在: 我的配置有什么问题?@Transactional 注解仍然不起作用

用户域实体:

@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User
{
    @Id
    @Column(name = "id_pk", length = 11)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idPk;

    @Column(name = "user_id", length = 25, nullable = false, unique = true)
    private String userId;

    @Column(name = "email_addr", length = 120)
    private String email;
}
Run Code Online (Sandbox Code Playgroud)

特定领域的 Spring Data CRUD 存储库声明:

public interface UserRepository extends CrudRepository<User, Integer> {
  //nothing specific
}
Run Code Online (Sandbox Code Playgroud)

Spring (无引导)基于代码的配置:

@EnableJpaRepositories(basePackages = "***",
        transactionManagerRef = "jpaTransactionManager")
@EnableTransactionManagement
public class DataConfig
{
    @Bean
    public EntityManagerFactory entityManagerFactory()
    {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(dataSource());
        factory.setPackagesToScan(DOMAIN_ENTITY_SCAN_PACKAGE);
        factory.setJpaVendorAdapter(getVendorAdapter());
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    private HibernateJpaVendorAdapter getVendorAdapter()
    {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(Boolean.TRUE);
        return vendorAdapter;
    }

    @Bean
    public JpaTransactionManager jpaTransactionManager()
    {
        JpaTransactionManager txManager = new JpaTransactionManager();
        txManager.setEntityManagerFactory(entityManagerFactory());
        txManager.afterPropertiesSet();
        return txManager;
    }
}
Run Code Online (Sandbox Code Playgroud)

小智 2

最后,我为我的案例找到了解决方案。

由于我使用的 Spring 没有 Boot 部分,因此我必须配置自定义WebApplicationInitializer来让 Spring 管理应用程序入口点:

public class MainWebAppInitializer implements WebApplicationInitializer
{
    @Override
    public void onStartup(final ServletContext sc)
    {
        AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
        root.register(WebAppConfiguration.class, DataConfig.class);
        sc.addListener(new ContextLoaderListener(root));
        
        ...other not related code ommited
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,因为我已经使用AnnotationConfigWebApplicationContext#register注册了两个配置类( WebAppConfiguration.classDataConfig.class ),所以我认为使用@Configuration 注释配置将是多余的。

那时我错了。

要正确注册TransactionManager ,您应该使用@Configuration注释您的 Jpa Config 类。

因此,我设法用@Configuration注释我的配置类,这解决了我的问题。

现在 Spring CRUD 存储库能够对数据库运行 DML 查询(在 #save 方法的帮助下)。准确地说:现在存储库能够打开自己的事务并根据这些事务运行所需的查询。