JPA 2.0 @Version列没有增加

时间:2015-07-08 15:16:17

标签: google-app-engine jpa datanucleus

我花了将近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;
    }

以下是发生的事情:

  • 最初,"版本" field的值为1.读取用户实体 从数据库中显示在屏幕上。
  • 的一些属性 此用户实体已修改。
  • 试图坚持这一点 实体。
  • " paramUser"有所有未经修改和修改 领域。
  • 代码首先"找到" s实体,并按照我的 期待,我得到一个" 1"打印出来" exst ver"。
  • 然后代码打印" 1"反对" param ver",这也符合我的期望,因为我不应该修改这个值。
  • 代码然后"合并" paramUser"实体。此方法返回更新的用户实体,我将其保存在" 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

1 个答案:

答案 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;
}

换句话说,以下是有效的序列:

  • 阅读&#34;用户&#34; &#34; user&#34;中的实体,基于传入的键值&#34; paramUser&#34;
  • 复制&#34; paramUser&#34;中的所有字段进入&#34;用户&#34;
  • 合并&#34;用户&#34;