Play 框架:实现 RESTful 更新操作的问题
Posted
技术标签:
【中文标题】Play 框架:实现 RESTful 更新操作的问题【英文标题】:Play framework: issues with implementing restful update operation 【发布时间】:2013-10-02 20:46:58 【问题描述】:我们正在创建基于 Play 框架 2.1.x 的 RESTFul API,它以 JSON 格式传输/接受数据。 创建、读取和删除操作很容易实现,但我们却被update操作卡住了。 p>
以下是我们拥有的实体:
事件:
@Entity
public class Event extends Model
@Id
public Long id;
@NotEmpty
public String title;
@OneToOne(cascade = CascadeType.ALL)
public Location location;
@OneToMany(cascade = CascadeType.ALL)
public List<Stage> stages = new LinkedList<Stage>();
...
地点:
@Entity
public class Location extends Model
@Id
public Long id;
@NotEmpty
public String title;
public String address;
...
阶段:
@Entity
public class Stage extends Model
@Id
public Long id;
@NotEmpty
public String title;
public int capacity;
...
在我们的路由器中,我们有以下条目:
PUT /events/:id controllers.Event.updateEvent(id: Long)
控制器中的 updateEvent 方法如下所示(注意:我们使用 Jackson 库将对象映射到 JSON 并返回):
@BodyParser.Of(BodyParser.Json.class)
public static Result updateEvent(Long id)
Event event = Event.find.byId(id);
Http.RequestBody requestBody = request().body();
JsonNode jsonNode = requestBody.asJson();
try
ObjectMapper mapper = new ObjectMapper();
ObjectReader reader = mapper.readerForUpdating(event);
event = reader.readValue(jsonNode);
event.save();
catch (IOException e)
e.printStackTrace();
return ok();
在我们从数据库中获取事件后,通过使用 ObjectReader 从 JSON 读取更新其值,我们尝试保存更新的事件并获得异常(我们在尝试更新阶段列表时遇到类似的情况):
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_9F ON PUBLIC.LOCATION(ID)"; SQL statement: insert into location (id, title, address) values (?,?,?) [23505-168]
根据 H2 日志框架尝试对位置执行插入操作,但由于具有指定 id 的位置已存在而失败。我们已经进一步调查了 ant,当我们从 DB 获取 Event 时,由于延迟获取,位置未加入。看起来问题发生在保存与我们的事件有关系的其他实体时。我们尝试通过执行以下操作来强制获取位置操作:
Event event = Ebean.find(Event.class).fetch("location").where().eq("id", id).findUnique();
但当我们使用 ObjectReader 的 readValue 方法更新此事件并保存事件时,我们仍然会得到相同的异常。
我们还尝试从 JSON 中创建单独的 Event 对象,并逐个字段地从 DB 中更新 Event(我们自己实现了合并操作),它确实有效,但看起来很奇怪,框架没有提供任何合并和更新实体的方法从客户端传递的数据。
有人可以建议如何解决这个问题吗?任何展示如何将实体与来自客户端的 JSON 数据合并并在存储中更新它的示例都将受到高度赞赏。
【问题讨论】:
【参考方案1】:您现在可能已经修复了错误,但如果这对其他人有帮助,我还是会回答它。
我也是 Play Framework 的初学者,几天前才开始。但我相信当你的代码中有:
event.save();
你应该这样做:
event.update();
这里的问题是,您并没有将新实体插入数据库,而实际上只是更新了已经存在的实体,因此您需要使用第二种方法。
您可以在http://www.playframework.com/documentation/2.0/api/java/play/db/ebean/Model.html找到更多信息
【讨论】:
以上是关于Play 框架:实现 RESTful 更新操作的问题的主要内容,如果未能解决你的问题,请参考以下文章
对于 Java 中的 RESTful 服务,JAX-RS 是不是比 Swing、Grails 或 Play 等 MVC 框架更好?