Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.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 JPA线程:IllegalArgumentException异常_Java_Spring_Hibernate_Jpa_Transactional - Fatal编程技术网

Java Spring JPA线程:IllegalArgumentException异常

Java Spring JPA线程:IllegalArgumentException异常,java,spring,hibernate,jpa,transactional,Java,Spring,Hibernate,Jpa,Transactional,我对Thread类进行了如下注释: @Transactional(propagation = Propagation.REQUIRED) @Component @Scope("prototype") public class ThreadRetrieveStockInfoEuronext implements Runnable { ... } 线程被连接到控制器类中,并通过Global.poolMultiple.execute(threadRetrieveStockInfoEuronex

我对Thread类进行了如下注释:

@Transactional(propagation = Propagation.REQUIRED)
@Component
@Scope("prototype")
public class ThreadRetrieveStockInfoEuronext implements Runnable {
   ...
}
线程被连接到控制器类中,并通过Global.poolMultiple.execute(threadRetrieveStockInfoEuronext)调用

全球类:

@SuppressWarnings("unchecked")
@Component
public class Global {

    // create ExecutorService to manage threads
    public static ExecutorService poolMultiple = Executors.newFixedThreadPool(10);
    public static ExecutorService poolSingle = Executors.newFixedThreadPool(1);
...
}
运行应用程序时,会发生以下异常:

java.lang.IllegalArgumentException:无法设置 com.chartinvest.admin.thread.ThreadRetrieveStockInfoEuronext字段

com.chartinvest.controller.RetrievelController.threadRetrieveStockInfoEuronext 到com.sun.proxy.$Proxy52


这是因为您的可运行实现是一个Spring组件,用
@Transactional
注释,而声明性事务是在Spring中通过将类的实际实例包装在处理事务的基于JDK接口的代理中实现的。因此,自动连接的实际对象不是ThreadRetrieveStockInfoEuronext的实例,而是其接口Runnable的实例,该接口委托给ThreadRetrieveStockInfoEuronext的实例

解决此问题的常用方法是自动连接接口,而不是自动连接具体类型。但是在这种情况下,这个类首先不应该是Spring组件,也不应该是事务性的。顺便说一句,使其成为原型会让您产生这样的错觉,即每次调用submitRetrieveStockInfo()时都会创建一个新实例,但这是错误的:创建一个实例并将其自动连接到RetrieveController singleton中,因此对控制器的所有请求都使用相同的runnable

只需使ThreadRetrieveStockInfoEuronext成为一个简单的类,使用new实例化它,将SpringBean作为参数传递,并使其
run()
方法调用该SpringBean的事务方法:

@Transactional
@Component
public class ThreadRetrieveStockInfoEuronextImpl implements ThreadRetrieveStockInfoEuronext {
    @Override 
    void doSomething() { ... }
}

public class RetrievelController {

    @Autowired
    private ThreadRetrieveStockInfoEuronext threadRetrieveStockInfoEuronext;

    @RequestMapping(value = "/.retrieveStockInfo.htm", method = RequestMethod.POST)
    public ModelAndView submitRetrieveStockInfo(@ModelAttribute("retrieveStockInfoCommand") RetrieveStockInfoCommand command, BindingResult result, HttpServletRequest request) throws Exception {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                threadRetrieveStockInfoEuronext.doSomething();
            }
        };

        Global.poolMultiple.execute(runnable);
        return new ModelAndView(".retrieveStockInfo", "retrieveStockInfoCommand", command);
    }

非常感谢JB的建议,该解决方案非常有效!!
@Transactional
@Component
public class ThreadRetrieveStockInfoEuronextImpl implements ThreadRetrieveStockInfoEuronext {
    @Override 
    void doSomething() { ... }
}

public class RetrievelController {

    @Autowired
    private ThreadRetrieveStockInfoEuronext threadRetrieveStockInfoEuronext;

    @RequestMapping(value = "/.retrieveStockInfo.htm", method = RequestMethod.POST)
    public ModelAndView submitRetrieveStockInfo(@ModelAttribute("retrieveStockInfoCommand") RetrieveStockInfoCommand command, BindingResult result, HttpServletRequest request) throws Exception {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                threadRetrieveStockInfoEuronext.doSomething();
            }
        };

        Global.poolMultiple.execute(runnable);
        return new ModelAndView(".retrieveStockInfo", "retrieveStockInfoCommand", command);
    }