0

我们正在创建基于 Play 框架 2.1.x 的 RESTFul API,它以 JSON 格式传输/接受数据。创建读取删除操作很容易实现,但我们却被更新操作卡住了。

以下是我们拥有的实体:

事件:

@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 数据合并并在存储中更新它的示例都将受到高度赞赏。

4

1 回答 1

0

您现在可能已经修复了错误,但如果这对其他人有帮助,我还是会回答它。

我也是 Play Framework 的初学者,几天前才开始。但我相信当你的代码中有:

event.save();

你应该这样做:

event.update();

这里的问题是您没有将新实体插入到数据库中,而实际上只是更新了已经存在的实体,因此您需要使用第二种方法。

您可以在http://www.playframework.com/documentation/2.0/api/java/play/db/ebean/Model.html找到更多信息

于 2013-10-10T13:36:23.803 回答