我无法在Play Framework环境中使用JPA实现具有常量类型集合的多个属性的模型。
多次@ElementCollection
次Collection
次使用Enum
注释会导致错误,这样一个带注释的属性不会导致错误和正确行为。
问题通过https://github.com/adpes/jpa-elementcollection-mvce/tree/elementcollection-double进行了演示,并在README.md:
中进行了说明这个fork演示了重复注释JPA的问题 Play Framework环境中的
@ElementCollection
。看文件, 除了states
之外,特别是属性languages
:如果使用注释了多个属性,则构建失败
@ElementCollection
。
以下模型Person
会产生以下堆栈跟踪:
models/Person.java
package models;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
@Entity
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long id;
public String name;
@ElementCollection(targetClass = Languages.class, fetch = FetchType.EAGER)
public Collection<Languages> languages = new ArrayList<>();
// TODO Comment me and the build will succeed
@ElementCollection(targetClass = State.class, fetch = FetchType.EAGER)
public Collection<State> states = new ArrayList<>();
}
sbt run
[info] Loading settings from idea.sbt ...
[info] Loading global plugins from /home/adpes/.sbt/1.0/plugins
[info] Loading settings from plugins.sbt ...
[info] Loading project definition from /home/adpes/dev/jpa-elementcollection-mvce/project
[info] Loading settings from build.sbt ...
[info] Set current project to play-java-jpa-example (in build file:/home/adpes/dev/jpa-elementcollection-mvce/)
--- (Running the application, auto-reloading is enabled) ---
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
(Server started, use Enter to stop and go back to the console...)
Warning: node.js detection failed, sbt will use the Rhino based Trireme JavaScript engine instead to run JavaScript assets compilation, which in some cases may be orders of magnitude slower than using node.js.
[info] application - Creating Pool for datasource 'default'
[info] p.a.d.HikariCPConnectionPool - datasource [default] bound to JNDI as DefaultDS
[info] p.a.d.DefaultDBApi - Database [default] connected at jdbc:h2:mem:play
[warn] o.h.v.m.ParameterMessageInterpolator - HV000184: ParameterMessageInterpolator has been chosen, EL interpolation will not be supported
[info] p.a.h.EnabledFilters - Enabled Filters (see <https://www.playframework.com/documentation/latest/Filters>):
play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter
[error] application -
! @777cf90c8 - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:44)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:39)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
for the 1st parameter of models.JPAPersonRepository.<init>(JPAPersonRepository.java:23)
while locating models.JPAPersonRepository
while locating models.PersonRepository
for the 2nd parameter of controllers.PersonController.<init>(PersonController.java:28)
while locating controllers.PersonController
for the 2nd parameter of router.Routes.<init>(Routes.scala:30)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router
for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:222)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for the 6th parameter of play.api.DefaultApplication.<init>(Application.scala:236)
at play.api.DefaultApplication.class(Application.scala:235)
while locating play.api.DefaultApplication
while locating play.api.Application
1 error]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:186)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:124)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:189)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:106)
at akka.stream.impl.fusing.MapAsync$$anon$25.onPush(Ops.scala:1194)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:482)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:378)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:585)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:469)
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:44)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:39)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
for the 1st parameter of models.JPAPersonRepository.<init>(JPAPersonRepository.java:23)
while locating models.JPAPersonRepository
while locating models.PersonRepository
for the 2nd parameter of controllers.PersonController.<init>(PersonController.java:28)
while locating controllers.PersonController
for the 2nd parameter of router.Routes.<init>(Routes.scala:30)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router
for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:222)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for the 6th parameter of play.api.DefaultApplication.<init>(Application.scala:236)
at play.api.DefaultApplication.class(Application.scala:235)
while locating play.api.DefaultApplication
while locating play.api.Application
1 error
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:409)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:404)
at play.api.inject.ContextClassLoaderInjector.$anonfun$instanceOf$2(Injector.scala:117)
at play.api.inject.ContextClassLoaderInjector.withContext(Injector.scala:126)
at play.api.inject.ContextClassLoaderInjector.instanceOf(Injector.scala:117)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:174)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:967)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at play.db.jpa.DefaultJPAApi.lambda$start$1(DefaultJPAApi.java:65)
at java.lang.Iterable.forEach(Iterable.java:75)
at play.db.jpa.DefaultJPAApi.start(DefaultJPAApi.java:64)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:51)
at play.db.jpa.DefaultJPAApi$JPAApiProvider$$FastClassByGuice$$dcd4cdbd.newInstance(<generated>)
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [models.Person.languages, models.Person.states]
at org.hibernate.loader.plan.exec.internal.AbstractLoadQueryDetails.generate(AbstractLoadQueryDetails.java:178)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails.<init>(EntityLoadQueryDetails.java:90)
at org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory.makeEntityLoadQueryDetails(BatchingLoadQueryDetailsFactory.java:61)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.<init>(AbstractLoadPlanBasedEntityLoader.java:82)
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:103)
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:38)
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byUniqueKey(EntityLoader.java:83)
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byPrimaryKey(EntityLoader.java:77)
at org.hibernate.loader.entity.plan.AbstractBatchingEntityLoaderBuilder.buildNonBatchingLoader(AbstractBatchingEntityLoaderBuilder.java:30)
at org.hibernate.loader.entity.BatchingEntityLoaderBuilder.buildLoader(BatchingEntityLoaderBuilder.java:59)
[error] application -
! @777cf90c8 - Internal server error, for (GET) [/favicon.ico] ->
play.api.UnexpectedException: Unexpected exception[ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:44)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:39)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
for the 1st parameter of models.JPAPersonRepository.<init>(JPAPersonRepository.java:23)
while locating models.JPAPersonRepository
while locating models.PersonRepository
for the 2nd parameter of controllers.PersonController.<init>(PersonController.java:28)
while locating controllers.PersonController
for the 2nd parameter of router.Routes.<init>(Routes.scala:30)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router
for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:222)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for the 6th parameter of play.api.DefaultApplication.<init>(Application.scala:236)
at play.api.DefaultApplication.class(Application.scala:235)
while locating play.api.DefaultApplication
while locating play.api.Application
1 error]
at play.core.server.DevServerStart$$anon$1.reload(DevServerStart.scala:186)
at play.core.server.DevServerStart$$anon$1.get(DevServerStart.scala:124)
at play.core.server.AkkaHttpServer.handleRequest(AkkaHttpServer.scala:189)
at play.core.server.AkkaHttpServer.$anonfun$createServerBinding$1(AkkaHttpServer.scala:106)
at akka.stream.impl.fusing.MapAsync$$anon$25.onPush(Ops.scala:1194)
at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:519)
at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:482)
at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:378)
at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:585)
at akka.stream.impl.fusing.GraphInterpreterShell$AsyncInput.execute(ActorGraphInterpreter.scala:469)
Caused by: com.google.inject.ProvisionException: Unable to provision, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:44)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:39)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
for the 1st parameter of models.JPAPersonRepository.<init>(JPAPersonRepository.java:23)
while locating models.JPAPersonRepository
while locating models.PersonRepository
for the 2nd parameter of controllers.PersonController.<init>(PersonController.java:28)
while locating controllers.PersonController
for the 2nd parameter of router.Routes.<init>(Routes.scala:30)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router
for the 1st parameter of play.api.http.JavaCompatibleHttpRequestHandler.<init>(HttpRequestHandler.scala:222)
while locating play.api.http.JavaCompatibleHttpRequestHandler
while locating play.api.http.HttpRequestHandler
for the 6th parameter of play.api.DefaultApplication.<init>(Application.scala:236)
at play.api.DefaultApplication.class(Application.scala:235)
while locating play.api.DefaultApplication
while locating play.api.Application
1 error
at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1028)
at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1054)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:409)
at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:404)
at play.api.inject.ContextClassLoaderInjector.$anonfun$instanceOf$2(Injector.scala:117)
at play.api.inject.ContextClassLoaderInjector.withContext(Injector.scala:126)
at play.api.inject.ContextClassLoaderInjector.instanceOf(Injector.scala:117)
at play.api.inject.guice.GuiceApplicationBuilder.build(GuiceApplicationBuilder.scala:137)
at play.api.inject.guice.GuiceApplicationLoader.load(GuiceApplicationLoader.scala:21)
at play.core.server.DevServerStart$$anon$1.$anonfun$reload$3(DevServerStart.scala:174)
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build Hibernate SessionFactory
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:967)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at play.db.jpa.DefaultJPAApi.lambda$start$1(DefaultJPAApi.java:65)
at java.lang.Iterable.forEach(Iterable.java:75)
at play.db.jpa.DefaultJPAApi.start(DefaultJPAApi.java:64)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:51)
at play.db.jpa.DefaultJPAApi$JPAApiProvider$$FastClassByGuice$$dcd4cdbd.newInstance(<generated>)
Caused by: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags: [models.Person.languages, models.Person.states]
at org.hibernate.loader.plan.exec.internal.AbstractLoadQueryDetails.generate(AbstractLoadQueryDetails.java:178)
at org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails.<init>(EntityLoadQueryDetails.java:90)
at org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory.makeEntityLoadQueryDetails(BatchingLoadQueryDetailsFactory.java:61)
at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.<init>(AbstractLoadPlanBasedEntityLoader.java:82)
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:103)
at org.hibernate.loader.entity.plan.EntityLoader.<init>(EntityLoader.java:38)
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byUniqueKey(EntityLoader.java:83)
at org.hibernate.loader.entity.plan.EntityLoader$Builder.byPrimaryKey(EntityLoader.java:77)
at org.hibernate.loader.entity.plan.AbstractBatchingEntityLoaderBuilder.buildNonBatchingLoader(AbstractBatchingEntityLoaderBuilder.java:30)
at org.hibernate.loader.entity.BatchingEntityLoaderBuilder.buildLoader(BatchingEntityLoaderBuilder.java:59)
[info] p.c.s.AkkaHttpServer - Stopping server...
[success] Total time: 21 s, completed Mar 6, 2018 9:15:27 AM
[INFO] [03/06/2018 09:15:28.031] [Thread-2] [CoordinatedShutdown(akka://sbt-web)] Starting coordinated shutdown from JVM shutdown hook
答案 0 :(得分:0)
我知道我参加晚会很晚,但是请参阅下文,我对您的代码进行了更改。更改仍然使您急切地寻找所需的内容。
package models;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Collection;
@Entity
public class Person {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long id;
public String name;
@ElementCollection(targetClass = Languages.class) // remove fetch type
@LazyCollection(LazyCollectionOption.FALSE)// This I have found to be my saving grace
public Collection<Languages> languages = new ArrayList<>();
// TODO Comment me and the build will succeed
@ElementCollection(targetClass = State.class) // remove fetch type
@LazyCollection(LazyCollectionOption.FALSE) // This I have found to be my saving grace
public Collection<State> states = new ArrayList<>();
}