Desde hace años es sabido que concatenar strings con el operador + no es nada recomendable por su bajo rendimiento respecto a otras opciones. Pero la facilidad de su uso ha conseguido que a estas alturas sea la primera opción que usan muchos programadores para juntar varios strings en uno.
Si lo que estás haciendo es un programa tipo "hola mundo" no vas a notar mucha diferencia entre usar el + o no, pero cuando ya te metes en algo más serio puedes estar creando una ralentización de tu código sin saberlo y que tiene muy facil solución: NO USES EL +
La opción con mejor rendimiento es usar StringBuilder y juntar Strings mediante el método append. Pongamos un ejemplo:
String juntaletras = new StringBuilder().append("A").append("BE").append("C").toString();
Como ves tampoco te va a llevar mucho más tiempo hacerlo de esta forma y a la larga vas a salir ganando. La única pega del StringBuilder es que no es synchronized y te puedes llevar un chasco si estás usando programación recurrente multihilos. Para asegurar que tus datos no se corrompen en esos casos puedes usar sin ningún problema StringBuffer. Su uso es similiar a StringBuilder:
String juntaletras = new StringBuffer().append("A").append("BE").append("C").toString();
Cualquiera de las dos opciones mejora el rendimiento del operador + así que ante la duda puedes usar siempre StringBuffer ;)
Limpia tu código
Resoluciones de bugs y expedientes X del día a día que aparecen en tu código cuando menos te lo esperas.
miércoles, 19 de febrero de 2014
miércoles, 12 de febrero de 2014
Obtener un array de strings que vienen en un clob
Cada día me sigo sorprendiendo más y más del género humano.
Hoy me he encontrado con la necesidad de obtener un listado de dnis que vienen guardados en un clob para luego tener que recorrerlos para quedarme con los ids a los que corresponden dichos dnis.
La solución más limpia que he encontrado ha sido la siguiente:
DECLARE
dnis apex_application_global.vc_arr2;
persona_id number;
BEGIN
dnis := apex_util.string_to_table(dbms_lob.substr(:NEW.LISTADO,length(:NEW.LISTADO),1), ', ');
FOR i IN 1..dnis.count LOOP
SELECT id INTO persona_id FROM persona WHERE dnis(i) = dni;
END LOOP;
END;
Cuidado porque si el clob (:NEW.LISTADO) tiene mas de 4000 caracteres va a dar error en la función dbms_lob.substr (que pasa un clob a un varchar2). Como en mi caso se que no va a ser nunca tan grande no me he preocupado pero si no habría que evitarlo (próximamente en sus pantallas...).
Si lo usas dentro de una function o procedure entonces podrías guardar hasta 32767 caracteres en un varchar2.
La gracia del asunto es usar las librerias de apex que metieron en oracle 10, usando por un lado los vectores (apex_application_global.vc_arr2) y por otro lado apex_util.string_to_table que pasa un string a vector indicándole un separador (en mi caso era la ',').
Hoy me he encontrado con la necesidad de obtener un listado de dnis que vienen guardados en un clob para luego tener que recorrerlos para quedarme con los ids a los que corresponden dichos dnis.
La solución más limpia que he encontrado ha sido la siguiente:
DECLARE
dnis apex_application_global.vc_arr2;
persona_id number;
BEGIN
dnis := apex_util.string_to_table(dbms_lob.substr(:NEW.LISTADO,length(:NEW.LISTADO),1), ', ');
FOR i IN 1..dnis.count LOOP
SELECT id INTO persona_id FROM persona WHERE dnis(i) = dni;
END LOOP;
END;
Cuidado porque si el clob (:NEW.LISTADO) tiene mas de 4000 caracteres va a dar error en la función dbms_lob.substr (que pasa un clob a un varchar2). Como en mi caso se que no va a ser nunca tan grande no me he preocupado pero si no habría que evitarlo (próximamente en sus pantallas...).
Si lo usas dentro de una function o procedure entonces podrías guardar hasta 32767 caracteres en un varchar2.
La gracia del asunto es usar las librerias de apex que metieron en oracle 10, usando por un lado los vectores (apex_application_global.vc_arr2) y por otro lado apex_util.string_to_table que pasa un string a vector indicándole un separador (en mi caso era la ',').
lunes, 10 de febrero de 2014
Configurar timeout de arranque y parada de Tomcat en Eclipse
Se guro que la mayoría de vosotros sabéis montar un Tomcat en Eclipse (es relativamente fácil y puede que me anime a hacer un minitutorial, aunque ya los hay a patadas) así que nos vamos a poner en ese supuesto.
Le dais a correr y ... Ops! error de timeout en la inicialización!!
Al final meterle tantos frameworks, plugins y demás parafernalia al proyecto lo ha convertido en un caballo de guerra que le cuesta bastante arrancar y el tomcat por defecto del eclipse no le da tiempo a montarlo todo en 45 segundos.
No te preocupes porque puedes ir un paso más en la configuración y ajustar dicho valor.
Vas a la vista (view) de servidores (servers) y ahí tendrás tus servidores.
Haz doble click en el nombre del servidor y se abrirá una pantalla con nombre Overview.
Le das a la opción Timeouts y ahí podrás asignar libremente el valor en segundos del timeout de arranque y de parada.
¡Cuando termines no te olvides de guardar!
Le dais a correr y ... Ops! error de timeout en la inicialización!!
Al final meterle tantos frameworks, plugins y demás parafernalia al proyecto lo ha convertido en un caballo de guerra que le cuesta bastante arrancar y el tomcat por defecto del eclipse no le da tiempo a montarlo todo en 45 segundos.
No te preocupes porque puedes ir un paso más en la configuración y ajustar dicho valor.
Vas a la vista (view) de servidores (servers) y ahí tendrás tus servidores.
Haz doble click en el nombre del servidor y se abrirá una pantalla con nombre Overview.
Le das a la opción Timeouts y ahí podrás asignar libremente el valor en segundos del timeout de arranque y de parada.
¡Cuando termines no te olvides de guardar!
miércoles, 5 de febrero de 2014
Crear un sequence con el maximo id de una tabla con execute immediate
Seguimos solucionando desaguisados y nos hemos encontrado con una tabla que no tiene ningún sequence para generar ids y se estaban metiendo a pelo.
Como en los distintos entornos (desarrollo, pruebas, producción,...) la tabla en cuestión tiene distinto número de elementos y queremos una solución única para todos los entornos voy a coger el máximo valor del id de la tabla para que la sequence se quede con ese valor para generar el próximo id.
Para ello vamos a usar la función execute immediate dentro de un script que solucionará nuestros problemas.
Primero declaramos una variable integer donde guardar el max id y con una fácil select le añadimos dicho valor. Luego para crear el sequence usamos execute immediate que va a ejecutar lo que le pasemos como parámetro, así que le pasamos el código para crear la secuencia concatenando el valor obtenido antes y asunto solucionado.
Os dejo un ejemplo para que lo disfruteis:
declare
secuencia integer;
begin
select max(id)+1 into secuencia from tabla_sin_sequence;
execute immediate 'CREATE SEQUENCE SEQ_TABLA
MINVALUE 1
MAXVALUE 999999999999999999999999999
INCREMENT BY 1
START WITH ' ||secuencia ||
' NOCACHE
ORDER
CYCLE';
end;
/
Como en los distintos entornos (desarrollo, pruebas, producción,...) la tabla en cuestión tiene distinto número de elementos y queremos una solución única para todos los entornos voy a coger el máximo valor del id de la tabla para que la sequence se quede con ese valor para generar el próximo id.
Para ello vamos a usar la función execute immediate dentro de un script que solucionará nuestros problemas.
Primero declaramos una variable integer donde guardar el max id y con una fácil select le añadimos dicho valor. Luego para crear el sequence usamos execute immediate que va a ejecutar lo que le pasemos como parámetro, así que le pasamos el código para crear la secuencia concatenando el valor obtenido antes y asunto solucionado.
Os dejo un ejemplo para que lo disfruteis:
declare
secuencia integer;
begin
select max(id)+1 into secuencia from tabla_sin_sequence;
execute immediate 'CREATE SEQUENCE SEQ_TABLA
MINVALUE 1
MAXVALUE 999999999999999999999999999
INCREMENT BY 1
START WITH ' ||secuencia ||
' NOCACHE
ORDER
CYCLE';
end;
/
lunes, 23 de diciembre de 2013
Obtener el valor de un nodo de un xml en Oracle
Espero por vuestro bien que a nadie se le haya ocurrido guardar un fichero xml con una serie de datos que vayas a necesitar en un blob... pero si a alguno de vuestros compañeros le ha poseido Satán y ha hecho tan atroz fechoría os dejo una forma de obtener dichos datos.
Supongamos que tenemos una tabla_del_demonio con un id y un campo_blob. Para el id 1816 dentro del campo blob guardas un fichero xml de este tipo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<attributes xmlns="http://www.sat.an/attributes/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:ns3="http://www.sat.an/attributes/trabajadores/1.0">
<trabajador>
<nombre>Daniel</nombre>
<apellido1>Garcia</apellido1>
<apellido2>Fernandez</apellido2>
<ns3:dni>123456789B</ns3:dni>
</specificData>
</attributes>
Para quedarnos con el valor del dni habría que hacer lo siguiente:
select extractvalue(X.XML, '/attributes/trabajador/ns3:dni', 'xmlns="http://www.sat.an/attributes/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:ns3="http://www.sat.an/attributes/trabajadores/1.0"')
from (select XMLType(campo_blob,178) XML
from tabla_del_demonio
where id=1816) X;
Supongamos que tenemos una tabla_del_demonio con un id y un campo_blob. Para el id 1816 dentro del campo blob guardas un fichero xml de este tipo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<attributes xmlns="http://www.sat.an/attributes/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:ns3="http://www.sat.an/attributes/trabajadores/1.0">
<trabajador>
<nombre>Daniel</nombre>
<apellido1>Garcia</apellido1>
<apellido2>Fernandez</apellido2>
<ns3:dni>123456789B</ns3:dni>
</specificData>
</attributes>
Para quedarnos con el valor del dni habría que hacer lo siguiente:
select extractvalue(X.XML, '/attributes/trabajador/ns3:dni', 'xmlns="http://www.sat.an/attributes/1.0" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:ns3="http://www.sat.an/attributes/trabajadores/1.0"')
from (select XMLType(campo_blob,178) XML
from tabla_del_demonio
where id=1816) X;
viernes, 20 de diciembre de 2013
Transformar Clob a Varchar2 en Oracle
Muchas veces te encuentras por misterios de la naturaleza que nadie comprende que en una tabla se está guardando un string de pequeñas dimensiones en un clob.
Si necesitas hacer alguna búsqueda con él, la manera más sencilla es la siguiente:
select * from tabla_misteriosa t where dbms_lob.substr(t.campo_clob,length(t.campo_clob),1) = 'abcdefg';
Si lo que hay dentro del campo_clob tiene un tamaño menor de 4000 caracteres no tendrás ningún problema; pero si es mayor y menor de 32767 caracteres todavía te queda otro camino relativamente facil: usar pl/sql en vez de sql
declare
ristra varchar2;
begin
for t in ( select * from tabla_misteriosa )
loop
ristra := dbms_lob.substr( t.campo_clob, length(t.campo_clob), 1 );
-- Via libre a lo que quieras hacer con ristra
Si necesitas hacer alguna búsqueda con él, la manera más sencilla es la siguiente:
select * from tabla_misteriosa t where dbms_lob.substr(t.campo_clob,length(t.campo_clob),1) = 'abcdefg';
Si lo que hay dentro del campo_clob tiene un tamaño menor de 4000 caracteres no tendrás ningún problema; pero si es mayor y menor de 32767 caracteres todavía te queda otro camino relativamente facil: usar pl/sql en vez de sql
declare
ristra varchar2;
begin
for t in ( select * from tabla_misteriosa )
loop
ristra := dbms_lob.substr( t.campo_clob, length(t.campo_clob), 1 );
-- Via libre a lo que quieras hacer con ristra
miércoles, 18 de diciembre de 2013
Eclipse ERROR: No generator named “xxx” is defined in the persistence unit
Usando Eclipse con las herramientas de Hibernate te puede salir el error "No generator named “xxx” is defined in the persistence" unit a la hora de usar @GenericGenerator sin que realmente haya dicho error debido a un bug.
Ejemplo:
En el ejemplo anterior Eclipse te marcará un error en la línea
@GeneratedValue(generator = “informeGenerator“)
indicando No generator named “informeGenerator” is defined in the persistence unit
Actualmente no hay una solución limpia a este bug, pero si quieres que no te moleste puedes desactivarlo desde la opción de menú Preferences -> Java Persistence -> JPA -> Error/Warnings
y marcar Generator is not defined in the persistence unit con Warning.
Ejemplo:
@Id
@GeneratedValue(generator = “informeGenerator“)
@GenericGenerator(name = “informeGenerator“, strategy = “foreign”, parameters = { @Parameter(name = “property”, value = “informeId”) })
public String getId() { return id; }
En el ejemplo anterior Eclipse te marcará un error en la línea
@GeneratedValue(generator = “informeGenerator“)
indicando No generator named “informeGenerator” is defined in the persistence unit
Actualmente no hay una solución limpia a este bug, pero si quieres que no te moleste puedes desactivarlo desde la opción de menú Preferences -> Java Persistence -> JPA -> Error/Warnings
y marcar Generator is not defined in the persistence unit con Warning.
Suscribirse a:
Comentarios (Atom)