简体   繁体   English

在JDO中使用一对多拥有的关系-AppEngine

[英]Using one-to-many owned relationship in JDO - AppEngine

I'm new to JDO and its concept. 我是JDO及其概念的新手。 I worked with ORMLite before which is very simple, and I can't figure out how should I do in JDO what I did in ORMLite. 我以前使用过ORMLite,这很简单,而且我不知道该如何在JDO中做我在ORMLite中所做的事情。 I have 2 entities, Broadcast and Movie . 我有2个实体,分别是BroadcastMovie Every Broadcast has one Movie and a Movie can have many Broadcasts s. 每个Broadcast都有一部Movie ,一部Movie可以有许多Broadcasts The id of a broadcast is not generated, it's configured before persisting it. 广播的ID不会生成,它是在持久存储之前进行配置的。 So this is what I did: 这就是我所做的:

@PersistenceCapable
public class Broadcast {

    @PrimaryKey
    private String id;

    @Persistent
    private Movie movie;

    //More fields....
}

Now this is the Movie class (again the id is not generated, it's configured before saving the object): 现在这是Movie类(同样不会生成ID,它是在保存对象之前配置的):

@PersistenceCapable
public class Movie {

    @PrimaryKey
    private String id;

    @Persistent(mappedBy = "movie")
    private List<Broadcast> broadcasts;

    //More fields....
}

Now, I have a servlet that is fetching and saving all the data in the DB. 现在,我有一个servlet,它正在提取所有数据并将其保存在DB中。 First, I fetch all the Broadcasts , for every Broadcast 's movie all I know is the title, and its ID, so I save the Broadcast with a Movie object in it with a transaction (because there are two objects that are saved, so this must be atomic action): 首先,我获取所有Broadcasts ,对于Broadcast的所有电影,我所知道的都是标题及其ID,因此我通过事务保存了带有Movie对象的Broadcast (因为保存了两个对象,因此这必须是原子动作):

// Check if this broadcast already exist.
try {
     mgr.getObjectById(Broadcast.class, brdcst.getId());
} catch (Exception e) {
     if(e instanceof JDOObjectNotFoundException){
    Transaction tx = null;
    try{
        tx = mgr.currentTransaction();
        tx.begin();
        mgr.makePersistent(brdcst);
        tx.commit();
    }
    catch(Exception e1){
        sLogger.log(Level.WARNING, e.getMessage());
    }
    finally{
        if (tx.isActive()) {
            tx.rollback();
        }
        mgr.flush();
    }

     }
     else sLogger.log(Level.WARNING, e.getMessage());
}

Then, I'm fetching the movie's data and saving it too, with the same ID, overriding the previous object (In other thread with no reference to the Broadcast object). 然后,我以相同的ID来获取电影的数据并保存它,以覆盖先前的对象(在另一个没有引用Broadcast对象的线程中)。

try {
    sLogger.log(Level.INFO, "Added the movie: " + movie);
    mgr.makePersistent(movie);
} catch (Exception e) {
    e.printStackTrace();
}
finally{
    mgr.flush();
}

So just to be clear, this is what happening in ORMLite and what I want to happen here. 因此,要清楚一点,这就是ORMLite中发生的事情以及我想在这里发生的事情。 When I'm saving the Broadcast object I'm adding the movie with the ID to it, so in the future this ID will help him to get reference to its Movie in the database. 当我保存Broadcast对象时,我要添加具有ID的电影,因此将来使用此ID可以帮助他在数据库中引用其Movie

But whenever I'm querying the DB for broadcasts and hope to find references to movies in them all I get is null or this exception: 但是每当我在数据库中查询广播并希望在其中找到对电影的引用时,我得到的都是null或以下异常:

Field Broadcast.movie should be able to provide a reference to its parent but the entity does not have a parent.  Did you perhaps try to establish an instance of Broadcast as the child of an instance of Movie after the child had already been persisted?

So, what am I doing wrong here? 那么,我在这里做错了什么?

To use ralations in GAE, you have to use com.google.appengine.api.datastore.Key instead of long or String keys. 要在GAE中使用庆典,您必须使用com.google.appengine.api.datastore.Key而不是长键或字符串键。 Example

A bit explanation of what was going here: I had a List of Broadcasts fetched from the web. 关于这里发生的事情,有一点解释:我有一个从网络上获取的广播List Every Broadcast in the list had a Movie object inside (Broadcast.setMovie), which only had a title. 列表中的每个广播都有一个Movie对象(Broadcast.setMovie),里面只有一个标题。 My purpose was to iterate over this list of broadcasts and fetch the needed information for every Broadcast's movie (this is why I used mgr.flush() in the end of every operation). 我的目的是遍历此广播列表,并获取每个广播电影的所需信息(这就是为什么在每个操作结束时都使用mgr.flush()的原因)。 So first I added the Broadcast to the datastore if it didn't exist, and then fetched the data for the movie and persisted it too. 因此,如果广播不存在,我首先将其添加到数据存储中,然后获取电影的数据并将其持久化。 And there was my problem, in ORMLite, when you have a field which is foreign, and you store this object, the framework is saving this object and the id of the foreign field's object. 我的问题是,在ORMLite中,当您有一个外来字段并存储了该对象时,框架将保存该对象和外来字段的对象ID。 So, let's say I had a Broadcast with id=10 and a Movie inside him with id=2, the framework would save the Broadcast to the database with 2 in the movie field. 因此,假设我有一个id = 10的Broadcast和一个id = 2的电影,框架会将movie字段中的Broadcast保存为2。 So this is what I wanted to do here but in JDO it's not working like this. 所以这就是我想在这里做的,但是在JDO中,它不是这样工作的。 After following the good example @Noofiz shared in his answer, I figured out I was doing it wrong and needed to do it in reverse order. 在遵循@Noofiz在他的答案中分享的好例子之后,我发现我做错了,需要以相反的顺序进行。 Take the movie from every broadcast object, add the broadcast to the movie using Movie.addBroadcast and persist it in the datastore, and this is what I did, and it's working fine. 从每个广播对象中获取电影,使用Movie.addBroadcast将广播添加到电影中,并将其保存在数据存储区中,这就是我所做的,并且工作正常。

So thanks everyone for your help and I hope this will help other people. 因此,感谢大家的帮助,希望这对其他人有帮助。

There are ample code samples and associated persistence code available for GAE JDO for all types of relations (including 1-N bidir owned, that you have). 对于所有类型的关系(包括您拥有的1-N bidir,),GAE JDO都有足够的代码示例相关的持久性代码

You have some "flush" after a transaction has finished, what for I'm not sure. 交易完成后,您会有一些“刷新”,我不确定。 You have no code that relates the Movie and Broadcast objects (ie where is Movie.addBroadcast ?). 您没有与Movie和Broadcast对象相关的代码(即Movie.addBroadcast在哪里?)。 You make no reference to the log at all (which tells you about all PUTs and GETs to/from the datastore). 您根本不参考日志(它告诉您有关数据存储的所有PUT和GET)。 You say you're retrieving a Movie and "saving it overwriting the same id", but there is no code that does this, or mention of what state the objects are in at that time ... transient? 您说要检索电影并“保存以覆盖相同的ID”,但是没有代码可以做到这一点,也没有提到对象当时处于什么状态……瞬态? detached? 超脱?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM