我正在使用Play Framework 2.3和Java,我在委员会及其记录的会议日期之间存在以下一对多的关系:
@Entity
public class Committee {
@Id
protected Long id;
@OneToMany(cascade=CascadeType.ALL, mappedBy="committee", orphanRemoval=true)
private List<MeetingDate> meetingDates;
}
@Entity
public class MeetingDate {
@Id
private Long id;
@Constraints.Required
@JoinColumn(nullable=false)
@ManyToOne
private Committee committee;
@Constraints.Required
@Formats.DateTime(pattern="dd MMM yyyy")
@Temporal(TemporalType.DATE)
@Column(nullable=false)
private Date meetingDate;
}
我有一个表单,允许用户在一个页面上编辑委员会和相关的会议日期。我已经关注了&#34; Forms&#34;来自https://www.playframework.com/documentation/2.2.x/Samples的示例应用程序,我的模板代码如下所示:
@meetingDateGroup(field: Field, className: String = "meeting-date") = {
<tr class="repeating-group @className">
<td>
<input type="hidden" id='@field("id").name' name='@field("id").name' value='@field("id").value'>
<input type="text" id='@field("meetingDate").name' name='@field("meetingDate").name' value='@field("meetingDate").value' class="form-control">
@if(field("meetingDate").hasErrors){
<div class="help-block"><span class="glyphicon glyphicon-exclamation-sign"></span> @field("meetingDate").errors.mkString(", ")</div>
}
</td>
<td align="right"><a href="javascript:void(0)" class="remove-meeting-date rowIcon"><span class="glyphicon glyphicon-remove"></span> Delete</a></td>
</tr>
}
...
@helper.repeat(form("meetingDates"), min=1) { meetingDate =>
@meetingDateGroup(meetingDate)
}
@**
* Keep a hidden block that will be used as template for Javascript copy code
**@
@meetingDateGroup(
form("meetingDates[x]"), className = "hidden meeting-date-template"
)
请注意,有额外的Javascript代码(未显示)可以动态地添加和删除表中的会议日期行。此Javascript代码是从Forms示例应用程序中复制的。
我遇到的问题是没有对MeetingDate实体进行验证。例如,我添加了额外的会议日期行,并且不输入日期值。当我保存委员会时,我不会在Form
中收到任何错误,但会发生以下例外:
play.api.Application$$anon$1: Execution exception[[RollbackException: Error while committing the transaction]]
at play.api.Application$class.handleError(Application.scala:296) ~[play_2.11-2.3.4.jar:2.3.4]
at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.11-2.3.4.jar:2.3.4]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun
$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.4.jar:2.3.4]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun
$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.11-2.3.4.jar:2.3.4]
at scala.Option.map(Option.scala:145) [scala-library-2.11.1.jar:na]
Caused by: javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:94) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at play.db.jpa.JPA$2.apply(JPA.java:193) ~[play-java-jpa_2.11-2.3.4.jar:2.3.4]
at play.core.j.FPromiseHelper$$anonfun$map$1.apply(FPromiseHelper.scala:98) ~[play_2.11-2.3.4.jar:2.3.4]
at scala.util.Success$$anonfun$map$1.apply(Try.scala:236) ~[scala-library-2.11.1.jar:na]
at scala.util.Try$.apply(Try.scala:191) ~[scala-library-2.11.1.jar:na]
Caused by: javax.validation.ConstraintViolationException: Validation failed forclasses [models.MeetingDate] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='error.required', propertyPath=meetingDate, rootBeanClass=class models.MeetingDate, messageTemplate='error.required'}
]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:160) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:95) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:218) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:97) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463) ~[hibernate-core-4.3.6.Final.jar:4.3.6.Final]
[ERROR] [09/03/2014 23:25:59.167] [play-akka.actor.default-dispatcher-4] [akka.dispatch.Dispatcher] EntityManager is closed
java.lang.IllegalStateException: EntityManager is closed
at org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:105)
at org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:96)
at org.hibernate.jpa.internal.EntityManagerImpl.close(EntityManagerImpl.java:148)
at play.db.jpa.JPA$3.invoke(JPA.java:209)
at play.db.jpa.JPA$3.invoke(JPA.java:203)
at play.core.j.FPromiseHelper$$anonfun$onFailure$1.applyOrElse(FPromiseHelper.scala:116)
at play.core.j.FPromiseHelper$$anonfun$onFailure$1.applyOrElse(FPromiseHelper.scala:116)
at scala.concurrent.Future$$anonfun$onFailure$1.apply(Future.scala:136)
at scala.concurrent.Future$$anonfun$onFailure$1.apply(Future.scala:134)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
at play.core.j.HttpExecutionContext$$anon$2.run(HttpExecutionContext.scala:40)
at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
[error] a.d.Dispatcher - EntityManager is closed
java.lang.IllegalStateException: EntityManager is closed
at org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:105) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.internal.EntityManagerImpl.checkOpen(EntityManagerImpl.java:96) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at org.hibernate.jpa.internal.EntityManagerImpl.close(EntityManagerImpl.java:148) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]
at play.db.jpa.JPA$3.invoke(JPA.java:209) ~[play-java-jpa_2.11-2.3.4.jar:2.3.4]
at play.db.jpa.JPA$3.invoke(JPA.java:203) ~[play-java-jpa_2.11-2.3.4.jar:2.3.4]
MeetingDate
对象肯定无效,因为它的meetingDate
属性为空。我的问题是:为什么在表单错误中没有报告此错误,即为什么以下表达式为false?
Form.form(Committee.class).bindFromRequest().hasErrors()
答案 0 :(得分:1)
想出我错过了什么 - 我需要将@Valid
注释添加到我的一对多关系中:
@Valid
@OneToMany(cascade=CascadeType.ALL, mappedBy="committee", orphanRemoval=true)
private List<MeetingDate> meetingDates;
这会触发嵌套字段的验证。