如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体

Posted

技术标签:

【中文标题】如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体【英文标题】:How do I configure a POST route in Play Framework v1.2.7 with a dynamic id attribute that will load a JPA entity 【发布时间】:2013-09-14 09:42:07 【问题描述】:

我想要一个 http 路由“POST /users/2”,它可以将表单提交给带有动作签名 Application.saveUser(User user) 的控制器,该控制器将根据指定的实体 id 更新现有用户的详细信息URL 中的动态参数。 User 类型是一个 JPA 实体,如果在请求/表单中指定了参数“user.id”,则 Play 对 JPA 的支持将自动加载该实体。到目前为止,我一直将“user.id”指定为隐藏输入,但我真的希望 id 成为 URL 的一部分。

我在 URL 中包含用户 ID 的第一个想法是定义这样的路由:

POST /users/user.id   Application.saveUser()

不幸的是,这给出了以下异常:

Oops: PatternSyntaxException
An unexpected error occured caused by exception PatternSyntaxException: unknow class: user.id

play.exceptions.UnexpectedException: Unexpected Error
    at play.Invoker$Invocation.onException(Invoker.java:244)
    at play.Invoker$Invocation.run(Invoker.java:286)
    at Invocation.HTTP Request(Play!)
Caused by: jregex.PatternSyntaxException: unknow class: member.id
    at jregex.CharacterClass.parseName(jregex/CharacterClass.java:361)
    at jregex.Term.append(jregex/Term.java:482)
    at jregex.Term.makeTree(jregex/Term.java:259)
    at jregex.Term.makeTree(jregex/Term.java:219)
    at jregex.Term.makeTree(jregex/Term.java:206)
    at jregex.Pattern.compile(jregex/Pattern.java:164)
    at jregex.Pattern.<init>(jregex/Pattern.java:150)
    at jregex.Pattern.<init>(jregex/Pattern.java:108)
    at play.mvc.Router$Route.compute(Router.java:755)

我尝试的另一个选项是只使用“id”参数名称,希望 Play 能够将其与用户 id 属性匹配:

POST /users/id   Application.saveUser()

但这给出了预期的 NoRouteFoundException,因为“id”与操作方法参数名称“用户”不匹配。最后一个明显的选择是使用参数名称“用户”,并再次希望 Play 可以使用一些智能来计算出这是 id:

POST /users/user   Application.saveUser()

这确实使页面能够使用表单中指定的正确路由呈现,但在提交时未加载正确的 JPA 实体:

<form action="/users/3" method="post" accept-charset="utf-8" enctype="application/x-www-form-urlencoded">

我尝试的最后一种方法是进行映射,但不确定是否支持:

POST /users/user   Application.saveUser(user.id: user)

再次没有加载正确的 JPA 实体。我搜索了高低,但没有找到如何正确完成此操作的示例。

【问题讨论】:

【参考方案1】:

播放文档中有一个示例,它显示了解决您问题的方法: http://www.playframework.com/documentation/1.2.7/jpa#save (本章第二个代码sn-p)

您需要一条路线(就像您在第二种方法中建议的那样),您只需传递要编辑的模型的 id:

POST /users/id   Application.saveUser()

相应的操作方法可能如下所示:

public static void save(Long id) 
    User user = User.findById(id);  // here you load the entity you want to edit by it's id
    user.edit("user", params.all());  // here the entity will be edited
    validation.valid(user);
    if(validation.hasErrors()) 
        edit(id);
     else
        user.save(); // explicit save here
        show(id);
    

【讨论】:

好的,所以这种方法更明确,需要更多样板文件 - 准确地说是前三行 - 如果实体 id 以以下格式提供,则匹配 Play JPA 插件完成的自动加载插件理解的。我希望有一个稍微更优雅的解决方案,看起来应该是可能的,但这绝对是有效的,而不是一个巨大的负担。谢谢【参考方案2】:

[Hi tazmaniax],尝试同时包含 id 和 model,但只在您的路线中包含 id。

POST /users/id   Application.saveUser()

Application.saveUser(Long id, User user)

<form action="@Application.saveUser(user.id)" method="post".....

【讨论】:

感谢您的提示,看起来很有趣,很快就会尝试

以上是关于如何在 Play Framework v1.2.7 中配置带有动态 id 属性的 POST 路由,该属性将加载 JPA 实体的主要内容,如果未能解决你的问题,请参考以下文章