在 EBean 和表单中保存枚举列表
Saving a list of enums in an EBean and a Form
我有一个包含枚举项的字段 'roles'。我正在尝试使用表单编辑此列表,但得到:
[InvalidPropertyException: Invalid property 'roles[0]' of bean class [models.Device]: Property referenced in indexed property path 'roles[0]' is neither an array nor a List nor a Map; returned value was [SERVER]]
这是我的实体:
@Entity
public class Device extends Model {
@Id
@Constraints.Min(1)
public Long id;
@Constraints.Required
public String name;
@Constraints.Required
public String ipAddress;
@Constraints.Required
@ElementCollection(fetch = FetchType.EAGER)
public Set<DeviceRole> roles = new HashSet<DeviceRole>(Arrays.asList(DeviceRole.OTHER));
@Version
public Timestamp lastUpdate;
public static Finder<Long,Device> find = new Finder<Long,Device>(
Long.class, Device.class
);
public List<ValidationError> validate() {
/*
List<ValidationError> errors = new ArrayList<ValidationError>();
if (User.byEmail(email) != null) {
errors.add(new ValidationError("email", "This e-mail is already registered."));
}
return errors.isEmpty() ? null : errors;
*/
return null;
}
}
控制器中的编辑和更新功能:
public static Result edit(Long id) {
Device device = Device.find.byId(id);
Form<Device> myForm = Form.form(Device.class);
myForm = myForm.fill(device);
return ok(views.html.Devices.edit.render(myForm, listOfRoles()));
}
public static Result update() {
Form<Device> deviceForm = Form.form(Device.class).bindFromRequest();
if (deviceForm.hasErrors()) {
return badRequest(views.html.Devices.edit.render(deviceForm, listOfRoles()));
}
// Form is OK, has no errors, we can proceed
Device device = deviceForm.get();
device.update(device.id);
return redirect(routes.Devices.index());
}
private static List<String> listOfRoles() {
List<String> list = new ArrayList<String>();
for(DeviceRole role : DeviceRole.values()) {
list.add(role.toString());
}
return list;
}
和模板:
@main("Edit a device") {
@helper.form(action = routes.Devices.update()) {
@helper.inputText(myForm("name"))
@helper.inputText(myForm("ipAddress"))
@helper.select(myForm("roles"), options(deviceRoles), 'multiple->"multiple")
<input type="hidden" name="id" value="@myForm("id").value">
<input type="submit" value="Submit">
}
<a href="@routes.Devices.index()">Cancel</a>
}
实际上,这样做可能需要将它们保存为字符串字段中以逗号分隔的值列表,为了更清楚,我建议将 DeviceRole
更改为 Ebean 模型并处理它作为常见的 ManyToMany 关系。
恕我直言,它为您提供了更大的灵活性,还允许您在未来创建更多动态角色,
刚刚分叉了您的示例并对其进行了修改以展示我自己是如何做的(自述文件中的一些细节):
https://github.com/biesior/temperature-control
P.S.: 如果到现在为止没有任何变化,请查看 Ebean 的票证,只是尚不支持保存枚举列表(我不知道当前状态)http://avaje.org/topic-149.html
对于 Enum,您可以使用 @EnumValue
,这是 Ebean 特定的注释,用于将 Enum 映射到数据库值。
public static enum RoleName {
@EnumValue("SERVER") SERVER,
@EnumValue("TEMPERATURE") TEMPERATURE,
@EnumValue("HUMIDITY") HUMIDITY,
@EnumValue("SWITCH") SWITCH,
@EnumValue("OTHER") OTHER
}
我有一个包含枚举项的字段 'roles'。我正在尝试使用表单编辑此列表,但得到:
[InvalidPropertyException: Invalid property 'roles[0]' of bean class [models.Device]: Property referenced in indexed property path 'roles[0]' is neither an array nor a List nor a Map; returned value was [SERVER]]
这是我的实体:
@Entity
public class Device extends Model {
@Id
@Constraints.Min(1)
public Long id;
@Constraints.Required
public String name;
@Constraints.Required
public String ipAddress;
@Constraints.Required
@ElementCollection(fetch = FetchType.EAGER)
public Set<DeviceRole> roles = new HashSet<DeviceRole>(Arrays.asList(DeviceRole.OTHER));
@Version
public Timestamp lastUpdate;
public static Finder<Long,Device> find = new Finder<Long,Device>(
Long.class, Device.class
);
public List<ValidationError> validate() {
/*
List<ValidationError> errors = new ArrayList<ValidationError>();
if (User.byEmail(email) != null) {
errors.add(new ValidationError("email", "This e-mail is already registered."));
}
return errors.isEmpty() ? null : errors;
*/
return null;
}
}
控制器中的编辑和更新功能:
public static Result edit(Long id) {
Device device = Device.find.byId(id);
Form<Device> myForm = Form.form(Device.class);
myForm = myForm.fill(device);
return ok(views.html.Devices.edit.render(myForm, listOfRoles()));
}
public static Result update() {
Form<Device> deviceForm = Form.form(Device.class).bindFromRequest();
if (deviceForm.hasErrors()) {
return badRequest(views.html.Devices.edit.render(deviceForm, listOfRoles()));
}
// Form is OK, has no errors, we can proceed
Device device = deviceForm.get();
device.update(device.id);
return redirect(routes.Devices.index());
}
private static List<String> listOfRoles() {
List<String> list = new ArrayList<String>();
for(DeviceRole role : DeviceRole.values()) {
list.add(role.toString());
}
return list;
}
和模板:
@main("Edit a device") {
@helper.form(action = routes.Devices.update()) {
@helper.inputText(myForm("name"))
@helper.inputText(myForm("ipAddress"))
@helper.select(myForm("roles"), options(deviceRoles), 'multiple->"multiple")
<input type="hidden" name="id" value="@myForm("id").value">
<input type="submit" value="Submit">
}
<a href="@routes.Devices.index()">Cancel</a>
}
实际上,这样做可能需要将它们保存为字符串字段中以逗号分隔的值列表,为了更清楚,我建议将 DeviceRole
更改为 Ebean 模型并处理它作为常见的 ManyToMany 关系。
恕我直言,它为您提供了更大的灵活性,还允许您在未来创建更多动态角色,
刚刚分叉了您的示例并对其进行了修改以展示我自己是如何做的(自述文件中的一些细节):
https://github.com/biesior/temperature-control
P.S.: 如果到现在为止没有任何变化,请查看 Ebean 的票证,只是尚不支持保存枚举列表(我不知道当前状态)http://avaje.org/topic-149.html
对于 Enum,您可以使用 @EnumValue
,这是 Ebean 特定的注释,用于将 Enum 映射到数据库值。
public static enum RoleName {
@EnumValue("SERVER") SERVER,
@EnumValue("TEMPERATURE") TEMPERATURE,
@EnumValue("HUMIDITY") HUMIDITY,
@EnumValue("SWITCH") SWITCH,
@EnumValue("OTHER") OTHER
}