DEV Community

Edgar Rios Navarro
Edgar Rios Navarro

Posted on

Procesar una transacción remota (XML) mediante un procedimiento almacenado

Para enviar información (transaccional) hacia una base de datos centralizada, prodríamos emplear un servicio web: recibe los datos y los persiste de forma autónoma, segura y confiable. Pero como alternativa, es invocar un procedimiento almacenado remoto.

Consideremos la limitante que no podemos enviar la información en formato JSON. La versión del motor no lo soporta: Oracle 11g. La solución será emplear el formato XML.

No pasemos por alto los riesgos de enviar la información no cifrada (el sistema está en una red privada o no), el tamaño de los datos y el costo de procesamiento del servidor.


Este ejemplo nuestra cómo generar el formato XML en el cliente. Se etiqueta los bean's con la anotación @XmlRootElement.

/**
*
* @author erios
*/
@XmlRootElement
public class Cabecera {
private String numero;
private Date fecha;
private List<Detalle> detalle;
...
}
@XmlRootElement
public class Detalle {
private int secuencial;
private double monto;
...
}
public class Main {
public static String jaxbObjectToXML(Cabecera customer, boolean pretty) {
String xmlString = "";
try {
JAXBContext context = JAXBContext.newInstance(Cabecera.class);
Marshaller m = context.createMarshaller();
if(pretty){
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); // To format XML
}
StringWriter sw = new StringWriter();
m.marshal(customer, sw);
xmlString = sw.toString();
} catch (JAXBException e) {
e.printStackTrace();
}
return xmlString;
}
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cabecera>
<detalle>
<monto>10.0</monto>
<secuencial>1</secuencial>
</detalle>
<detalle>
<monto>6.95</monto>
<secuencial>2</secuencial>
</detalle>
<fecha>2016-09-13T13:23:28.319-05:00</fecha>
<numero>00001</numero>
</cabecera>
view raw Main.log hosted with ❤ by GitHub

El procedimiento para interpretar el xml y grabar las tablas correspondientes. La solución es válida para todas las base de datos relacionales (como Postgres y Sql Server), aunque el código varía entre ellas.

CREATE OR REPLACE PROCEDURE P_INSERT_DOCUMENTO(id_in IN CHAR,xml_in IN VARCHAR2) AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
INSERT INTO CABECERA(NUMERO,FECHA)
SELECT x.numero,to_date(replace(x.fecha,'T',' '),'YYYY-MM-DD HH24:MI:SS') fecha
FROM XMLTABLE ('/cabecera'
PASSING XMLTYPE(xml_in)
COLUMNS numero CHAR(5) PATH 'numero',
fecha VARCHAR2(19) PATH 'fecha') x
WHERE x.numero = id_in;
INSERT INTO DETALLE(NUMERO,SECUENCIAL,MONTO)
SELECT id_in,x.secuencial,TO_NUMBER(x.monto,'990.00') monto
FROM XMLTABLE ('/cabecera/detalle'
PASSING XMLTYPE(xml_in)
COLUMNS monto VARCHAR2(6) PATH 'monto',
secuencial NUMBER(4,0) PATH 'secuencial') x
;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE_APPLICATION_ERROR(-20112,'Error al grabar:'||SQLERRM);
END;
DECLARE
id_in CHAR(5);
xml_in VARCHAR2(500);
BEGIN
id_in := '00001';
xml_in := '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cabecera>
<detalle>
<monto>10.0</monto>
<secuencial>1</secuencial>
</detalle>
<detalle>
<monto>6.95</monto>
<secuencial>2</secuencial>
</detalle>
<fecha>2016-09-13T13:23:28.319-05:00</fecha>
<numero>00001</numero>
</cabecera>';
P_INSERT_DOCUMENTO(id_in,xml_in);
END;

Documentación

https://github.com/edgargs/Ejemplo-2016-01.git
http://howtodoinjava.com/jaxb/jaxb-exmaple-marshalling-and-unmarshalling-list-or-set-of-objects/
http://viralpatel.net/blogs/oracle-xmltable-tutorial/

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Billboard image

Create up to 10 Postgres Databases on Neon's free plan.

If you're starting a new project, Neon has got your databases covered. No credit cards. No trials. No getting in your way.

Try Neon for Free →

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay