简体   繁体   中英

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. 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

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?

I need to make sure that only one request is accessing the Resource (fetching a list of SomeClass objects) without throwing an exception. Instead, subsequent requests should be queued and try to access the resource after the current request has finished fetching the list of SomeClass objects.

My final solution was to introduce a Blocking Queue in the @Service and add all incoming requests to it. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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