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 框架更好?

使用 Play 2 框架的基于令牌的身份验证

springMVC框架 学习Restful风格 详解

更新如何与 Ebean 和 Play 框架一起使用

将 macOS 更新到 Catalina 后,Play 框架无法正常工作

PHP实现RESTful风格的API实例