我花了将近8个小时,在网上搜索(包括SO),不得不在这个论坛上提出我的问题,但无济于事。我的问题与JPA @Version field doesn't get incremented有关,但存在一些差异。
我的设置:Java,JPA 2.0,DataNucleus 3.1.3,Google App Engine SDK 1.9.17。
我有一个数据模型User,其中有一个用@Version注释的字段,如下所示:
import javax.persistence.Table;
import javax.persistence.Version;
import org.datanucleus.api.jpa.annotations.Extension;
@Entity(name="User")
@Table(name="User")
public class User
implements Serializable {
private static final long serialVersionUID = -6706180854431454626L;
public User() {
}
@Id
@Column (name="USER_IDEN_PK",nullable=false)
....
....
@Basic (fetch = FetchType.EAGER)
@Column (name="USER_LAST_LOGOUT_TIMESTAMP",nullable=false)
private Long userLastLogoutTimestamp = null;
@Version
private Integer version;
public void setUserLastLogoutTimestamp(Long userLastLogoutTimestamp) {
this.userLastLogoutTimestamp = userLastLogoutTimestamp;
}
public Integer getVersion() {
return version;
}
public void setVersion(Integer version) {
this.version = version;
}
以下是用户实体更新的代码。 paramUser参数是更新后的User实体,需要在Google App Engine的高复制数据存储区中保留。
public synchronized User updateUser (User paramUser)
throws Exception {
User existingUser = null;
existingUser = getUserByUserIden(paramUser.getUserIden());
logger.info("exst ver = " + existingUser.getVersion().intValue());
logger.info("param ver = " + paramUser.getVersion().intValue());
if(null != existingUser) {
modifiedUser = tu.getEM().merge(paramUser);
tu.getEM().flush();
}
logger.info("new ver = " + modifiedUser.getVersion().intValue());
return modifiedUser;
}
以下是发生的事情:
这是一个问题:反对"新版本",我仍然得到" 1",而我的期望是我会得到一个" 2"。即使在底层的GAE数据存储区中,"版本"的价值也是如此。遗体" 1"。
我需要做些什么才能使JPA / DataNucleus / GAE / High-Replication数据存储区增加"版本"字段乘以1,当我打电话给"合并" API?
任何帮助/见解/建议都将受到高度赞赏。
这是日志:
2015-07-08 21:57:33.147
com.applix.imedipro.serverapp.controller.UserController update: paramJSONUser = {"userIden":"someUserIden","userPassword":"someUserPassword","userName":"someUserName","userMobile":2222222222,"userStreet":"someUserStreet","userArea":"someUserArea","userTown":"someUserTown","userDistrict":"someUserDistrict","userState":"someUserState","userCountry":"someUserCountry","userListOfRoleNames":["SuperUser"],"userLastLoginTimestamp":1436372833064,"userLastLogoutTimestamp":0,"version":1}
I 2015-07-08 21:57:33.147
com.applix.imedipro.serverapp.dao.DaoUser <init>: This object is com.applix.imedipro.serverapp.dao.DaoUser@1cf2d14
D 2015-07-08 21:57:33.148
org.datanucleus.ObjectManagerImpl initialiseLevel1Cache: Level 1 Cache of type "soft" initialised
D 2015-07-08 21:57:33.148
org.datanucleus.ObjectManagerImpl <init>: Object Manager "org.datanucleus.ObjectManagerImpl@989fda" opened for datastore "com.google.appengine.datanucleus.DatastoreManager@1b71125" with txn="org.datanucleus.TransactionImpl@26b3fb"
D 2015-07-08 21:57:33.148
org.datanucleus.transaction.Transaction <init>: Transaction created [DataNucleus Transaction, ID=Xid=
D 2015-07-08 21:57:33.148
org.datanucleus.TransactionImpl internalBegin: Transaction begun for ObjectManager org.datanucleus.ObjectManagerImpl@989fda (optimistic=true)
D 2015-07-08 21:57:33.148
com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection <init>: Created ManagedConnection using DatastoreService = com.google.appengine.api.datastore.DatastoreServiceImpl@f2343a
D 2015-07-08 21:57:33.148
org.datanucleus.transaction.Transaction enlistResource: Running enlist operation on resource: com.google.appengine.datanucleus.DatastoreXAResource@735d7f, error code TMNOFLAGS and transaction: [DataNucleus Transaction, ID=Xid=
D 2015-07-08 21:57:33.151
com.google.appengine.datanucleus.DatastoreXAResource start: Started datastore transaction: 4261602282148180867
D 2015-07-08 21:57:33.152
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection added to the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.157
org.datanucleus.ObjectManagerImpl getObjectFromLevel1Cache: Object with id "com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM" not found in Level 1 cache [cache size = 0]
D 2015-07-08 21:57:33.157
org.datanucleus.ObjectManagerImpl putObjectIntoLevel1Cache: Object "com.applix.imedipro.entity.User@4d3c7d" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") added to Level 1 cache (loadedFlags="[NNNNYNNNNNNNNNN]")
D 2015-07-08 21:57:33.158
org.datanucleus.state.JDOStateManager wrapSCOField: Object "com.applix.imedipro.entity.User@4d3c7d" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") is having the value in field "userListOfRoleNames" replaced by a SCO wrapper
D 2015-07-08 21:57:33.158
org.datanucleus.store.types.sco.simple.ArrayList initialise: Created SCO wrapper for object "com.applix.imedipro.entity.User@4d3c7d" field "userListOfRoleNames" with 1 entries, using options="cached,allowNulls"
D 2015-07-08 21:57:33.158
org.datanucleus.ObjectManagerImpl enlistInTransaction: Object "com.applix.imedipro.entity.User@4d3c7d" (id="ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") enlisted in transactional cache
D 2015-07-08 21:57:33.158
org.datanucleus.ObjectManagerImpl getObjectFromLevel2Cache: Object with id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM" taken from Level 2 cache (fields="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]", version="") - represented as "com.applix.imedipro.entity.User@4d3c7d"
D 2015-07-08 21:57:33.158
org.datanucleus.state.LifeCycleState changeState: Object "com.applix.imedipro.entity.User@4d3c7d" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") has a lifecycle change : "P_CLEAN"->"P_NONTRANS"
D 2015-07-08 21:57:33.158
org.datanucleus.ObjectManagerImpl evictFromTransaction: Object "com.applix.imedipro.entity.User@4d3c7d" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") being evicted from transactional cache
D 2015-07-08 21:57:33.159
org.datanucleus.ObjectManagerImpl removeObjectFromLevel2Cache: Object with id="ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM" removed from Level 2 cache
D 2015-07-08 21:57:33.159
org.datanucleus.ObjectManagerImpl persistObjectInternal: Making object persistent : "com.applix.imedipro.entity.User@be62e9"
D 2015-07-08 21:57:33.159
org.datanucleus.ObjectManagerImpl enlistInTransaction: Object "com.applix.imedipro.entity.User@be62e9" (id="org.datanucleus.identity.IdentityReference@14fbfca") enlisted in transactional cache
D 2015-07-08 21:57:33.159
org.datanucleus.state.JDOStateManager makePersistent: Object "com.applix.imedipro.entity.User@be62e9" has been marked for persistence but its actual persistence to the datastore will be delayed due to use of optimistic transactions or "delayDatastoreOperationsUntilCommit"
D 2015-07-08 21:57:33.159
org.datanucleus.ObjectManagerImpl putObjectIntoLevel1Cache: Object "com.applix.imedipro.entity.User@be62e9" (id="org.datanucleus.identity.IdentityReference@14fbfca") added to Level 1 cache (loadedFlags="[YYYYYYYYYYYYYYY]")
D 2015-07-08 21:57:33.159
org.datanucleus.ObjectManagerImpl flushInternalWithOrdering: ObjectManager.internalFlush() process started using ordered flush - 1 dirty objects
I 2015-07-08 21:57:33.159
com.applix.imedipro.serverapp.dao.DaoUser updateUser: existing version = 1
I 2015-07-08 21:57:33.159
com.applix.imedipro.serverapp.dao.DaoUser updateUser: param version = 1
D 2015-07-08 21:57:33.160
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.160
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.160
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.160
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.160
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.160
com.google.appengine.datanucleus.EntityUtils putEntitiesIntoDatastore: Putting entity of kind User with key User("someUserIden") as {USER_TOWN[someUserTown], USER_AREA[someUserArea], USER_DISTRICT[someUserDistrict], VERSION[1], USER_Street[someUserStreet], USER_NAME[someUserName], USER_MOBILE[2222222222], userListOfRoleNames[[SuperUser]], USER_LAST_LOGOUT_TIMESTAMP[0], USER_COUNTRY[someUserCountry], USER_STATE[someUserState], USER_PASSWORD[someUserPassword], USER_LAST_LOGIN_TIMESTAMP[1436372833064], }
D 2015-07-08 21:57:33.164
org.datanucleus.ObjectManagerImpl replaceObjectId: Object "com.applix.imedipro.entity.User@be62e9" (id="org.datanucleus.identity.IdentityReference@14fbfca") being changed to be referenced by id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM" in Level 1 cache
D 2015-07-08 21:57:33.164
org.datanucleus.ObjectManagerImpl replaceObjectId: Object "com.applix.imedipro.entity.User@be62e9" (id="org.datanucleus.identity.IdentityReference@14fbfca") enlisted in transactional cache is now enlisted using id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM"
D 2015-07-08 21:57:33.164
org.datanucleus.store.connection.ConnectionManagerImpl allocateConnection: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.164
org.datanucleus.state.JDOStateManager wrapSCOField: Object "com.applix.imedipro.entity.User@be62e9" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") is having the value in field "userListOfRoleNames" replaced by a SCO wrapper
D 2015-07-08 21:57:33.164
org.datanucleus.store.types.sco.simple.ArrayList initialise: Created SCO wrapper for object "com.applix.imedipro.entity.User@be62e9" field "userListOfRoleNames" with 1 entries, using options="cached,allowNulls"
D 2015-07-08 21:57:33.164
org.datanucleus.ObjectManagerImpl flushInternal: ObjectManager.internalFlush() process finished
I 2015-07-08 21:57:33.164
com.applix.imedipro.serverapp.dao.DaoUser updateUser: new version = 1
I 2015-07-08 21:57:33.164
com.applix.transactions.TranxUtility postTransaction: EM is open
D 2015-07-08 21:57:33.165
org.datanucleus.TransactionImpl internalPreCommit: Transaction committing for ObjectManager org.datanucleus.ObjectManagerImpl@989fda
D 2015-07-08 21:57:33.165
org.datanucleus.ObjectManagerImpl flushInternalWithOrdering: ObjectManager.internalFlush() process started using ordered flush - 0 dirty objects
D 2015-07-08 21:57:33.165
org.datanucleus.ObjectManagerImpl flushInternal: ObjectManager.internalFlush() process finished
D 2015-07-08 21:57:33.165
org.datanucleus.ObjectManagerImpl putObjectsIntoLevel2Cache: Object "com.applix.imedipro.entity.User@be62e9" (id="ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") added to Level 2 cache (fields="[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]", version="1")
D 2015-07-08 21:57:33.165
org.datanucleus.transaction.Transaction commit: Committing [DataNucleus Transaction, ID=Xid=
I 2015-07-08 21:57:33.165
com.applix.transactions.TranxUtility postTransaction: transaction is active
I 2015-07-08 21:57:33.165
com.applix.transactions.TranxUtility postTransaction: About to start committing the transaction
D 2015-07-08 21:57:33.190
com.google.appengine.datanucleus.DatastoreXAResource commit: Committed datastore transaction: 4261602282148180867
D 2015-07-08 21:57:33.191
org.datanucleus.store.connection.ConnectionManagerImpl$1 managedConnectionPostClose: Connection removed from the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@4445f6 for key=org.datanucleus.ObjectManagerImpl@989fda in factory=ConnectionFactory:tx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@842f22]
D 2015-07-08 21:57:33.191
org.datanucleus.state.LifeCycleState changeState: Object "com.applix.imedipro.entity.User@be62e9" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") has a lifecycle change : "P_NEW"->"P_NONTRANS"
D 2015-07-08 21:57:33.191
org.datanucleus.ObjectManagerImpl evictFromTransaction: Object "com.applix.imedipro.entity.User@be62e9" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") being evicted from transactional cache
D 2015-07-08 21:57:33.191
org.datanucleus.TransactionImpl commit: Transaction committed in 26 ms
D 2015-07-08 21:57:33.191
org.datanucleus.state.JDOStateManager detach: Detaching object from persistence : "com.applix.imedipro.entity.User@be62e9" (depth=0)
I 2015-07-08 21:57:33.191
com.applix.transactions.TranxUtility postTransaction: Transaction committed
D 2015-07-08 21:57:33.192
org.datanucleus.state.JDOStateManager unwrapSCOField: Object "com.applix.imedipro.entity.User@be62e9" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") is having the SCO wrapper in field "userListOfRoleNames" replaced by the unwrapped value
D 2015-07-08 21:57:33.192
org.datanucleus.state.LifeCycleState changeState: Object "com.applix.imedipro.entity.User@be62e9" (id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM") has a lifecycle change : "P_NONTRANS"->"DETACHED_CLEAN"
D 2015-07-08 21:57:33.192
org.datanucleus.state.JDOStateManager disconnect: Disconnecting com.applix.imedipro.entity.User@be62e9 from StateManager[pc=com.applix.imedipro.entity.User@be62e9, lifecycle=DETACHED_CLEAN]
D 2015-07-08 21:57:33.192
org.datanucleus.ObjectManagerImpl removeObjectFromLevel1Cache: Object with id="com.applix.imedipro.entity.User:ahJzfmF0LWltZWRpcHJvLWJldGFyFwsSBFVzZXIiDW5pbWVzaF9wYXJtYXIM" being removed from Level 1 cache [current cache size = 1]
D 2015-07-08 21:57:33.192
org.datanucleus.ObjectManagerImpl disconnectObjectProvidersFromCache: Level 1 Cache cleared
D 2015-07-08 21:57:33.192
org.datanucleus.ObjectManagerImpl close: Object Manager "org.datanucleus.ObjectManagerImpl@989fda" closed
I 2015-07-08 21:57:33.192
com.applix.transactions.TranxUtility postTransaction: Entity Manager cleared
答案 0 :(得分:0)
最后,12小时后,找到答案。
以下是DID的代码:
public synchronized User updateUser (User paramUser)
throws Exception {
User user = null;
user = getUserByUserIden(paramUser.getUserIden());
user.setUserPassword(paramUser.getUserPassword());
user.setUserName(paramUser.getUserName());
user.setUserMobile(paramUser.getUserMobile());
user.setUserStreet(paramUser.getUserStreet());
user.setUserArea(paramUser.getUserArea());
user.setUserTown(paramUser.getUserTown());
user.setUserDistrict(paramUser.getUserDistrict());
user.setUserState(paramUser.getUserState());
user.setUserCountry(paramUser.getUserCountry());
user.setUserListOfRoleNames(paramUser.getUserListOfRoleNames());
user.setUserLastLoginTimestamp(paramUser.getUserLastLoginTimestamp());
user.setUserLastLogoutTimestamp(paramUser.getUserLastLogoutTimestamp());
user = tu.getEM().merge(user);
return user;
}
换句话说,以下是有效的序列: