Uso de una relación de propiedad de uno a muchos en JDO - AppEngine

Soy nuevo en JDO y su concepto. Trabajé con ORMLite antes, lo cual es muy simple, y no puedo entender cómo debo hacer en JDO lo que hice en ORMLite. tengo 2 entidades, Broadcast y Movie. . Every Cada Broadcast Tiene uno Movie y Movie puede tener muchos Broadcastss. El id de un broadcast no se genera, se configura antes de persistirlo. Así que esto es lo que hice:

@PersistenceCapable
public class Broadcast {

    @PrimaryKey
    private String id;

    @Persistent
    private Movie movie;

    //More fields....
}

Ahora este es el Movie clase (nuevamente, la identificación no se genera, se configura antes de guardar el objeto):

@PersistenceCapable
public class Movie {

    @PrimaryKey
    private String id;

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

    //More fields....
}

Ahora, tengo un servlet que está obteniendo y guardando todos los datos en la base de datos. Primero, busco todos los Broadcasts, para cada Broadcastde la película todo lo que sé es el título y su ID, así que guardo el Broadcast con un Movie object en él con una transacción (porque hay dos objetos que se guardan, por lo que debe ser una acción atómica):

// 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());
}

Luego, busco los datos de la película y los guardo también, con la misma ID, anulando el objeto anterior (en otro hilo sin referencia a la Broadcast objeto).

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

Para que quede claro, esto es lo que sucede en ORMLite y lo que quiero que suceda aquí. Cuando estoy guardando el Broadcast objeto, estoy agregando la película con la identificación, por lo que en el futuro esta identificación lo ayudará a obtener una referencia a su Movie en la base de datos.

Pero cada vez que consulto la base de datos para transmisiones y espero encontrar referencias a películas en ellas, todo lo que obtengo es nulo o esta excepción:

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?

Entonces, ¿qué estoy haciendo mal aquí?

preguntado el 09 de marzo de 13 a las 14:03

3 Respuestas

Para usar relaciones en GAE, tienes que usar com.google.appengine.api.datastore.Key en lugar de teclas largas o de cadena. Ejemplo

respondido 09 mar '13, 16:03

Cambié la identificación de ambas clases a com.google.appengine.api.datastore.Key, pero desafortunadamente todavía no funciona. Traté de eliminar la parte de las películas persistentes y dejé solo la parte de la transmisión persistente con el objeto de la película dentro de ellas, y las películas no se agregaron a la base de datos por alguna razón. - elad92

Una pequeña explicación de lo que estaba pasando aquí: Tuve un List de transmisiones obtenidas de la web. Cada transmisión en la lista tenía un objeto de película dentro (Broadcast.setMovie), que solo tenía un título. Mi propósito era iterar sobre esta lista de transmisiones y obtener la información necesaria para cada película de transmisión (es por eso que usé mgr.flush() al final de cada operación). Entonces, primero agregué la transmisión al almacén de datos si no existía, y luego busqué los datos para la película y también los conservé. Y estaba mi problema, en ORMLite, cuando tienes un campo que es externo y almacenas este objeto, el marco está guardando este objeto y la identificación del objeto del campo externo. Entonces, digamos que tengo una transmisión con id = 10 y una película dentro de él con id = 2, el marco guardaría la transmisión en la base de datos con 2 en el campo de la película. Así que esto es lo que quería hacer aquí, pero en JDO no funciona así. Después de seguir el buen ejemplo que @Noofiz compartió en su respuesta, me di cuenta de que lo estaba haciendo mal y necesitaba hacerlo en orden inverso. Tome la película de cada objeto de transmisión, agregue la transmisión a la película usando Movie.addBroadcast y consérvela en el almacén de datos, y esto es lo que hice, y funciona bien.

Así que gracias a todos por su ayuda y espero que esto ayude a otras personas.

respondido 11 mar '13, 14:03

Hay un amplio muestras de código y código de persistencia asociado disponible para GAE JDO para todo tipo de relaciones (incluyendo 1-N bidir propiedad, que tienes).

Tiene algo de "descarga" después de que finaliza una transacción, no estoy seguro de por qué. No tiene ningún código que relacione los objetos Movie y Broadcast (es decir, ¿dónde está Movie.addBroadcast?). No hace ninguna referencia al registro (que le informa sobre todos los PUT y GET hacia/desde el almacén de datos). Usted dice que está recuperando una película y "guardándola sobrescribiendo la misma identificación", pero no hay un código que haga esto, o mencione en qué estado se encuentran los objetos en ese momento ... ¿transitorio? ¿separado?

respondido 10 mar '13, 09:03

Lamento esta falta de información. Resolví este problema y estoy publicando la respuesta con toda la información en este momento, por lo que puede ayudar a otros que enfrentarán el mismo problema que el mío. - elad92

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.