use*_*385 3 java rest persistence jpa jersey
使用此代码使用简单的REST服务时出现问题:
@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public synchronized Links nextLink(@PathParam("uuid") String uuid) {
Links link = null;
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}
return link;
}
Run Code Online (Sandbox Code Playgroud)
这应该提供一个链接对象,并将其标记为已使用(setStatusCode(5))以防止下次访问服务以发送相同的对象.问题是,当有很多快速客户端访问Web服务时,这个客户端向不同客户端提供相同链接对象的2到3倍.我怎么能解决这个问题?
这里是resquest使用:@NamedQuery(name ="Links.getNext",query ="SELECT l FROM Links l WHERE l.statusCode = 2")
和super.next()方法:
public T next() {
javax.persistence.Query q = getEntityManager().createNamedQuery("Links.getNext");
q.setMaxResults(1);
T res = (T) q.getSingleResult();
return res;
}
Run Code Online (Sandbox Code Playgroud)
谢谢
(根)JAX-RS资源的生命周期是每个请求,因此synchronized
该nextLink
方法上的(否则正确的)关键字可悲地无效.
您需要的是同步访问/更新的意思.这可以通过多种方式完成:
I)您可以在外部对象上进行同步,由框架注入(例如:CDI注入@ApplicationScoped),如下所示:
@ApplicationScoped
public class SyncLink{
private ReentrantLock lock = new ReentrantLock();
public Lock getLock(){
return lock;
}
}
....
public class MyResource{
@Inject SyncLink sync;
@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public Links nextLink(@PathParam("uuid") String uuid) {
sync.getLock().lock();
try{
Links link = null;
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}
return link;
}finally{
sync.getLock().unlock();
}
}
}
Run Code Online (Sandbox Code Playgroud)
II)你可能在课堂上很懒惰并且同步
public class MyResource{
@Inject SyncLink sync;
@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public Links nextLink(@PathParam("uuid") String uuid) {
Links link = null;
synchronized(MyResource.class){
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}
}
return link;
}
}
Run Code Online (Sandbox Code Playgroud)
III)您可以使用数据库进行同步.在这种情况下,您将调查JPA2中可用的悲观锁定.
您需要使用某种形式的锁定,最有可能的是乐观版本锁定。这将确保只有一笔交易成功,另一笔交易将失败。
请参阅 http://en.wikibooks.org/wiki/Java_Persistence/Locking
归档时间: |
|
查看次数: |
6944 次 |
最近记录: |