我正在关注Play框架示例计算机数据库应用程序中的示例并具有以下模型
public class Simulation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
@ManyToOne
@JoinColumn(name="projection_set_id")
public ProjectionSet projectionSet;
}
public class ProjectionSet {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long id;
}
在表格中,我有以下表格帮助
@helper.select(
simulationForm("projectionSet.id"),
options(ProjectionSet.options),
'_label -> "Team Context",
'_showConstraints -> false
)
选项定义为
public static Map<String,String> options() {
List<ProjectionSet> projectionSets = ProjectionSet.findAll();
LinkedHashMap<String,String> options = new LinkedHashMap<String,String>();
for(ProjectionSet set: projectionSets) {
options.put(set.id.toString(), set.forDate.toString());
}
return options;
}
在控制器中我有以下内容:
Form<Simulation> filledForm = simulationForm.bindFromRequest();
Logger.debug("form = " + filledForm.toString());
if(filledForm.hasErrors()) {
final User user = BaseController.currentUser();
return badRequest(newSimulation.render(user, filledForm));
} else {
Map<String, String> formData = filledForm.data();
Simulation created = filledForm.get();
created.create();
return redirect("/simulations");
}
我得到的例外是
Caused by: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: models.simulations.Simulation.projectionSet -> models.baseball.ProjectionSet
at org.hibernate.engine.spi.CascadingAction$8.noCascade(CascadingAction.java:380) ~ [hibernate-core-4.2.7.Final.jar:4.2.7.Final]
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:176) ~[hibernate-core-4.2.7.Final.jar:4.2.7.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:162) ~[hibernate-core-4.2.7.Final.jar:4.2.7.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:153) ~[hibernate-core-4.2.7.Final.jar:4.2.7.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:89) ~[hibernate-core-4.2.7.Final.jar:4.2.7.Final]
在放置断点之后,出现的问题是我从bindToRequest获得的Simulation类具有ProjectionSet对象,但其中的所有值都为null。然后我逐步介绍了bindToRequest方法,我发现对于嵌套绑定,即)projectionSet.id,spring绑定器在setPropertyValue方法中的org.springframework.beans.BeanWrapperImpl类中引发异常
private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {
,特别是,当PropertyValue的resolvedDescriptor为null时,它会抛出NotWriteablePropertyException。
我是Spring的新手,它是绑定库。我不知道如何才能让这个属性得到妥善解决。有什么想法吗?
答案 0 :(得分:1)
尝试为ProjectionSet
课程注册格式化程序。因此Form.bindFromRequest()
知道如何将提交表单中的id转换为实际对象。我更喜欢在应用程序级别定义格式化程序,以便将它们放在Global对象中。
public class Global extends GlobalSettings {
static {
play.data.format.Formatters.register(ProjectionSet.class,
new Formatters.SimpleFormatter<ProjectionSet>() {
@Override
public ProjectionSet parse(String id, Locale locale) throws ParseException {
ProjectionSet pSet = null;
try {
long tmpId = Long.parseLong(id);
pSet = ProjectionSet.finder.byId(tmpId);
} catch (NumberFormatException ignored) {
//unexpected id
}
return pSet;
}
@Override
public String print(ProjectionSet pSet , Locale locale) {
return pSet.id + "";
}
});
}
}
有关表单处理的更多信息,请查看this page,尤其是最后一节,用于定义自定义对象的映射。