Duda en la clase PO al instanciar un nuevo objeto

Inicio Foros Foro principal Desarrolladores Duda en la clase PO al instanciar un nuevo objeto

  • Este debate está vacío.
Viendo 6 entradas - de la 1 a la 6 (de un total de 6)
  • Autor
    Entradas
  • #31323

    Buenas tardes, creo que con una explicacion breve se va entender lo que deseo realizar.
    Al instanciar cualquier clase que extiende de PO se le expecifican ciertos parametros entre ellos el ID para el objeto. Si se le asigna 0, la clase PO genera un nuevo identificador y si se le especifica un ID esta obtiene los datos de objeto con dicho ID.
    Ahora, lo que necesito es crear un nuevo PO pero con un ID especifico.
    Al especificar el ID como mencione, la clase PO intenta obtener los datos y si no existe no crea el objeto persistente.
    Tengo el siguiente codigo:

    Code:
    /* creamos una instancia de la clase MProductQuery */
    MProductQuery mpq = new MProductQuery(this.getCtx(), this.getM_Product_ID(), this.get_TrxName());

    De esta manera la clase PO busca el objeto con el ID especificado, pero no lo crea. De esta otra manera:

    Code:
    /* creamos una instancia de la clase MProductQuery */
    MProductQuery mpq = new MProductQuery(this.getCtx(), 0, this.get_TrxName());

    la clase PO crea el objeto pero con un ID generado internamente por la clase.
    Intente realizar el proceso asi:

    Code:
    /* creamos una instancia de la clase MProductQuery */
    MProductQuery mpq = new MProductQuery(this.getCtx(), 0, this.get_TrxName());
    /* seteamos el id del producto */
    mpq.setM_Product_Query_ID(this.getM_Product_ID());

    pero no asigna el ID especificado. El objeto queda con el ID que le asigno la clase PO.

    Existe alguna manera de especificar en los parametros el ID que se desea para el nuevo PO?

    De antemano muchas gracias
    Hermann D. Schimpf

    #34177
    Javier Ader
    Participante

    Muy clara no la tengo, pero al llamar al contructo con id 0, el objeto se considera como “nuevo” (PO.m_createNew = true); y al ejecutar el PO.save(), necesariamente va a parar a PO.saveNew(); el cual en las primeras lineas se ve

    Code:
    // Set ID for single key – Multi-Key values need explicitly be set previously
    if (m_IDs.length == 1 && p_info.hasKeyColumn()
    && !m_KeyColumns[0].equals(“AD_Language”))
    {
    int no = DB.getNextID(getAD_Client_ID(), p_info.getTableName(), m_trxName);
    if (no <= 0) { log.severe("No NextID (" + no + ")"); return saveFinish (true, false); } m_IDs[0] = new Integer(no); set_ValueNoCheck(m_KeyColumns[0], m_IDs[0]); }

    lo cual termina llamando a set_valueNoCheck con el id calculado automaticamente por DB.getNextId; vos al llamar a mpq.setM_Product_Query_ID haces lo mismo pero ANTES del save (e.d, vos cambias el id de 0 a tu numero; pero despues el saveNew lo pisa).
    Para mi, tal vez evitando que se llege al saveNew… una de las formas que veo es (aunque tal vez no muy elegante y no se si no va a tirar algún tipo de error), creas un objeto nuevo (id = 0), lo salvas (eso va a parar a saveNew); lo volves a traer con el id generado automaticamente, se lo cambias con setM_Product_Query_ID al id que vos realmente queres y volves a ejecutar un save(). La teoria es que el ultimo save() no va a llamar a saveNew() , si no a saveUpdate() y tal vez (auqneu tenga bastantes dudas) el codigo de saveUpdate es lo suficientemente general como para permitir updates sobres columnas claves (me da la sensación que si, mirándolo un poco por arriba).

    Otra forma que veo es hacer el utlimo update a “mano” (DB.executeUpdate casi seguro que anda), ejecutando algo como
    “Update m_ProductQuery set m_productQuery_id =
    where m_productQuery_id =
    Viejo valor seria el que te dio atuomaticamente el saveNew().
    Ok, despues de esto obvimetne tenes que releer el objeto con usadno el constructor con el nuevo id.
    OTRA… que no se si va a andar, es NO definir m_productquery_id como Id en la base de datos (tal vez si sea necesario asociarlo al elemento MProductId y como “columana padre”). De esa manera, el saveNew, aun cuando es llamado, no entra dentro del if que genera el id automaticamente (m_IDs.length =0 ).

    Más allá de todo esto… estas usando como clave primaria la clave primaria de otra tabla? Es medio raro y problemático; supongo que podes hacer otro diseño que te sirva y no te complique las cosas; pero no se bien cual es la idea (me da la sensación que es una relación 1 a 1-0 entre productos y queries)

    #34179

    javAd,
    Cuando se genera un registro en la DB la PK NO puede ser modificada. Por algo es una PK. Para el caso que propones releer el registro, no hay forma de saber cual es el ID del registro generado a no ser que ejecute un SELECT MAX().. luego de la inserción en la DB, pero no tengo la seguridad que el ultimo registro sea el que se inserto recientemente, y además estos ya son demasiados pasos no adecuados para algo que quiza los desarrolladores puedan tener una solucion mas simple y efectiva.

    Federico o Franco, me pueden dar una mano con esto?

    Gracias
    Hermann D. Schimpf

    #34178
    Javier Ader
    Participante

    mschimpf, despues de ejecutar el save sobre un objeto po creado con Id 0, el nuevo id se obtiene como en cualquier otro objeto: o.getXXXX_ID() (despues del save, este metodo no te retorna 0, si no el nuevo id generado automaticamente).
    Ahora, a nivel de base de datos los valores de las claves primarias sí se pueden modificar en ciertos casos (por lo general si las claves primarias no son autonumericas; como es el la mayoría por no decir todas, las tablas de libertya).
    El siguiente update anda (asumiendo que hay un juguete con Id 100001; despues del update queda con Id 10)

    Code:
    update libertya.m_juguetes set m_juguetes_id = 10 where m_juguetes_id =1000001

    Lo que yo te propongo es (pero que no lo veo correcto en el sentido de diseño) es

    Code:
    MProductQuery mpq = new MProductQuery(this.getCtx(), this.getM_Product_ID(), this.get_TrxName());

    …. seteas lo que sea neceario….
    //lo salvas
    mpg.save();
    // y ahora podes hacer dos cosas
    //1)
    mpq.setM_Product_Query_ID(this.getM_Product_ID());
    mpg.save();

    //o 2)
    DB.executeUpdate(“Update m_ProductQuery set m_productQuery_id = “+
    this.getM_Product_ID() +
    ” where m_productQuery_id ” = mpg.getM_Product_Query_ID() );
    //este ejecuta el update de la clave primaria “a mano”
    //y ahora “lo relees”
    mpg = new MProductQuery(this.getCtx(), this.getM_Product_ID(), this.get_TrxName());

    En cualquier caso, esto es bastante mala práctica (internamente el servidor setea indices sobres la claves primarias…. cuando se cambian los valores de las claves, se tienen que modificar el indice lo cual puede ser muyyyyyy costoso).

    Lo que yo te digo igual es que debes estar intentando un diseño medio raro… por el código que pusiste estas intentando usar el id de un producto para setear el id (la clave primaria) de una fila en la tabla MProductQuery. Para lo único que puede tener sentido esto es para tener una relación 1 a 1 entre entre queries y productos (e.d un producto puede tener asociado a lo máximo una query ); si no es tu intención, entonces no se para que queres setear especificamente el id en la tabla query; si es tu intención, entonces deben haber mejores diseños.

    #34181
    Federico Cristina
    Superadministrador

    Hermann,

    Como estás.
    Tu problema radica sencillamente en una cuestión de diseño. En Libertya, toda tabla (salvo excepciones) DEBE contener una columna _ID, que será la PK, cuya numeración es gestionada por MSequence. Esto es en definitiva un autoincremental que se apoya en las secuencias físicas de Postgres.

    El seteo manual de identificadores para la columna asociada con la PK no es correcto, y es por ello que no podés lograrlo utilizando las funcionalidades de PO.

    Supongo que tu intención es tener una tabla de referencia con ciertos datos de tipo “Clave – Valores”, y en la columna _ID querés cargar las entradas específicas a la Clave (y éstos son ciertos valores específicos). Para ésto, además de la columna _ID, deberías tener una columna Value, a la cual podrás definirle una UK (para evitar repetidos) y cargar en ésta las Claves, pero abstrayéndote de la secuencia de la columna _ID (la cual recordemos es la PK). Luego podrás recuperar el ID mediante una simple sentencia SQL (o implementar un método getIDFromValue() o similar en la subclase M correspondiente).

    Mas allá de este comentario, teniendo el código completo de Libertya, podrías ver cómo modificar el core para permitir lo que planteás. Sin embargo, estarías brindando una funcionalidad que me parece no debería ser utilizada.

    Saludos,
    Federico

    #34182

    Bueno, he probado con las ideas que me han dado y me solucionan a medias ya que debo realizar muchos procesos y no he logrado realizar lo que deseo.

    La idea es realizar una ventana de solo lectura para una consulta rápida de artículos, de tal manera que, por ejemplo, el empleado del mostrador pueda acceder a esta consulta sin tener que pasar por la creación de las lineas de una factura.

    Revisando el código fuente de LY encontré que las ventanas de consulta rápida de artículos similar a la que se accede al crear una linea de factura (org.openXpertya.apps.search.InfoProduct), son creadas completamente a mano, no intercede el framework.
    En este caso, realizare una ventana de consulta similar a estas pero les realizo una consulta antes, se pueden asignar estas ventanas de ‘consulta’ directamente al menú como un ítem? En el caso que se pueda, les agradecería una guía de como realizar esta ventana de consulta ya que son bastante complejas.

    Gracias
    Hermann D. Schimpf

Viendo 6 entradas - de la 1 a la 6 (de un total de 6)
  • Debes estar registrado para responder a este debate.