【问题标题】:Issue with bindFromRequest in Play! Framework 2.3Play 中的 bindFromRequest 问题!框架 2.3
【发布时间】:2014-10-11 12:11:54
【问题描述】:

我正在尝试使用 Play 的自动绑定功能,但没有成功。我在 Eclipse 4.4 Luna 上使用 Java 进行开发。

这是我的表格:

<h2>Create a new user</h2>
<form action="@routes.Backend.createUser()" method="post">
    First Name
    <input type="text" name="firstName" />
    Last Name
    <input type="text" name="lastName" />
    E-mail
    <input type="email" name="email" />
    PIN
    <input type="number" name="pin" />
    Status
    <input type="text" name="status" />
    Is guest?
    <input type="checkbox" name="isGuest" />

    <input type="submit" value="Create user" />
</form>

这是我的“用户”类:

@Entity
public class Users extends Model {

// Database columns
@Id
public int userId;

public String firstName;
public String lastName;
public String email;
public int pin;
public String status;
public boolean isGuest;

}

这是我的控制器:

public class Backend extends Controller {

  public static Result createUser() {
    Form<Users> form = Form.form(Users.class).bindFromRequest();
    if (form.hasErrors()) {
        // doSomething()
    } else {
        Users u = form.get();
        u.save();
    }

    // TESTING
    // Checking the content of the request
    DynamicForm requestData = Form.form().bindFromRequest();
    String firstName = requestData.get("firstName");
    String lastName = requestData.get("lastName");
    // Printing the content works, I am able to see the correct values
    System.out.println(firstName); // Bob
    System.out.println(lastName); // Smith
    // This somehow doesn't work...
    System.out.println(u.firstName); // NULL
    System.out.println(u.lastName); // NULL
    System.out.println(u.userId); // Correctly generated
    // END OF TESTING

    return redirect(routes.Backend.allUsers());
  }
}

我想知道为什么值的自动绑定不起作用。我已经确保表单中的字段名称与类中的属性名称相对应,这应该足以使表单绑定起作用,对吧?

我正在使用 Eclipse Luna,并且我关闭了自动项目构建(我从控制台手动完成)。我知道有时 Eclipse 会因为该自动构建功能而导致问题。 注意:这是要走的路,但我没有按照用户 Dmitri 的建议使用 activator 命令清理项目。此外,您只需执行一次,只要您不打开 Eclipse 中的自动构建功能即可。

我尝试了几次重启 Eclipse 和应用程序,都没有成功...

编辑: 我尝试只为我的用户类使用字符串属性,因为 requestData.get(String s) 方法返回一个字符串。但是还是没有成功...

编辑 2: 我将手动绑定值...如果有人有想法,请发布:)

编辑 3: 我已经更新了我的代码以遵循以下答案中提到的规则

编辑 4: 只有在使用我的 Postgresql 9.3 数据库时,我才能使自动绑定工作。当我使用内存数据库时,一切都很顺利。此外,由于没有适用于 Java 8 和 postgresql 9.3 的 JDBC 驱动程序,我使用的是旧版本的驱动程序(实际上该驱动程序在 PGSQL 的网站上,但我无法让它与 Play 一起使用)。我将不得不检查另一个数据库会发生什么,然后我会在这里报告!

编辑 5: 我尝试像这样创建我的自定义数据绑定器:

        Formatters.register(User.class, new Formatters.SimpleFormatter<User>() {
        @Override
        public User parse(String arg0, Locale arg1) throws ParseException {
            User u = new Model.Finder<Integer, User>(Integer.class, User.class).byId(Integer.parseInt(arg0));
            return u;
        }
        @Override
        public String print(User arg0, Locale arg1) {
            return "User : " + arg0.firstName;
        }
    });

...但是没有用!

编辑 6: 用户 Dmitri 找到了一个可行的解决方案:您必须在 Eclipse 之外编译项目。 Eclipse的编译器和Play之间似乎有些不兼容!框架的编译器...

【问题讨论】:

  • 你有什么错误吗?
  • 绝对没有错误...我知道其余的工作正常,因为我可以手动绑定值并创建我的 Users 对象的实例,然后保存并检索它,但是这个自动绑定功能对我来说肯定坏了......

标签: java eclipse playframework-2.3 eclipse-luna databinder


【解决方案1】:

我一直在努力解决完全相同的问题:bindFromRequest 为“名称”字段返回空值。我所做的与 Play for Java 介绍视频中的一个人所做的完全相同:youtube.com/watch?v=bLrmnjPQsZc。但仍然没有运气。 我一直在使用 JDK 1.8 在 Windows 7 上工作。 IDE:Eclipse 4.4.0。我通过 cygwin 运行激活器。

这就是为我解决问题的方法:

  1. 在 Eclipse 中:项目 -> 自动构建 -> 关闭
  2. 在 cygwin 中: ./活化剂清洁; ./激活器编译; ./激活器运行;

在此之后,bindFromRequest 将 name 正确绑定并放入数据库中。

【讨论】:

  • 我已经尝试创建我的自定义数据绑定器,但它仍然没有工作,所以基本上我仍在努力解决这个问题......我正要回到所有的普通 SQL我的要求!但现在我要立即尝试并在这里报告!
  • 难以置信,它成功了!所以这是与 Eclipse 相关的……对吧?你能解释一下实际发生的事情吗?太感谢了! :)
  • 没问题 :) 我怀疑它与编译后发生的 ebean 增强有关。 Eclipse 看到新的更改并再次编译,从而弄乱了代码。
  • 很有可能。 IntelliJ IDEA 用户还没有报告过这种问题......我不知道是否已经提交了错误报告,向谁报告错误(Eclipse 或 Play?)以及是否值得提交一个。无论如何,非常感谢您的帮助,我自己不会发现的!
  • ......哇......令人兴奋......所以Eclipse IDE的问题
【解决方案2】:

为您的数据模型创建 getter/setter。它解决了我的问题。

【讨论】:

  • 这其实是正确的答案。发生错误是因为 scala 编译器添加了使用 eclipse 编译时未创建的默认 getter 和 setter。
  • 即使在今天,我也相信这是正确的答案,遇到了完全相同的问题。创建 getter 和 setter 可以解决问题。
【解决方案3】:

在你的代码中你有:

Users u = Form.form(Users.class).bindFromRequest().get(); 

试试这个:

Users user = new Users();
Form <Users> u = Form.form(Users.class).fill(user).bindFromRequest();

编辑:

问题可能出在您使用的输入类型上。尝试像这样生成您的表单:

@form(routes.Backend.createUser()) {

            <label>First Name:</label> @inputText(userForm("first_name")) <br />
            <label>Last Name:</label> @inputText(userForm("first_name")) <br />
            <label>Email:</label> @inputText(userForm("email")) <br />
            <label>Pin:</label> @inputText(userForm("pin")) <br />
            <label>Status:</label> @inputText(userForm("status")) <br />
            <label>Is Guest:</label> @checkbox(userForm("is_guest")) <br />
            <input type="submit" value="Create user" />
    }

然后在User Entity:尝试将所有列类型更改为String

@Entity
public class Users extends Model {

// Database columns
@Id
public int user_id;

public String first_name;
public String last_name;
public String email;
public String pin;
public String status;
public String is_guest;

}

在您的控制器中:

public class Backend extends Controller {

  public static Result createUser() {
    Form <Users> userForm = Form.form(Users.class).bindFromRequest();
    Users user = userForm .get();
    user.save();
}
}  

【讨论】:

  • 最后我使用了“.get()”方法,它应该返回一个“Users”类型的对象。这正是在 Play 中所做的! Java 开发者框架介绍视频:youtube.com/watch?v=bLrmnjPQsZc
  • 您的代码中的“userForm”是什么?我查看了 play 的文档,但上面什么都没有……我只知道它是传递给模板的参数,例如 @(userForm: Form[Users]),但它到底是什么?
  • 好的,所以我认为这只是一个简单的 Form userForm = Form.form(Users.class);我传递给我的模板。而且我仍然无法让自动绑定工作......生成的表单很好,当我手动检查值时一切正常。
  • 这是一个很好的post
【解决方案4】:

绑定和您的数据库之间绝对没有链接。不要遵循@blackbishop 的建议,告诉您将模型的所有字段更改为字符串。这是一个很糟糕的主意,如果有不同的类型,那是有原因的……

此外,Ebean(假设您正在使用它)或 JPA 会根据您的 Java 属性类型生成数据库列类型。为什么要将 0 或 1 存储在 varchar 列中?

遵守这些规则:

  1. 为您的模型使用单数名称(User 而不是 Users
  2. 始终为您的属性使用驼峰式大小写,不要使用下划线(firstName 代替 first_name,lastName 代替 last_name...)
  3. 绑定后获取值前检查错误

这应该给你这个:

public static Result createUser() {
    Form<User> form = Form.form(User.class).bindFromRequest();
    if (form.hasErrors()) {
        // Do what you have to do (i.e. : redirect to the form with a flash message)
    }
    User u = form.get();
    u.save();
    return redirect(routes.Backend.allUsers());
}

顺便说一句,在您的测试行中,user_id 是正确生成的,因为您没有验证规则,并且此数据来自数据库,而不是表单。

【讨论】:

  • 我一直使用这些规则,但是对于这个项目,如果我将我的模型命名为“用户”,那么数据库名称将是“用户”,这是一个保留的 SQL 名称......无论如何,我会尝试使用 camelCase 并报告。谢谢!
  • 我尝试了camelCase...没有成功。我真的不知道发生了什么,我仍然得到相同的结果:/
  • 真正困扰我的是,如果我打印表单的内容 (form.toString()),我会得到:Form(of=class models.system.Users, data={firstName=Bob, lastName=Smith, pin=567, isGuest=on, email=bob@smith.com, status=active}, value=Some(models.system.Users@5d482b), errors={}),这清楚地表明 form.get() 方法没有不适合我...
  • 因为user 是 MySQL 中的保留字,只需在模型类中使用 @Table(name = "users")。提交表单后在数据库中插入了什么?
  • 是的,我将使用@Table 注释,这是一个更好的解决方案。提交表单后,将插入“null”。我可能有线索:检查我的编辑!
【解决方案5】:

我通过添加 Setter 和 Getter 解决了这个问题。 如果你有实体/模型类,你应该添加 setter 和 getter。 如果你有 FormData 类,也可以为它添加 setter 和 getter。

所以当你打电话时

Form<YourFormData> formData =       Form.form(YourFormData.class).bindFromRequest(); 
 YourFormData formData = formData.get(); 

您的 formData 现在将设置所有值。 希望这可以帮助!

【讨论】:

    【解决方案6】:

    我知道这篇文章有一个可接受的答案,但想发表我在这个问题上的经验。

    我遇到了同样的问题并执行了上面答案中提到的所有步骤,即 Eclipse 自动构建,然后通过激活器清理和编译。然而,这并没有奏效。我尝试了许多不同的方法,甚至从头开始创建了一个项目,而没有创建任何 Eclipse 依赖项。还是不行。

    然后,我查看了我的模型并决定尝试更改属性名称的大小写,然后瞧!成功了!

    这是我的模型之前的样子:

    public class Test {
     public String FirstName;
     public String LastName;}
    

    现在,我把它改成了这样:

    public class Test {
      public String firstName;
      public String lastName;}
    

    只是想指出这一点,因为它并不明显,而且我来自 .Net

    【讨论】:

      猜你喜欢
      • 2016-12-21
      • 2015-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多