播放框架。在实体构造函数中使用事务

PlayFramework. Use transaction in entity constructor

我正在尝试获取其他实体构造函数中的实体列表。

不幸的是它在运行时失败了。

这是构造函数:

public Contract_Answer() {
    this.commonEntities = CommonEntityDao.getList();
}

这是我的整个堆栈跟踪:

play.api.UnexpectedException: Unexpected exception[PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory]
        at play.core.ReloadableApplication$$anonfun$get$$anonfun$apply$$anonfun.apply(ApplicationProvider.scala:148) ~[play_2.10.jar:2.2.6]
        at play.core.ReloadableApplication$$anonfun$get$$anonfun$apply$$anonfun.apply(ApplicationProvider.scala:112) ~[play_2.10.jar:2.2.6]
        at scala.Option.map(Option.scala:145) ~[scala-library.jar:na]
        at play.core.ReloadableApplication$$anonfun$get$$anonfun$apply.apply(ApplicationProvider.scala:112) ~[play_2.10.jar:2.2.6]
        at play.core.ReloadableApplication$$anonfun$get$$anonfun$apply.apply(ApplicationProvider.scala:110) ~[play_2.10.jar:2.2.6]
        at scala.util.Success.flatMap(Try.scala:200) ~[scala-library.jar:na]
        at play.core.ReloadableApplication$$anonfun$get.apply(ApplicationProvider.scala:110) ~[play_2.10.jar:2.2.6]
        at play.core.ReloadableApplication$$anonfun$get.apply(ApplicationProvider.scala:102) ~[play_2.10.jar:2.2.6]
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1(Future.scala:24) ~[scala-library.jar:na]
        at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) ~[scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinTask$AdaptedRunnableAction.exec(ForkJoinTask.java:1361) ~[scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) ~[scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) ~[scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) ~[scala-library.jar:na]
        at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) ~[scala-library.jar:na]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: defaultPersistenceUnit] Unable to build EntityManagerFactory
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915) ~[hibernate-entitymanager-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890) ~[hibernate-entitymanager-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57) ~[hibernate-entitymanager-4.2.0.CR1.jar:4.2.0.CR1]
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63) ~[hibernate-jpa-2.0-api.jar:1.0.1.Final]
        at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47) ~[hibernate-jpa-2.0-api.jar:1.0.1.Final]
        at play.db.jpa.JPAPlugin.onStart(JPAPlugin.java:35) ~[play-java-jpa_2.10.jar:2.2.6]
        at play.api.Play$$anonfun$start$$anonfun$apply$mcV$sp.apply(Play.scala:88) ~[play_2.10.jar:2.2.6]
        at play.api.Play$$anonfun$start$$anonfun$apply$mcV$sp.apply(Play.scala:88) ~[play_2.10.jar:2.2.6]
        at scala.collection.immutable.List.foreach(List.scala:318) ~[scala-library.jar:na]
        at play.api.Play$$anonfun$start.apply$mcV$sp(Play.scala:88) ~[play_2.10.jar:2.2.6]
        at play.api.Play$$anonfun$start.apply(Play.scala:88) ~[play_2.10.jar:2.2.6]
        at play.api.Play$$anonfun$start.apply(Play.scala:88) ~[play_2.10.jar:2.2.6]
        at play.utils.Threads$.withContextClassLoader(Threads.scala:18) ~[play_2.10.jar:2.2.6]
        at play.api.Play$.start(Play.scala:87) ~[play_2.10.jar:2.2.6]
        at play.core.ReloadableApplication$$anonfun$get$$anonfun$apply$$anonfun.apply(ApplicationProvider.scala:139) ~[play_2.10.jar:2.2.6]
        ... 14 common frames omitted
Caused by: org.hibernate.MappingException: Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
        at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:185) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:385) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1742) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94) ~[hibernate-entitymanager-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905) ~[hibernate-entitymanager-4.2.0.CR1.jar:4.2.0.CR1]
        ... 28 common frames omitted
Caused by: org.hibernate.InstantiationException: could not instantiate test objectmyInsurance.models.part.Contract_Answer
        at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:49) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.engine.internal.UnsavedValueFactory.getUnsavedIdentifierValue(UnsavedValueFactory.java:68) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.tuple.PropertyFactory.buildIdentifierProperty(PropertyFactory.java:75) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:145) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:507) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:146) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        at sun.reflect.GeneratedConstructorAccessor317.newInstance(Unknown Source) ~[na:na]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.7.0_80]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526) ~[na:1.7.0_80]
        at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        ... 33 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.7.0_80]
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) ~[na:1.7.0_80]
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.7.0_80]
        at java.lang.reflect.Constructor.newInstance(Constructor.java:526) ~[na:1.7.0_80]
        at org.hibernate.engine.internal.UnsavedValueFactory.instantiate(UnsavedValueFactory.java:46) ~[hibernate-core-4.2.0.CR1.jar:4.2.0.CR1]
        ... 42 common frames omitted
Caused by: java.lang.RuntimeException: No EntityManager bound to this thread. Try wrapping this call in JPA.withTransaction, or ensure that the HTTP context is setup on this thread.
        at play.db.jpa.JPA.em(JPA.java:55) ~[play-java-jpa_2.10.jar:2.2.6]
        at generic.models.GenericDictionary.getList(GenericDictionary.java:38) ~[na:na]
        at myInsurance.models.part.Contract_Answer.<init>(Contract_Answer.java:49) ~[na:na]
        ... 47 common frames omitted

请帮帮我。我做错了什么?


编辑


感谢 @Mon Calamari 的指导,我重写了我的构造函数。不幸的是,这个代码结构对我来说是新的,我无法让它工作。

这是新的构造函数:

public Contract_Answer() {
    List<CommonEntity> list = JPA.withTransaction(
            new F.Function0<List<CommonEntity>>() { 
                return CommonEntityDao.getList();
            }
    );
    // doing something with list variable
}

无法编译:

Contract_Answer.java:60: error: illegal start of type
[error]                 return CommonEntityDao.getList();
Contract_Answer.java:60: error: ';' expected
[error]                 return CommonEntityDao.getList();
Contract_Answer.java:60: error: illegal start of type
[error]                 return CommonEntityDao.getList();

编辑2


最后我编译如下:

public Contract_Answer() {


    List<Contract_PolicyHolderHealthFormQuestion> list = new LinkedList<Contract_PolicyHolderHealthFormQuestion>();
    try {
        list = JPA.withTransaction(
            new play.libs.F.Function0<List<Contract_PolicyHolderHealthFormQuestion>>() {
                @Override
                public List<Contract_PolicyHolderHealthFormQuestion> apply() throws Throwable {
                    return new Contract_PolicyHolderHealthFormQuestion().getList();
                }
            }
        );
    } catch (Throwable e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    for(Contract_PolicyHolderHealthFormQuestion e: list) {
        Contract_PolicyHolderHealthFormAnswer ca = new Contract_PolicyHolderHealthFormAnswer();
        ca.question = e;
        this.answers.add(ca);
    }

}

答案很简单。您没有任何实体管理器附加到此线程。 有很多解决方案:

  • 最简单的是在你执行这段代码的方法中添加注解@Transactional
  • 手动开始您的交易:

    EntityManager em = JPA.em(); JPA.bindForCurrentThread(em);

    但如果您决定手动执行此操作,则必须小心并自行提交此事务。决定权在你:)

withTransaction

包裹起来
public Contract_Answer() {
    this.commonEntities = JPA.withTransaction(new F.Function0<List<CommonEntity>> () { 
        return CommonEntityDao.getList();
    });
}