Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring数据CRUD存储库:保存方法不起作用_Java_Spring_Jpa - Fatal编程技术网

Java Spring数据CRUD存储库:保存方法不起作用

Java Spring数据CRUD存储库:保存方法不起作用,java,spring,jpa,Java,Spring,Jpa,这与Spring Boot无关。 我的英语可以更好 我正在尝试对Spring数据使用下面的配置来执行DML请求 精确地crudepository#save方法 然而,执行Spring的crudepository#save方法,我将得到下一个: 只有选择被休眠。显示sql功能记录 对于hibernate.show\u sql日志记录,没有执行任何“insert”或“update”语句 数据库中没有任何更改 ==============================================

这与Spring Boot无关。

我的英语可以更好

我正在尝试对Spring数据使用下面的配置来执行DML请求

精确地
crudepository#save
方法

然而,执行Spring的crudepository#save方法,我将得到下一个:

  • 只有选择被休眠。显示sql功能记录
  • 对于hibernate.show\u sql日志记录,没有执行任何“insert”或“update”语句
  • 数据库中没有任何更改
  • ====================================================

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

    似乎在那一点上没有交易

    因此,交易外CRUD Repos无法执行DML请求, 包括
    crudepository#save

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

    更新: 下一个错误实践解决方案帮助我实现了“Update”语句的执行

    //(autowired, shared entity manager)
    entityManager.joinTransaction();
    repository.save(user);
    
    然而,这仍然是一种糟糕的实践方法。在这种情况下,弹簧的作用就失去了。 无论如何,我需要使用基于声明性代码的事务管理。 问题仍然悬而未决: 我的配置有什么问题@事务性批注仍然不起作用

    用户域实体:

    @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;
    }
    
    特定于域的Spring数据CRUD存储库声明:

    public interface UserRepository extends CrudRepository<User, Integer> {
      //nothing specific
    }
    

    我不明白,你是如何初始化数据源属性的?我无法在您给定的代码中看到

    factory.setDataSource(dataSource());
    
    您应该像下面这样设计您的配置类。使用以下两种方法:

    entityManagerFactoryRef="entityManagerFactory",
    transactionManagerRef="jpaTransactionManager"
    
    从yaml或属性文件中读取hibernate属性

    并设置您的数据源

    配置类:DataConfig

    /**
     * @author Som
     *
     */
    
    @Configuration
    @EnableJpaRepositories(basePackages="package-name",
                           entityManagerFactoryRef="entityManagerFactory",
                           transactionManagerRef="jpaTransactionManager")
    @EnableTransactionManagement
    @PropertySource(value = { "classpath:application.yml" })
    public class DataConfig {
        
        @Autowired
        private Environment environment;
        
        @Value("${datasource.myapp.maxPoolSize:10}")
        private int maxPoolSize;
        
        
        /**
         * Populate DataSourceProperties object directly from application.yml 
         *       *
         */
        
        @Bean
        @Primary
        @ConfigurationProperties(prefix = "datasource.myapp")
        public DataSourceProperties dataSourceProperties(){
            return new DataSourceProperties();
        }
        
        
        /**
         * Configure HikariCP pooled DataSource.
         * 
         */
        @Bean
        public DataSource dataSource() {
            DataSourceProperties dataSourceProperties = dataSourceProperties();
            HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder
                    .create(dataSourceProperties.getClassLoader())
                    .driverClassName(dataSourceProperties.getDriverClassName())
                    .url(dataSourceProperties.getUrl())
                    .username(dataSourceProperties.getUsername())
                    .password(dataSourceProperties.getPassword())
                    .type(HikariDataSource.class)
                    .build();
            
            dataSource.setMaximumPoolSize(maxPoolSize);
            return dataSource;
        }
        
        
        /**
         * Entity Manager Factory setup.
         * 
         */
        @Bean
        public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws NamingException {
            LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
            factoryBean.setDataSource(dataSource());
            factoryBean.setPackagesToScan(new String[] { "package-name" });
            factoryBean.setJpaVendorAdapter(jpaVendorAdapter());
            factoryBean.setJpaProperties(jpaProperties());
            return factoryBean;
        }
        
        
        
        /**
         * Provider specific adapter.
         * 
         */
        @Bean
        public JpaVendorAdapter jpaVendorAdapter() {
            HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
            return hibernateJpaVendorAdapter;
        }
     
        /**
         * Hibernate properties.
         * 
         */
        private Properties jpaProperties() {
            Properties properties = new Properties();
            properties.put("hibernate.dialect", environment.getRequiredProperty("datasource.myapp.hibernate.dialect"));
            properties.put("hibernate.hbm2ddl.auto", environment.getRequiredProperty("datasource.myapp.hibernate.hbm2ddl.method"));
            properties.put("hibernate.show_sql", environment.getRequiredProperty("datasource.myapp.hibernate.show_sql"));
            properties.put("hibernate.format_sql", environment.getRequiredProperty("datasource.myapp.hibernate.format_sql"));
            if(StringUtils.isNotEmpty(environment.getRequiredProperty("datasource.myapp.defaultSchema"))){
                properties.put("hibernate.default_schema", environment.getRequiredProperty("datasource.myapp.defaultSchema"));
            }
            return properties;
        }
     
        @Bean
        @Autowired
        public PlatformTransactionManager jpaTransactionManager(EntityManagerFactory emf) {
            JpaTransactionManager txManager = new JpaTransactionManager();
            txManager.setEntityManagerFactory(emf);
            return txManager;
        }
    
    }
    
    应用程序.yaml

    server:
      port: 8081
      servlet:
        context-path: /CRUDApp
    ---
    spring:
      profiles: local,default
    datasource:
      myapp:
        url: jdbc:h2:~/test
        username: SA
        password:
        driverClassName: org.h2.Driver
        defaultSchema:
        maxPoolSize: 10
        hibernate:
          hbm2ddl.method: create-drop
          show_sql: true
          format_sql: true
          dialect: org.hibernate.dialect.H2Dialect
    ---
    

    最后,我为我的案子找到了解决办法

    因为我使用的是没有启动部分的Spring 我必须配置自定义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
        }
    }
    
    因为我已经使用AnnotationConfigWebApplicationContext#register注册了两个配置类(WebAppConfiguration.class,DataConfig.class) 我认为用@Configuration注释configs是多余的

    那一点我错了

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

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

    现在,Spring CRUD存储库能够对DB运行DML查询(借助于#save方法)。
    精确地说:现在存储库可以打开自己的事务,并根据这些事务运行所需的查询。

    将id更改为非基本类型,以便它可以接受空值,否则,当您转到时,它将始终为PK 0insert@JLazar0谢谢你的建议,但是这一点与我上面描述的问题无关。谢谢你,Som。我隐藏了#dataSource方法,因为它的内部工作与上述问题无关。这肯定与数据源无关,因为在数据源配置方面,与db的所有通信都正常工作。正如我在上面的更新中提到的:使用entityManager#joinTransaction,一切都很好,尽管这是一种糟糕的做法。谢谢,我将尝试显式指定entityManagerFactoryRef。@MykytaChelombitko:没问题。啊,我明白了。是的,这不是关于数据源的,我理解。您可以在配置类中使用
    entityManagerFactoryRef
    transactionManagerRef
    尝试一次,正如我在代码中所描述的。不幸的是,这没有帮助。有趣的是,事务注释似乎正在工作。为什么?因为如果我不在方法/类上使用事务,我将无法加入事务。所以它看起来像是事务上下文或类似的东西之间的差异。不确定。@MykytaChelombitko:奇怪的是,我在我的一个项目中使用了多年相同的配置。您所说的@Transactional working是什么意思,您在服务类或服务方法中错过了这一点?最好在服务类中使用此anno。很高兴看到你的问题得到解决。
    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
        }
    }