gpt4 book ai didi

google-app-engine - Google App Engine : When calling persist(. ..) 上的 JPA,它总是发生在事务中吗?

转载 作者:行者123 更新时间:2023-12-03 22:51:56 26 4
gpt4 key购买 nike

在我的应用程序中,我坚持一个具有许多无主子级的实体。

似乎对 persist 的调用实体和所有子项的持久化发生在事务中,因为当我不启用跨组事务时出现错误(并且子项作为父实体生活在不同的实体组中)。

是否有可能以非交易方式进行持久化?

(如果需要此信息:我正在使用 Guice 将请求范围的 Provider<EntityManager> 注入(inject)我的服务对象。)

添加:

这是一个简单的测试用例:

@Entity public class Department {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;

@OneToMany(mappedBy = "department", cascade = CascadeType.ALL)
@Unowned
Collection<Employee> employees = new ArrayList<Employee>();

public Collection<Employee> getEmployees() {
return employees;
}

}

@Entity public class Employee {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne private Department department; private String name;

public Employee(String name) { this.name = name; } public String getName() { return name; }

public void setName(String name) { this.name = name; } }

现在,当我这样做时:
EntityManager em = EMF.get().createEntityManager();
try {
Department department = new Department();
department.getEmployees().add(new Employee("Joe"));
em.persist(department);
} finally {
em.close();
}

我得到:

Illegal argument

Caused by:

javax.persistence.PersistenceException: Illegal argument at org.datanucleus.api.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:298) at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:197) at com.example.jpa.JpaServlet.doGet(JpaServlet.java:23) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:409) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) Caused by: java.lang.IllegalArgumentException: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXGfound both Element { type: "Department" id: 17 } and Element { type: "Employee" id: 18 }

at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:33) at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:70) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:94) at com.google.appengine.api.datastore.FutureHelper$CumulativeAggregateFuture.get(FutureHelper.java:142) at com.google.appengine.api.datastore.FutureHelper$TxnAwareFuture.get(FutureHelper.java:218) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:86) at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:71) at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:32) at com.google.appengine.api.datastore.DatastoreServiceImpl.put(DatastoreServiceImpl.java:85) at com.google.appengine.datanucleus.WrappedDatastoreService.put(WrappedDatastoreService.java:112) at com.google.appengine.datanucleus.EntityUtils.putEntitiesIntoDatastore(EntityUtils.java:766) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:314) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218) at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381) at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3778) at org.datanucleus.store.types.sco.SCOUtils.validateObjectForWriting(SCOUtils.java:1518) at com.google.appengine.datanucleus.scostore.AbstractFKStore.validateElementForWriting(AbstractFKStore.java:396) at com.google.appengine.datanucleus.scostore.FKListStore.validateElementForWriting(FKListStore.java:1036) at com.google.appengine.datanucleus.scostore.FKListStore.internalAdd(FKListStore.java:195) at com.google.appengine.datanucleus.scostore.FKListStore.addAll(FKListStore.java:114) at org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(CollectionMapping.java:134) at com.google.appengine.datanucleus.StoreFieldManager.storeRelations(StoreFieldManager.java:809) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:367) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218) at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381) at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3778) at org.datanucleus.ObjectManagerImpl.flushInternalWithOrdering(ObjectManagerImpl.java:3888) at org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:3811) at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:3751) at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:4141) at org.datanucleus.ObjectManagerImpl.transactionPreCommit(ObjectManagerImpl.java:428) at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:398) at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287) at org.datanucleus.ObjectManagerImpl.close(ObjectManagerImpl.java:1090) at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:193) ... 36 more

Caused by:

java.lang.IllegalArgumentException: cross-group transaction need to be explicitly specified, see TransactionOptions.Builder.withXGfound both Element { type: "Department" id: 17 } and Element { type: "Employee" id: 18 }

at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:33) at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:70) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:94) at com.google.appengine.api.datastore.FutureHelper$CumulativeAggregateFuture.get(FutureHelper.java:142) at com.google.appengine.api.datastore.FutureHelper$TxnAwareFuture.get(FutureHelper.java:218) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:86) at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:71) at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:32) at com.google.appengine.api.datastore.DatastoreServiceImpl.put(DatastoreServiceImpl.java:85) at com.google.appengine.datanucleus.WrappedDatastoreService.put(WrappedDatastoreService.java:112) at com.google.appengine.datanucleus.EntityUtils.putEntitiesIntoDatastore(EntityUtils.java:766) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:314) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218) at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381) at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3778) at org.datanucleus.store.types.sco.SCOUtils.validateObjectForWriting(SCOUtils.java:1518) at com.google.appengine.datanucleus.scostore.AbstractFKStore.validateElementForWriting(AbstractFKStore.java:396) at com.google.appengine.datanucleus.scostore.FKListStore.validateElementForWriting(FKListStore.java:1036) at com.google.appengine.datanucleus.scostore.FKListStore.internalAdd(FKListStore.java:195) at com.google.appengine.datanucleus.scostore.FKListStore.addAll(FKListStore.java:114) at org.datanucleus.store.mapped.mapping.CollectionMapping.postInsert(CollectionMapping.java:134) at com.google.appengine.datanucleus.StoreFieldManager.storeRelations(StoreFieldManager.java:809) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:367) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218) at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381) at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3778) at org.datanucleus.ObjectManagerImpl.flushInternalWithOrdering(ObjectManagerImpl.java:3888) at org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:3811) at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:3751) at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:4141) at org.datanucleus.ObjectManagerImpl.transactionPreCommit(ObjectManagerImpl.java:428) at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:398) at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287) at org.datanucleus.ObjectManagerImpl.close(ObjectManagerImpl.java:1090) at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:193) at com.example.jpa.JpaServlet.doGet(JpaServlet.java:23) at javax.servlet.http.HttpServlet.service(HttpServlet.java:617) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:123) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:61) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97) at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:94) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:409) at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) at org.mortbay.jetty.Server.handle(Server.java:326) at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923) at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:547) at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)



这就是为什么我一直在想 persist发生在交易中,尽管我没有明确地开始交易。

以下是来自 DataNucleus 的相关调试消息:

08:38:17,587 DEBUG [DataNucleus.Persistence] - ================= Persistence Configuration =============== 08:38:17,587 DEBUG [DataNucleus.Persistence] - DataNucleus Persistence Factory - Vendor: "DataNucleus" Version: "3.1.3" 08:38:17,588 DEBUG [DataNucleus.Persistence] - DataNucleus Persistence Factory initialised for datastore URL="appengine" driver="" userName="" 08:38:17,588 DEBUG [DataNucleus.Persistence] - JDK : 1.6.0_26 on Linux 08:38:17,588 DEBUG [DataNucleus.Persistence] - Persistence API : JPA 08:38:17,588 DEBUG [DataNucleus.Persistence] - Plugin Registry : org.datanucleus.plugin.NonManagedPluginRegistry 08:38:17,588 DEBUG [DataNucleus.Persistence] - Persistence-Unit : transactions-optional 08:38:17,588 DEBUG [DataNucleus.Persistence] - Standard Options : pm-singlethreaded, retain-values, nontransactional-read, nontransactional-write, serverTimeZone=UTC 08:38:17,589 DEBUG [DataNucleus.Persistence] - Persistence Options : detach-on-close deletion-policy=JDO2 08:38:17,589 DEBUG [DataNucleus.Persistence] - Transactions : type=RESOURCE_LOCAL mode=optimistic isolation=read-committed 08:38:17,589 DEBUG [DataNucleus.Persistence] - Value Generation : txn-isolation=read-committed connection=New 08:38:17,589 DEBUG [DataNucleus.Persistence] - ClassLoading : jdo 08:38:17,589 DEBUG [DataNucleus.Persistence] - Cache : Level1 (soft), Level2 (soft, mode=UNSPECIFIED), QueryResults (soft), Collections/Maps 08:38:17,589 DEBUG [DataNucleus.Persistence] - =========================================================== 08:38:17,657 DEBUG [DataNucleus.Persistence] - Object Manager "org.datanucleus.ObjectManagerImpl@e4eb585" opened for datastore "com.google.appengine.datanucleus.DatastoreManager@516f3619" with txn="org.datanucleus.TransactionImpl@5c48cd13" 08:38:17,688 DEBUG [DataNucleus.Persistence] - Making object persistent : "com.example.jpa.Department@55b7bf86" 08:38:17,736 DEBUG [DataNucleus.Persistence] - Object "com.example.jpa.Department@55b7bf86" has been marked for persistence but its actual persistence to the datastore will be delayed due to use of optimistic transactions or "delayDatastoreOperationsUntilCommit" 08:38:17,741 DEBUG [DataNucleus.Persistence] - Making object persistent : "com.example.jpa.Employee@95d0a50" 08:38:17,742 DEBUG [DataNucleus.Persistence] - Object "com.example.jpa.Employee@95d0a50" has been marked for persistence but its actual persistence to the datastore will be delayed due to use of optimistic transactions or "delayDatastoreOperationsUntilCommit" 08:38:17,747 DEBUG [DataNucleus.Transaction] - Transaction created [DataNucleus Transaction, ID=Xid= 08:38:17,748 DEBUG [DataNucleus.Transaction] - Transaction begun for ObjectManager org.datanucleus.ObjectManagerImpl@e4eb585 (optimistic=true) 08:38:17,757 DEBUG [DataNucleus.Transaction] - Running enlist operation on resource: com.google.appengine.datanucleus.DatastoreXAResource@7d7082d8, error code TMNOFLAGS and transaction: [DataNucleus Transaction, ID=Xid= 08:38:18,024 DEBUG [DataNucleus.Transaction] - Started datastore transaction: 0 08:38:18,026 DEBUG [DataNucleus.Transaction] - Transaction committing for ObjectManager org.datanucleus.ObjectManagerImpl@e4eb585 08:38:18,027 DEBUG [DataNucleus.Persistence] - ObjectManager.internalFlush() process started using ordered flush - 2 dirty objects 08:38:18,105 DEBUG [DataNucleus.Persistence] - Managing Persistence of Class : com.example.jpa.Employee [Table : com.example.jpa.Employee, InheritanceStrategy : new-table] 08:38:18,136 DEBUG [DataNucleus.Persistence] - Managing Persistence of Class : com.example.jpa.Department [Table : com.example.jpa.Department, InheritanceStrategy : new-table] 08:38:18,316 DEBUG [DataNucleus.Persistence] - Field "com.example.jpa.Department.employees" is being persisted for "cascade-persist". 08:38:18,331 INFO [DataNucleus.Persistence] - Object "com.example.jpa.Department@55b7bf86" has a collection "com.example.jpa.Department.employees" yet element "com.example.jpa.Employee@95d0a50" doesnt have the owner set. Managing the relation and setting the owner. 08:38:18,333 WARN [DataNucleus.MetaData] - Meta-data warning for com.example.jpa.Employee.department: Error in meta-data for com.example.jpa.Employee.department : The datastore does not support joins and therefore cannot honor requests to place related objects in the default fetch group. The field will be fetched lazily on first access. You can modify this warning by setting the datanucleus.appengine.ignorableMetaDataBehavior property in your config. A value of NONE will silence the warning. A value of ERROR will turn the warning into an exception. 08:38:18,354 DEBUG [DataNucleus.Persistence] - ObjectManager.internalFlush() process finished 08:38:18,355 DEBUG [DataNucleus.Transaction] - Illegal argument org.datanucleus.exceptions.NucleusFatalUserException: Illegal argument

最佳答案

刚遇到同样的问题,可以自信地说,当你打电话时事务已提交

EntityManager.close();

这是一些 prove来自 DataNucleus JPA 实现

关于google-app-engine - Google App Engine : When calling persist(. ..) 上的 JPA,它总是发生在事务中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15979389/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com