带JPA的Spring:从不同的请求

时间:2015-07-13 14:08:42

标签: java spring-mvc jpa concurrency spring-data-jpa

我有一个可以同时访问某个资源的Spring Web应用程序。此资源包含可能由请求获取的某些对象的列表。如果列表为空,则不应再返回任何SomeClass对象

资源如下所示:

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;
    }

}

此资源加载到服务层,然后访问并保存回数据库:

@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;
    }

}

我尝试在ResourceService #fetch方法上使用@Transactional来避免两个并发请求可能从列表中获取SomeClass对象的问题,尽管第一个请求已经清空了列表,但我不确定这是否是正确的方法......我是否必须在Resource#fetch方法上使用@Synchronized或在服务层中引入显式锁?

我需要确保只有一个请求正在访问资源(获取SomeClass对象的列表)而不会抛出异常。相反,后续请求应排队并在当前请求完成获取SomeClass对象列表后尝试访问资源。

1 个答案:

答案 0 :(得分:0)

我的最终解决方案是在@Service中引入Blocking Queue并将所有传入请求添加到它。然后,只要添加一个元素并对其进行处理,单独的线程就是taking队列中的元素。

我认为这是最干净的解决方案,因为添加ReentrantLock会阻止请求处理。