无法使用GAE / J DataNucleus插件版本2.1.2获取新创建的JDO持久实体的ID [英] Unable to get ID of newly-created JDO persistent entity using GAE/J DataNucleus plug-in version 2.1.2

查看:101
本文介绍了无法使用GAE / J DataNucleus插件版本2.1.2获取新创建的JDO持久实体的ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题

我将我的应用程序从版本1.x移植到GAE / J的DataNucleus插件2.0新的1.7.5 GAE / J SDK。这将我的JDO版本从2.3更改为3.0.1。我的持久化实体类有一个编码字符串类型的主键,以及对对象数字ID的只读访问权限。每个实例都是其实体组的唯一成员(孩子和父母仅通过数字ID链接)。



以前,我已经能够创建并保存一个新的 MyEntity 实例,然后立即访问其数字ID以存储在父节点 MyEntity 实例的子ID列表中。



现在我发现新实例的数字ID在持久化后不可用 - 即使它是生成并存储的,并且可以在以后使用。



我的问题

在对象创建和持久化后立即还原对数字ID的访问权限吗?



jdoconfig.xml配置提取

 < persistence-manager-factory name =big-table> 
< property
name =javax.jdo.PersistenceManagerFactoryClass
value =org.datanucleus.api.jdo.JDOPersistenceManagerFactory
/>
< property name =datanucleus.DetachAllOnCommitvalue =true/>
< property name =javax.jdo.option.NontransactionalReadvalue =true/>
< property name =javax.jdo.option.NontransactionalWritevalue =true/>
name =datanucleus.appengine.autoCreateDatastoreTxns
value =true
/>
[...]
< / persistence-manager-factory>

持久性实体类代码解压缩

  @PersistenceCapable(identityType = IdentityType.APPLICATION,detachable =true)
public class MyEntity实现Serializable
{
private static最终的长串serialVersionUID = 1L;

//这个只读数据成员没有setter
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName =datanucleus ,key =gae.encoded-pk,value =true)
private String sEncodedKey;

//这个只读数据成员没有setter
@Persistent
@Extension(vendorName =datanucleus,key =gae.pk-id,value = true)
私有长LoID;

@Persistent
private Long loParentID;

//
//其他持久数据成员
//

public Long getID()
{
return loID ;
}

//
//其他获取者和设置者
//
}
$ b

持续代码包括3个记录点

  / ** 
*创建一个新实体。
* @param loParentID
*实体的ID,
*将创建一个新的子项。
* @param sChildName
*要创建的新子的名称。
* @return
*创建的实体孩子
*或< code> null< / code>如果手术进行失败。
* /
public static MyEntity createEntityChild(Long loParentID,String sChildName)
{
MyEntity meResult = null;
MyEntity mePersistedChild = null;

PersistenceManagerFactory pmf =
DataExchange.getPersistenceManagerFactory(); //我自己的方法
PersistenceManager pm = pmf.getPersistenceManager();
Transaction tx = pm.currentTransaction();
尝试
{
tx.begin();

MyEntity meChild = new MyEntity();
meChild.setParentID(loParentID);
meChild.setName(sChildName);
meChild.setActive(true);
mePersistedChild = pm.makePersistent(meChild);

//Touch数据成员不在默认提取组中
ArrayList< Long> liChildIDs = mePersistedChild.getChildIDs();
if(liChildIDs!= null)
liChildIDs.size();

if(mePersistedChild!= null)
g_logger.log(Level.FINE,String.format(
Pre-commit:mePersistedChild.getID()=%d,
+mePersistedChild.getEncodedKey()= \%s\。,
mePersistedChild.getID(),mePersistedChild.getEncodedKey()));

tx.commit();

if(mePersistedChild!= null)
g_logger.log(Level.FINE,String.format(
Post-commit:mePersistedChild.getID()=%d,
+mePersistedChild.getEncodedKey()= \%s\。,
mePersistedChild.getID(),mePersistedChild.getEncodedKey()));
}
finally
{
try
{
if(tx.isActive())//由于例外情况,例如
tx .rollback();
}
finally
{
pm.close();



if(mePersistedChild!= null)
g_logger.log(Level.FINE,String.format(
Post-pm- mePersistedChild.getID()=%d,
+mePersistedChild.getEncodedKey()= \%s\ ));

[...]

返回meResult;
}

开发者服务器记录输出

  24-Feb-2013 13:28:02 [...]。MyEntityBusiness createMyEntityChild 
FINE:Pre-commit:mePersistedChild.getID ()= null,mePersistedChild.getEncodedKey()=agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM。

24-Feb-2013 13:28:03 [...] MyEntityBusiness createMyEntityChild
FINE:Post-commit:mePersistedChild.getID()= null,mePersistedChild.getEncodedKey()= agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM。

24-Feb-2013 13:28:03 [...] MyEntityBusiness createMyEntityChild
FINE:Post-pm-close:mePersistedChild.getID()= null,mePersistedChild.getEncodedKey )=agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM。

2013年2月24日13:28:07 com.google.appengine.api.datastore.dev.LocalDatastoreService $ PersistDatastore persist
INFO:保存数据存储的时间:141 ms

JDO增强版验证

构建过程成功输出片段:

  datanucleusenhancer:
09:33:00,531(main)INFO [ DataNucleus.Enhancer] - 用于APIJDO的DataNucleus增强器
09:33:01,125(main)INFO [DataNucleus.Enhancer] - DataNucleus增强器(版本3.1.1):增强类
DataNucleus增强器版本3.1.1):增强类
09:33:03,281(main)INFO [DataNucleus.Enhancer] - 使用增强定义
[]编写类文件[Path] \MyEntity.class。 ..(共有N个条目)]
09:33:04,046(main)INFO [DataNucleus.Enhancer] - DataNucleus增强器成功完成[N]类。计时:输入= 1922毫秒,增强= 984毫秒,总计= 2906毫秒。请查阅日志查看全部细节
DataNucleus增强器完成[N]类成功。计时:输入= 1922毫秒,增强= 984毫秒,总计= 2906毫秒。查阅日志查看完整详情

软件环境




  • Web服务器:Google App Engine for Java 1.7.5版本

  • Web框架:Apache Wicket 6.5.0
  • >
  • Java版本:1.6.0_39; Java HotSpot(TM)客户机VM 20.14-b01

  • GAE / J DataNucleus插件版本:2.1.2 DataNucleus Access Platform版本:3.1 .3

  • JDO版本:3.0.1
  • 操作系统:在x86上运行的Microsoft Windows XP版本5.1

  • IDE:NetBeans 7.2(build 201207171143)


解决方案

GAE JDO插件只设置当它从数据存储中读取标有该字段的字段时,它会显示一个gae.pk-id/gae.pk-name字段(只需在SVN中搜索,FetchFieldManager是唯一加载的地方 - 当它执行PUT时设置它)。不知道它在1.x中做了什么,但是所有GAE自己的测试都以1.x形式通过2.x。但是那个功能不是标准的JDO,所以对我没什么兴趣。



JDO提供了生命周期监听器,你可以很容易地设置一个 postStore 回调,并在你的对象中设置一些字段(而不是依赖AppEngine特有的功能)。


My problem

I am porting my application from version 1.x to 2.0 of the DataNucleus plug-in for GAE/J using the new 1.7.5 GAE/J SDK. This changes my JDO version from 2.3 to 3.0.1. My persistent entity class has a primary key of type encoded string, along with read-only access to the object’s numeric ID. Each instance is the sole member of its entity group (children and parent are linked by numeric ID only).

Previously, I have been able to create and persist a new MyEntity instance and then immediately access its numeric ID to store in the parent MyEntity instance’s list of child IDs.

Now I find that the new instance’s numeric ID is not available immediately after persistence – even though it is generated and stored and is available later.

My question

Is there anything I can do to restore access to the numeric ID immediately following object creation and persistence?

"jdoconfig.xml" configuration extract

<persistence-manager-factory name="big-table">
  <property
   name="javax.jdo.PersistenceManagerFactoryClass"
   value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"
  />
  <property name="datanucleus.DetachAllOnCommit" value="true"/>
  <property name="javax.jdo.option.NontransactionalRead" value="true"/>
  <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
  <property
   name="datanucleus.appengine.autoCreateDatastoreTxns"
   value="true"
  />
  [...]
</persistence-manager-factory>

Persistent entity class code extract

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class MyEntity implements Serializable
{
  private static final long serialVersionUID = 1L;

  // No setter for this read-only data member
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
  private String sEncodedKey;

  // No setter for this read-only data member
  @Persistent
  @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
  private Long loID;

  @Persistent
  private Long loParentID;

  //
  // Other persistent data members
  //

  public Long getID()
  {
    return loID;
  }

  //
  // Other getters and setters
  //
}

Persistence code including 3 logging points

/**
 * Create a new entity.
 * @param loParentID
 *   The ID of the entity,
 *   a new child of which is to be created.
 * @param sChildName
 *   The name of the new child to be created.
 * @return
 *   The created entity child,
 *   or <code>null</code> if the operation was carried out unsuccessfully.
 */
public static MyEntity createEntityChild(Long loParentID, String sChildName)
{
  MyEntity meResult = null;
  MyEntity mePersistedChild = null;

  PersistenceManagerFactory pmf =
   DataExchange.getPersistenceManagerFactory();    // My own method
  PersistenceManager pm = pmf.getPersistenceManager();
  Transaction tx = pm.currentTransaction();
  try
  {
    tx.begin();

    MyEntity meChild = new MyEntity();
    meChild.setParentID(loParentID);
    meChild.setName(sChildName);
    meChild.setActive(true);
    mePersistedChild = pm.makePersistent(meChild);

    // "Touch" data member not in the default fetch group
    ArrayList<Long> liChildIDs = mePersistedChild.getChildIDs();
    if (liChildIDs != null)
      liChildIDs.size();

    if (mePersistedChild != null)
      g_logger.log(Level.FINE, String.format(
       "Pre-commit: mePersistedChild.getID() = %d,"
       + " mePersistedChild.getEncodedKey() = \"%s\".",
       mePersistedChild.getID(), mePersistedChild.getEncodedKey()));

    tx.commit();

    if (mePersistedChild != null)
      g_logger.log(Level.FINE, String.format(
       "Post-commit: mePersistedChild.getID() = %d,"
       + " mePersistedChild.getEncodedKey() = \"%s\".",
       mePersistedChild.getID(), mePersistedChild.getEncodedKey()));
  }
  finally
  {
    try
    {
      if (tx.isActive())    // Because of an exception, say
        tx.rollback();
    }
    finally
    {
      pm.close();
    }
  }

  if (mePersistedChild != null)
    g_logger.log(Level.FINE, String.format(
     "Post-pm-close: mePersistedChild.getID() = %d,"
     + " mePersistedChild.getEncodedKey() = \"%s\".",
     mePersistedChild.getID(), mePersistedChild.getEncodedKey()));

  [...]

  return meResult;
}

Dev server logging output

24-Feb-2013 13:28:02 [...].MyEntityBusiness createMyEntityChild
FINE: Pre-commit: mePersistedChild.getID() = null, mePersistedChild.getEncodedKey() = "agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM".

24-Feb-2013 13:28:03 [...].MyEntityBusiness createMyEntityChild
FINE: Post-commit: mePersistedChild.getID() = null, mePersistedChild.getEncodedKey() = "agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM".

24-Feb-2013 13:28:03 [...].MyEntityBusiness createMyEntityChild
FINE: Post-pm-close: mePersistedChild.getID() = null, mePersistedChild.getEncodedKey() = "agttYXJrZXQtdHJlZXISCxIMSXRlbUNhdGVnb3J5GAUM".

24-Feb-2013 13:28:07 com.google.appengine.api.datastore.dev.LocalDatastoreService$PersistDatastore persist
INFO: Time to persist datastore: 141 ms

JDO enhancement version verification

The build process succeeded with output fragment:

datanucleusenhancer:
09:33:00,531 (main) INFO  [DataNucleus.Enhancer] - DataNucleus Enhancer for API "JDO"
09:33:01,125 (main) INFO  [DataNucleus.Enhancer] - DataNucleus Enhancer (version 3.1.1) : Enhancement of classes
DataNucleus Enhancer (version 3.1.1) : Enhancement of classes
09:33:03,281 (main) INFO  [DataNucleus.Enhancer] - Writing class file "[Path]\MyEntity.class" with enhanced definition
[... (N entries in all)]
09:33:04,046 (main) INFO  [DataNucleus.Enhancer] - DataNucleus Enhancer completed with success for [N] classes. Timings : input=1922 ms, enhance=984 ms, total=2906 ms. Consult the log for full details
DataNucleus Enhancer completed with success for [N] classes. Timings : input=1922 ms, enhance=984 ms, total=2906 ms. Consult the log for full details

Software environment

  • Web server: Google App Engine for Java version 1.7.5
  • Web framework: Apache Wicket 6.5.0
  • Java version: 1.6.0_39; Java HotSpot(TM) Client VM 20.14-b01
  • GAE/J DataNucleus plug-in version: 2.1.2
  • DataNucleus Access Platform version: 3.1.3
  • JDO version: 3.0.1
  • Operating system: Microsoft Windows XP version 5.1 running on x86
  • IDE: NetBeans 7.2 (build 201207171143)

解决方案

The GAE JDO plugin only ever sets a "gae.pk-id"/"gae.pk-name" field when it reads in a field marked with that from the datastore (just do a search in SVN trunk, FetchFieldManager is the only place where it's loaded - it doesn't set it when it does a PUT). No idea what it did in 1.x, but all of GAE's own tests pass in 2.x as they did in 1.x. But then that "feature" isn't standard JDO anyway, so of little interest to me.

JDO provides lifecycle listener and you could easily enough set up a postStore callback and set some field in your object in that (and not be reliant on AppEngine-specific "features").

这篇关于无法使用GAE / J DataNucleus插件版本2.1.2获取新创建的JDO持久实体的ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆