我有一个自动装配的 jpa 存储库对象正在工作。但是,我需要使用它从多个线程向数据库中添加行。
但是,在将其传递给另一个线程后,它失败了。代码结构
@SpringBootApplication(exclude = HealthcheckConfig.class)
public class Application implements CommandLineRunner {
@Autowired
private DBRepository dbRepository;
@Autowired
private AppConfig appConfig;
private ExecutorService executors = Executors.newFixedThreadPool(3);
Application() {
}
@Override
public void run(final String... args) {
final DBSchemaObject temp = new Application("testdb", "testfield");
dbRepository.save(temp); // This WORKs!!!
for (FileStatus fileStatus: fileStatuses) {
executors.execute(new ThreadSafeClass(dbRepository));
}
}
public static void main(final String[] args) {
new SpringApplicationBuilder(Application.class)
.web(WebApplicationType.NONE)
.run(args)
.close();
}
}
但是,从线程安全类执行 dbRepository.save() 时,出现错误原因: java.lang.IllegalStateException: org.springframework.context.annotation.AnnotationConfigApplicationContext@41330d4f has been closed already
详细留言: Error creating bean with name 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties': Could not bind properties to 'DataSourceProperties' : prefix=spring.datasource, ignoreInvalidFields=false, ignoreUnknownFields=true
堆栈跟踪:
{StackTraceElement@14839} "org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800)"
{StackTraceElement@14840} "org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229)"
{StackTraceElement@14841} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354)"
{StackTraceElement@14842} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204)"
{StackTraceElement@14843} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)"
{StackTraceElement@14844} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)"
{StackTraceElement@14845} "org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)"
{StackTraceElement@14846} "org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)"
{StackTraceElement@14847} "org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)"
{StackTraceElement@14848} "org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)"
{StackTraceElement@14849} "org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410)"
{StackTraceElement@14850} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334)"
{StackTraceElement@14851} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)"
{StackTraceElement@14852} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564)"
{StackTraceElement@14853} "org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524)"
{StackTraceElement@14854} "org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)"
{StackTraceElement@14855} "org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)"
{StackTraceElement@14856} "org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)"
{StackTraceElement@14857} "org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)"
{StackTraceElement@14858} "org.springframework.beans.factory.support.DefaultListableBeanFactory$1.orderedStream(DefaultListableBeanFactory.java:481)"
{StackTraceElement@14859} "org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:167)"
{StackTraceElement@14860} "org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:149)"
{StackTraceElement@14861} "org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)"
{StackTraceElement@14862} "org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)"
{StackTraceElement@14863} "org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)"
{StackTraceElement@14864} "org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)"
{StackTraceElement@14865} "org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)"
{StackTraceElement@14866} "org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)"
{StackTraceElement@14867} "com.sun.proxy.$Proxy99.save(Unknown Source)"
{StackTraceElement@14868} "com.xxxx.run(Application.java:109)"
{StackTraceElement@14869} "java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)"
{StackTraceElement@14870} "java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)"
{StackTraceElement@14871} "java.lang.Thread.run(Thread.java:748)"
如何跨多个线程使用 spring boot 存储库对象?
问题是您的run()
方法只是安排要执行的任务,而不是等待它们完成。这是正在发生的事情:
new SpringApplicationBuilder(Application.class)
您正在使用命令行运行程序创建新的应用程序上下文 Application
.run(args)
然后初始化并执行应用程序上下文的run()
方法run()
方法调度要执行的任务并立即存在: public void run(final String... args) {
for (FileStatus fileStatus: fileStatuses) {
executors.execute(new ThreadSafeClass(dbRepository));
}
}
由于已run()
终止,spring 假定应用程序已完成并调用.close();
从而关闭应用程序上下文并使其无法使用任何 spring 功能,例如存储库。
计划任务被执行,但上下文已经关闭,因此它们失败并抛出异常。
解决方案是在退出 run 方法之前等待任务完成。由于您的示例太少,这只是一个示例。或者,您可以使用其他方法等待任务完成,例如CountDownLatch等,而无需关闭线程池:
for (FileStatus fileStatus: fileStatuses) {
executors.execute(new ThreadSafeClass(dbRepository));
}
executors.shutdown(); // prevents the executor from accepting any new tasks
executors.awaitTermination(); // wait for the tasks to finish
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句