简体   繁体   English

Spring with JPA:将来自不同请求的对JPA实体的并发访问排队

[英]Spring with JPA: Queue concurrent access to JPA entity from different requests

I have a Spring Web Application with concurrent access to a certain resource. 我有一个Spring Web Application,可以同时访问某些资源。 This resource holds a list of a certain numer of objects which might be fetched by a request. 该资源保存了可能由请求获取的一定数量的对象的列表。 If the list is empty, no SomeClass Object should be returned any more 如果列表为空,则不再返回SomeClass对象

The resource looks like this: 该资源如下所示:

public class Resource {

    private List<SomeClass> someList;

    public List<SomeClass> fetch() {
        List<SomeClass> fetched = new ArrayList<SomeClass>();
        int max = someList.size();          
        if(max<=0) {
            return fetched;
        }

        int added = 0;
        while(added<max) {
            int randomIndex = Math.random(max-1);
            SomeClass someClass = someList.get(randomIndex);
            if(!fetched.contains(someClass)) {
                fetched.add(someClass);
                ++added;
            }
        }
        someList.remove(fetched);

        return fetched;
    }

}

This resource is loaded in the service layer, then accessed and saved back to the database: 此资源被加载到服务层中,然后被访问并保存回数据库中:

@Service    
public class ResourceService {

    @Autowired
    private ResourceRepository repo;

    public List<SomeClass> fetch(long id) {
        Resource resource = repo.findOne(id);
        List<SomeClass> fetched = resource.fetch();
        repo.save(resource);
        return fetched;
    }

}

I tried to use @Transactional on the ResourceService#fetch method to avoid the problem that two concurrent requests might fetch a SomeClass object from the list although the list was already emptied by the first request but I'm not sure if this is the right approach... Do I have to use @Synchronized on the Resource#fetch method or introduce an explicit Lock in the service layer? 我尝试在ResourceService#fetch方法上使用@Transactional来避免两个并发请求可能会从列表中获取SomeClass对象的问题,尽管该列表已被第一个请求清空,但是我不确定这是否是正确的方法...我必须在Resource#fetch方法上使用@Synchronized还是在服务层中引入显式的Lock?

I need to make sure that only one request is accessing the Resource (fetching a list of SomeClass objects) without throwing an exception. 我需要确保只有一个请求可以访问资源(获取SomeClass对象的列表)而不会引发异常。 Instead, subsequent requests should be queued and try to access the resource after the current request has finished fetching the list of SomeClass objects. 取而代之的是,应将后续请求排队,并在当前请求完成获取SomeClass对象列表之后尝试访问资源。

My final solution was to introduce a Blocking Queue in the @Service and add all incoming requests to it. 我的最终解决方案是在@Service中引入一个阻塞队列 ,并将所有传入请求添加到该队列中。 A seperate thread is then taking an element from the queue as soon as one was added and processing it. 然后一个单独的线程从队列中取出一个元素并对其进行处理。

I think this is the cleanest solution, as adding an ReentrantLock would block the request processing. 我认为这是最干净的解决方案,因为添加ReentrantLock会阻止请求处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM