我想问一下,是否有办法以优雅的方式解决以下问题。
我有一个使用JPA和Jersey的Java Rest应用程序。我希望能够部分更新我的模型。
我通过一个方法(更新)来完成它,它将检查提供的字段(!= null)并且只更新那些它它适用于除布尔类型字段之外的所有字段。
如果你能提出一些想法我真的很感激。我认为是布尔型,但它看起来并不优雅。
资源部分:
...
@PUT
@Path("{id:[0-9][0-9]*}")
@Consumes(MediaType.APPLICATION_JSON)
public Response update((@PathParam("id") long id, Event event) {
Event _event = dao.find(id);
if (event.getTitle()!=null) _event.setTitle(event.getTitle());
// in case variable finished is not provided we should not change anything
// if (event.getFinished()!=null) _event.setFinished(event.getFinished());
dao.update(id, _event);
}
...
模型部分:
@Entity
@XmlRootElement
public class Event implements Serializable {
private String title;
private boolean finished = false;
public Event(){}
// getters, setters
...
}
javascript部分:
// Those ones work
Event.post({id:12, title:"Meet with Joe", finished:true} // update all fields
Event.post({id:12, title:"Meet with Barack", finished:false} // update all fields
Event.post({id:12, finished:false} // partial update of boolean fields
// How to achieve this one without affecting other boolean fields?
Event.post({id:12, title:"Meet with Joe"}
// We haven't provided "finished" value. We don't want to change it.
// But system will update unprovided boolean field value with default.
答案 0 :(得分:0)
从语义上讲,如果你想使用你的Event类能够表达“部分事件填充了某些字段而某些字段没有填充”的概念,那么每个字段的类型可以为null都是有意义的,IMO会是“优雅”的解决方案。
但是,如果这使得你的事件现在能够在一个非空字段上有空值,只是因为你想在这个更新调用中也使用它 - 我的猜测是这是你的部分不喜欢它。 (即,您基本上使用相同的Event类作为直接表示数据库记录的模型对象,以及仅填充了一些字段的Event的部分表示)
另一种方法可能是从客户端获取一个简单的Map(即代替“Event event”作为update()的最后一个参数,执行“java.util.Map event”)并只复制值包含的内容。如果你必须做很多事情,你可以使用反射来使这个过程更容易复制多种类型的对象。
P.S。我对Jersey没有太多经验,所以我不确定它是否可以正常使用java.util.Map(这是一个接口)作为param类型,或者它是否需要一个具体类或可能是其他一些注释(s )。但我确信如果你喜欢这种方法,那么这个概念就可以发挥作用。
答案 1 :(得分:0)
我想我找到了解决方案。不使用Post in Post参数,最好使用JsonObject:
...
@PUT
@Path("{id:[0-9][0-9]*}")
@Consumes(MediaType.APPLICATION_JSON)
public Response update((@PathParam("id") long id, JSONObject json) {
Event _event = dao.find(id);
_event.setTitle(json.optString("title"));
_event.setFinished(json.optBoolean("finished", _event.getFinished())); // if boolean value is not provided, we don't change it
dao.update(id, _event);
}
...