Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.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 配置自定义HibernateItemWriter时获取“必须提供HibernateOperations或SessionFactory”_Java_Mysql_Hibernate_Spring Boot_Spring Batch - Fatal编程技术网

Java 配置自定义HibernateItemWriter时获取“必须提供HibernateOperations或SessionFactory”

Java 配置自定义HibernateItemWriter时获取“必须提供HibernateOperations或SessionFactory”,java,mysql,hibernate,spring-boot,spring-batch,Java,Mysql,Hibernate,Spring Boot,Spring Batch,因此,我正在尝试使用Hibernate构建一个可以写入MySQL数据库的应用程序,并且花了很长时间来尝试让它工作。简而言之,它没有看到会话,尽管我已经配置了一个会话并自动连接了它。以下是我的代码 首先,所述应用程序的配置: @EnableBatchProcessing @SpringBootApplication(scanBasePackages="com.lcbo") @EnableIntegration public class BatchConfig { @Autowired priva

因此,我正在尝试使用Hibernate构建一个可以写入MySQL数据库的应用程序,并且花了很长时间来尝试让它工作。简而言之,它没有看到会话,尽管我已经配置了一个会话并自动连接了它。以下是我的代码

首先,所述应用程序的配置:

@EnableBatchProcessing
@SpringBootApplication(scanBasePackages="com.lcbo")
@EnableIntegration
public class BatchConfig {

@Autowired
private JobBuilderFactory jobBuilderFactory;

@Autowired
private StepBuilderFactory stepBuilderFactory;

@Bean
public Job processLCBOInventory(@Qualifier("getCurrentLCBODataStep") final Step getCurrentLCBODataStep,
                                @Qualifier("getLCBOStoreDataStep") final Step getLCBOStoreDataStep,
                                final JobExecutionListenerConfig jelcListener
                                ) {
    return jobBuilderFactory
            .get("processLCBOInventory")
            .incrementer(new RunIdIncrementer())
            .start(getCurrentLCBODataStep)
            .next(getLCBOStoreDataStep)
            .listener(jelcListener)
            .build();

}

@Bean
public Step getLCBOStoreDataStep(final LCBOStoreReader lcboStoreReader,
                                 final LCBOStoreProcessor lcboStoreProcessor,
                                 final LCBOStoreWriter lcboStoreWriter,
                                 final ExecutionContextPromotionListener listener) throws Exception {

    return stepBuilderFactory
            .get("getLCBOStoreDataStep")
            .<LCBOStore, LCBOStore>chunk(inventoryTrackerProperties.getDefaults().getChunkSize())
            .reader(lcboStoreReader.read())
            .processor(lcboStoreProcessor)
            .writer(lcboStoreWriter)
            .listener(listener)
            .build();
}
甚至尝试过SessionFactory本身,就像这样

public LocalSessionFactoryBean getSessionFactory() throws SQLException {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "com.bytestree.model" });
    sessionFactory.setHibernateProperties(getHibernateProperties());

    return sessionFactory;
}
但是没有骰子。我还尝试将SessionFactory实例注入HibernateItemWriter附带的setSessionFactory中,同样没有骰子

我知道我有点不对劲,问题是它希望SessionFactory被应用程序重新确认到哪里,或者我是否已经将这个编写器配置得几乎正确

编辑:根据请求,运行此代码时在intellj中显示的堆栈跟踪

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'LCBOInventoryWriter' defined in file [C:\workspace\LCBOInventoryTracker\target\classes\com\lcbo\writer\LCBOInventoryWriter.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Either HibernateOperations or SessionFactory must be provided
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1628) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:314) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151) [spring-boot-1.5.1.RELEASE.jar:1.5.1.RELEASE]
    at com.lcbo.config.LCBOBatchConfig.main(LCBOBatchConfig.java:157) [classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_102]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_102]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_102]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_102]
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
Caused by: java.lang.IllegalStateException: Either HibernateOperations or SessionFactory must be provided
    at org.springframework.util.Assert.state(Assert.java:392) ~[spring-core-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.batch.item.database.HibernateItemWriter.afterPropertiesSet(HibernateItemWriter.java:93) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624) ~[spring-beans-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    ... 20 common frames omitted

由于HibernateItemWriter是第三方依赖项,我认为最好将LCBOStoreWriter设置为@Bean而不是@Component,并在那里设置sessionFactory

从LCBOStoreWriter中删除@组件,并将以下内容添加到BatchConfig

如果lcboStoreService和dbConfigy不是自动连接的,则可能需要对其进行设置。或者,你可以用其他方法注射,我不记得所有的方法

@Bean
public SessionFactory sessionFactory() throws SQLException {
    LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
    sessionFactory.setDataSource(dataSource());
    sessionFactory.setPackagesToScan(new String[] { "com.bytestree.model" });
    sessionFactory.setHibernateProperties(getHibernateProperties());
    return sessionFactory.getObject();
}

所以,从我收到的反馈听起来,正如我所担心的,我已经创造了一个从网上多个来源拼凑而成的frakenstein解决方案。通过大量的帮助和一些尝试和错误,我通过以下步骤解决了这个问题

首先,这是作者现在的样子

@Component
public class LCBOStoreWriter implements ItemWriter<LCBOStore> {

    @Autowired
    private DatabaseConfig dbConfig;

    @Override
    public void write(List<? extends LCBOStore> items) throws Exception {

        JpaItemWriter wr = new JpaItemWriter();

        wr.setEntityManagerFactory(dbConfig.entityManagerFactory());
        wr.write(items);

    }
}
自动连接到的entityManagerFactory类:

@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException {

    final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource());
    factoryBean.setJpaDialect(new HibernateJpaDialect());
    factoryBean.setJpaProperties(getHibernateProperties());
    factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    factoryBean.setPackagesToScan("com.lcbo.batch.domain");
   factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
    factoryBean.setPersistenceUnitName("persistenceUnit");
    factoryBean.afterPropertiesSet();


    return factoryBean.getObject();
}
以及步骤的配置

@Bean
public Step getLCBOStoreDataStep(final LCBOStoreReader lcboStoreReader,
                                 final LCBOStoreProcessor lcboStoreProcessor,
                                 final LCBOStoreWriter lcboStoreWriter,
                                 final ExecutionContextPromotionListener listener) throws Exception {

    return stepBuilderFactory
            .get("getLCBOStoreDataStep")
            .<LCBOStore, LCBOStore>chunk(inventoryTrackerProperties.getDefaults().getChunkSize())
            .reader(lcboStoreReader.read())
            .processor(lcboStoreProcessor)
            .writer(lcboStoreWriter)
            .listener(listener)
            .build();
}

我要感谢qtips和Deinum先生在这方面的帮助。非常感谢

您在写入程序上的SessionFactory设置在何处?能否显示完整的堆栈跟踪/错误?如何设置spring批处理?我注意到,在你的LCBOSTOREWRITE.write中,你正在将会话转换为SessionFactory。那不行!尝试使用SessionFactory SessionFactory=entityManagerFactory.UnwrappressionFactory.class设置HibernateItemWriter的SessionFactory;HibernateItemWriter需要在afterPropertiesSet方法中检查的显式连接的sessionFactory。此外,我也知道您的应用程序存在缺陷,因为您不需要SessionFactory和EntityRangerFactory。你为什么还要用HibernateItemWriter?您应该改为使用JpaItemWriter,因为您不需要现在已有的破解/解决方法。@MichaelMinella我在编写器中使用this.setSessionFactorydatabaseConfig.getSessionFactory设置SessionFactory时使用了它,但没有任何效果。只需使用普通JpaItemWriter,您不需要扩展它,这就是您的全部问题,您的扩展正在破坏编写器的正常工作。因此,自动连接dbConfig、修改sessionFactory以适合您的示例、修改步骤配置并将lCBOStoreWriter添加到批处理配置中,但遗憾的是,仍然存在完全相同的错误。但是,尝试了以下操作:wr.setSessionFactorydbConfig.entityManagerFactory.unwrap‌​SessionFactory.class‌​; 如果没有激活的事务错误,错误被替换为contains无效。您是否可以调试lCBOStoreWriter和getLCBOStoreDataStep并验证sessionfactory是否设置为not?事实上,我同意@m-deinum。你为什么要扩展HibernateItemWriter?您可能应该将其设置为带有会话工厂的bean。处理器应该简单地返回hibernate实体,而writer应该自动写入它们,而不需要服务。您看过本指南吗?这是一个很好的说明点,您可以将其扩展到使用hibernate。在这里,您将使用application.properties设置数据源,而不是在config中进行设置。SpringBoot将为您提供数据源。然后,我想您可以自动连接sessionfactory/EntityManager来告诉我们它是如何运行的:我找到了各种各样的解决方案。我已经在下面发布了我的答案。这仍然是一个弗兰肯斯坦的解决方案,你不需要那个包装。。。它只增加了复杂性。这也让我担心你的其他阅读器和处理器。我认为你能让它运行真是太好了!第一次运行bean是一个挑战。正如@M.Deinum所建议的,尝试在不扩展hibernate编写器的情况下让它工作,您将开始拥有spring批处理@M.Deinum我相信我知道你从哪里来,我已经为答案添加了一个附录,除非你知道你需要扩展你的编写器/处理器pr是愚蠢的,就像那种风格,只要把它放在配置你的步骤的配置风格中就行了。如果你扩展/包装的东西根本不知道你在做什么。一些编写器需要更多接口,而您仅使用ItemWriter包装的方式可能会破坏这些编写器或其他组件的正常运行。因此,我强烈建议不要使用ext 在没有正确理解Spring批处理的详细信息的情况下,将默认值终止为通常会导致中断。
@Component
public class LCBOStoreWriter implements ItemWriter<LCBOStore> {

    @Autowired
    private DatabaseConfig dbConfig;

    @Override
    public void write(List<? extends LCBOStore> items) throws Exception {

        JpaItemWriter wr = new JpaItemWriter();

        wr.setEntityManagerFactory(dbConfig.entityManagerFactory());
        wr.write(items);

    }
}
@Entity
@Table(name = "store")
public class LCBOStore {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    private Long id;

    @Column(name = "addressLineOne", length = 255)
    private String addressLineOne;

    @Column(name = "addressLineTwo", length = 255)
    private String addressLineTwo;

    @Column(name = "city", length = 255)
    private String city;

    @Column(name = "postalCode", length = 10)
    private String postalCode;

    @Column(name = "latitude", length = 255)
    private String latitude;

    @Column(name = "longitude", length = 255)
    private String longitude;

    @Column(name = "updatedAt", length = 255)
    private String updatedAt; //Convert to Date

//getters and setters

}
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException {

    final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource());
    factoryBean.setJpaDialect(new HibernateJpaDialect());
    factoryBean.setJpaProperties(getHibernateProperties());
    factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    factoryBean.setPackagesToScan("com.lcbo.batch.domain");
   factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
    factoryBean.setPersistenceUnitName("persistenceUnit");
    factoryBean.afterPropertiesSet();


    return factoryBean.getObject();
}
@Bean
public Step getLCBOStoreDataStep(final LCBOStoreReader lcboStoreReader,
                                 final LCBOStoreProcessor lcboStoreProcessor,
                                 final LCBOStoreWriter lcboStoreWriter,
                                 final ExecutionContextPromotionListener listener) throws Exception {

    return stepBuilderFactory
            .get("getLCBOStoreDataStep")
            .<LCBOStore, LCBOStore>chunk(inventoryTrackerProperties.getDefaults().getChunkSize())
            .reader(lcboStoreReader.read())
            .processor(lcboStoreProcessor)
            .writer(lcboStoreWriter)
            .listener(listener)
            .build();
}