JPA. JQL Java Persistence Query Language

Introducción JPA

JPA es un componente de la arquitectura J2EE que permite establecer un  interface de mapeo ORM (Object Relational Mapping) para  gestionar datos en aplicaciones Java.

Los datos que se gestionan en Java normalmente se solucionan a través de objetos, que tienen sus propios estados y comportamientos. Sin embargo, a la hora de almacenarlos (persistirlos) se usa habitualmente una base de datos relacional. Es por tanto necesario mapear o convertir esos objetos de Java en filas dentro de una tabla relacional.

A lo largo del tiempo se han intentado varias soluciones, tanto particulares como orientadas a un estándar, pero normalmente eran complejas de usar y sin una continuidad asegurada.

Para eso nació JPA, que se convierte en el estándar a la hora de realizar esta conversión objeto-relacional. Es una capa que se implementa sobre JDBC y que realiza por nosotros todo el trabajo pesado de mapeo. Este mapeo se suele hacer sobre metadatos, como XML o anotaciones.

De manera general, JPA viene implementado en varias áreas:

  • Las API que permiten la persistencia en Java
  • Un lenguaje de consulta denominado JPQL
  • Los metadatos que permiten el mapeo entre objetos y tablas relacionales

La funcionalidad de JPA es implementada a través de  un proveedor de persistencia de los que existen en la actualidad (como Hibernate, Eclipse Link, etc). Una de las ventajas de JPA es la de poder elegir en cualquier momento el proveedor que más se adapte a nuestras necesidades. Por tanto, es el proveedor quién implementa y realiza el trabajo de persistencia, pero siempre de acuerdo a las especificaciones indicadas en las API de JPA. 

Durante este artículo vamos a centrarnos en el lenguaje de consulta JPQL (Java Persistence Query Language), que permite acceder de forma rápida y sencilla a los datos que almacenamos a través de JPA.

Es conveniente, aunque no obligatorio conocer un poco el lenguaje SQL para sacar el mayor partido a JPQL, ya que muchas de sus instrucciones son iguales o muy parecidas.

Introducción a JPQL

Usando la interface “EntityManager”, podemos realizar accesos a la Base de datos, a través de la entidad correspondiente, pero tiene bastantes limitaciones en su funcionalidad.

Al contrario, JPQL nos permite realizar consultas a través de multitud de criterios posibles y obtener más de un objeto por consulta.

Es por tanto un entorno mucho más potente y sencillo de utilizar que comandos Java etándar.

Consultas. SELECT

Para poder acceder a los datos almacenados en una tabla relacional, la forma más simple de consulta JPQL es la siguiente

 SELECT a FROM alumnos a 

A través de este comando, podemos recuperar todos los objetos de la clase “Alumnos” que estarán almacenadas en la Base de Datos. Como vemos, el comando es muy similar a la SELECT del lenguaje SQL.

Como diferencia, la segunda cláusula “a” es un alias de la clase Alumnos que es usada por la primera “a” (denominada expresión) para acceder a la tabla de la Base de Datos y a sus propiedades (columnas de la tabla).

Por ejemplo para acceder a un atributo o columna de la tabla.

SELECT a.nombre FROM alumnos a

Por tanto, al igual que en SQL, desde JPQL se utiliza la notación de puntos para acceder a las propiedades.

SELECT a.nombre, a.apellidos FROM Alumnos a

Las consulta JPQL devuelve de 0 a N filas en cada operación, que luego se tendrán que tratar

Como SQL, se puede usar la cláusula DISTINCT para devolver filas que no estén duplicadas:

 

SELECT DISCTINCT a.nombre FROM Alumnos a

También podemos usar funciones dentro de las consultas. De nuevo vemos el parecido con SQL, ya que se usa la función COUNT para devolver el número de filas existentes en la tabla.

SELECT COUNT(a) FROM Alumnos a

Condiciones. Cláusula WHERE

Mediante la cláusula WHERE podemos poner condiciones en las consultas. De esta forma restringimos el número de filas a devolver por la consulta SELECT.

Su formato es el siguiente. En este caso recuperamos todos los alumnos que hayan suspendido matemáticas, suponiendo que haya un atributo que tenga ese dato (nota_matematicas).

SELECT a FROM Alumnos a 
WHERE a.nota_matematicas < 5

Por supueto, podemos realizar consultas complejas y combinadas, utilizando los operadores condicionales AND, OR, etc… En el siguiente ejemplo vemos los alumnos que hayan suspendido matemáticas y lengua.

SELECT a FROM Alumnos a 
WHERE a.nota_matematicas < 5 AND a.nota_lengua < 5

 

Otro ejemplo, en este caso de negación, vemos aquellos alumnos que hayan suspendido matemáticas pero no lengua.

SELECT a FROM Alumnos a 
WHERE a.nota_matematicas < 5 AND NOT (a.nota_lengua < 5)

Otro operador que se puede utilizar es “BETWEEN” que permite buscar por un rango. Por ejemplo, si queremos saber los alumnos que hayan sacado 9 o 10.
SELECT a FROM Alumnos a
WHERE a.nota BETWEEN 9 AND 10 

También es posible utilizar el operador LIKE que permite recuperar filas en columnas de tipo carácter. El siguiente ejemplo recupera todos los alumnos cuyo nombre comience por “AL”, por ejemplo Alberto o Alberto.
SELECT a FROM Alumnos a
WHERE a.nombre LIKE 'AL%' 

Se utilizan  comodines como “%” que sustituye un conjunto de caracteres o “_” que sustituye un solo carácter. De nuevo, el conocimiento de SQL es vital para poder sacarle partido a JPQL.

Existen otros operadores, funciones y componentes que se pueden consultar en el manual de referencia de JPQL.

Ordenar resultados. Cláusula Order by

La cláusula “Order by” permite realizar una ordenación de los datos devueltos. Con la cláusula ASC, lo hacemos de forma ascendente y con DESC de forma descendiente. 
SELECT a FROM Alumnos a 
ORDER BY a.nombre DESC 

Otro ejemplo, en este caso con una ordenación combinada.

SELECT a FROM Alumnos a 
ORDER BY a.nombre DESC, a.apellidos ASC 

Modificar objetos. UPDATE

Para modificar las instancias de objetos que se encuentren dentro de la tabla alumnos se usa la cláusula UPDATE. También es muy similar a la que se utiliza en el lenguaje SQL. 
UPDATE Alumnos  a 
SET a.nota_matematicas = 5 
WHERE a.cod_alumno = 1001 

En este caso modificamos la nota de matemáticas del alumno cuyo código es el 1001. Vemos que se puede utilizar la cláusula WHERE para acotar las filas modificadas, de lo contrario se cambiarían todos los objetos de la tabla.

Borrados de fila. DELETE

EL comando para borrar filas es DELETE. También se utiliza con la cláusula WHERE para acotar las filas que se deben borrar.
DELETE FROM Alumnos a 
WHERE a.alumno = 1001 

Ejecutar sentencias JQPL

Una vez que hemos visto como montar y crear sentencias JPQL llega el momento de lanzarlas. Dado que lo tenemos que hacer dentro de un  programa Java es necesario usar una  serie de métodos y pasos para poder hacerlo.

El lenguaje JPQL se integra implementado la interface “Query”. Esta implementación se obtiene a través de “EntityManager”. Se usan diversos métodos de factoría, entre los que destacan los siguientes:

  • createQuery(String jpql)
  • createNamedQuery(String name)
  • createNativeQuery(String sql)

Vamos a crer como crear un objeto “Query” y realizar una consulta a la base de datos. En este ejemplo ignoramos los métodos que no tienen que ver con JPQL propiamente dicho.
package es.cursojpa.cle; 

import java.util.List; 

import javax.persistence.EntityManager; 
import javax.persistence.EntityManagerFactory; 
import javax.persistence.EntityTransaction; 
import javax.persistence.Persistence; 
import javax.persistence.Query; 

public class Main { 

    public static void main(String[] args) { 
        EntityManagerFactory emf = Persistence 
                .createEntityManagerFactory("JPA_Factoria"); 
        EntityManager em = emf.createEntityManager(); 
         
        String jpql = "SELECT a FROM Alumnos a"; 

//Creamos un query a través del método createQuery

  Query query = em.createQuery(jpql); 

        List<Alumno> resultados = query.getResultList(); 

        for(Alumno a : resultados)

 { 
            //Comandos... 
        } 
         
        em.close(); 
        emf.close(); 
    } 
} 

Creamos un Query a través del método createQuery(String) del propio EntityManager. La sentencia JPQL se pasa en modo de cadena de texto.

Una vez obtenido el objeto Query podemos invocar al método retResultList() para recuperar mediante una lista todas las instancias de Alumno que se recuperen a través de la SELECT.

Después podemos realizar las operaciones sobre los datos que estimemos oportunas, ya desde comandos Java

Parámetro Dinámicos

Una de las características más potente de JPQL es la posibilidad de poner parámetros dinámicos, es decir pasar valores que pueden variar cada ve que se ejecuta la consulta.

Se realiza la asignación a través de la posición o del nombre del parámetro.

  • Para usar la sintaxis de tipo posición se usa “?posicion”. Por ejemplo “?1”
  • Para usar la notación por nombre se usa la sintaxis (:nombre).

Por ejemplo en el caso de pasar un parámetro dinámico por posición:
SELECT a FROM Alumnos a 
WHERE a.nombre = ?1 

En el caso de acceder por nombre 

SELECT a FROM Alumnos a 
WHERE a.nombre = :nombre 

Los valores de estos parámetros se pasan en el momento de ejecutar la consulta.  Usamos el método “setPArameter” para incluir un parámetro de forma dinámica en la consulta. Por ejemplo para pedir aquellos alumnos cuya nota en matemáticas sea superior a 5 y cuyo nombre comience por “AL” realizamos el siguiente código, en este caso pasando los valores por posición.
String jpql = "SELECT a FROM Alumnos a WHERE a.nota_matematicas > ?1 AND a.nombre like = ?2" 
Query query = em.createQuery(jpql); 
query.setParameter(1, 5); 
query.setParameter(2, "AL%"); 
List<Pelicula> resultados = query.getResultList(); 

 

Si el valor que pasamos como segundo argumento no se corresponde con el valor esperado (por ejemplo, una cadena de texto donde se espera un valor numérico), se dispara la excepción IllegalArgumentException. Esto también sucede si intentamos asignar  un valor a un parámetro dinámico que no existe.

En el caso de querer utilizar la nomenclatura por nombre usamos el siguiente formato:

 

String jpql = "SELECT a FROM Alumnos a WHERE a.nota_matematicas > :nota AND a.nombre like :nombre" 
Query query = em.createQuery(jpql); 
query.setParameter("nota", 5); 
query.setParameter("nombre", "AL%"); 
List<Pelicula> resultados = query.getResultList(); 

 

Consultas estáticas

Este tipo de consultas son un poco distintas a las anteriores, que son dinámicas. La diferencia básica es que una vez definidas no pueden ser modificadas, es decir se graban a fuego dentro del programa.

Por tanto solo se leen y cargan cuando el programa arranca, no cada vez que son ejecutadas. Al estar previamente “compiladas” son más eficientes que las dinámicas y disponen de un mejor rendimiento.

Estas consultas se definen mediante metadatos XML o anotaciones. Por ejemplo:
@Entity 
@NamedQuery(name="verAlumnos", query="SELECT a FROM Alumnos a") 
public class Alumno { ... } 

 

En este caso se usa la anotación  @NamedQuery para diseñar la consulta. La ponemos un nombre y una cadena con la sentencia JPQL que hay que ejecutar. El nombre que usemos para la consulta debe ser único en toda la unidad de persistencia. Como vemos la creamos en la Entity correspondiente, en este calso Alumno.

Una vez que hemos definido la consulta podemos utilizarla a través del objeto

Query query = em.createNamedQuery(Alumno.verAlumnos); 
List<Alumno> resultados = query.getResultList(); 

 

Consultas Nativas de SQL

Otra forma de usar comandos SQL es la de hacerlo de forma nativa, en vez de JPQL. Es decir, lanzamos un comando SQL contra la Base de Datos. De esta forma y en algunas ocasiones podemos aprovecharnos de alguna característica del motor de Base de Datos que estemos usando, por ejemplo Oracle y de esa forma mejorar el rendimiento.

Como efecto negativo, tenemos que un comando nativo en una Base de Datos puede no funcionar correctamente en otra y por tanto tenemos que ser cuidadosos con su uso.

Para realizar esta operación usamos le método “createNativeQuery”, lanzando la consulta como una cadena.

Por ejemplo:
String sql = "SELECT * FROM Alumnos"; 
Query query = em.createNativeQuery(sql); 
... 

También podemos definirlas de forma estática: 
@Entity 
@NamedNativeQuery(name=Alumno.ver_alumnos, query="SELECT * FROM alumnos") 
public class Alumno { 
} 

 

19
sep 2013
POSTED BY
POSTED IN Tic-tek
DISCUSSION 0 Comments
TAGS

, , , ,

HTML5: WebWorkers y WebSockets

Webworkers

Los WebWorkers nos permiten ejecutar procesos en paralelo sin impactar en el rendimiento del navegador.

Sin Web Workers por ejemplo, las tareas JavaScript pueden bloquear otros JavaScript de la página y por tanto el Navegador se puede colgar.

JavaScript es un entorno de subproceso único, es decir, que no se pueden ejecutar varias secuencias de comandos al mismo tiempo. Si tenemos que manipular eventos, manejar grandes cantidades de datos y manipular objetos DOM, no podemos hacerlo de forma simultánea debido a las limitaciones de JavaScript. La ejecución de comandos se realiza en un único subproceso.

Con Web Workers:

  • Podemos realizar procesos background
  • Podemos ejecutar procesos de forma paralela

Los Web Workers permiten realizar acciones con tiempos de ejecución muy largos para gestionar tareas pesadas en segundo plano, pero sin bloquear la interfaz de usuario.

Podemos usarlos para multitud de operaciones que en la actualidad consumirían recursos de navegación.

Tienen algunas limitaciones, ya que se ejecutan en una SANDBOX que no permite acceder a todos los recursos disponibles a los JavaScript normales.

  • No se puede acceder al objet window (window.document)
  • No hay acceso directo a la página WEB ni al DOM API
  • Se puede usar las funciones de timing
  • Tienen otras limitaciones de acceso.
  • Debemos comunicarnos con ellos a través de mensajes.

Para trabajar con WebWorkers, lo primero es comprobar que tenemos soporte para ellos.

Ejemplo

//Comprobar que nuestro navegador soporta WebWorkers.
if (typeof(Worker) !== "undefined") {
    document.getElementById("support").innerHTML =“ A tu navegador no le gustan los WebWorkers”;
}

Crear un WebWorker

Los Web Workers se ejecutan en un subproceso aislado. Por tanto, es necesario que el código que ejecutan se encuentre en un archivo independiente.

Sin embargo, antes de hacer esto, lo primero que hay que hacer es crear un nuevo objeto Worker en la página principal. El constructor debe tener el nombre de la secuencia de comandos del Worker.

Los pasos para crear un WebWorker son los siguientes:

  • Creamos un objeto WebWorker y le pasamos el fichero JavaScript a ejecutar. Si el archivo especificado existe, el navegador generará un nuevo subproceso que lo descargará de forma asíncrona. El Worker no empezará a trabajar hasta que el archivo se haya descargado al completo.
var worker = new Worker('fichero.js');

 

  • Lo arrancamos con el método PostMessage
worker.postMessage();

Trabajar con un WebWorker

El trabajo entre un Worker y su programa principal se hace mediante eventos. Se usa el método postMessage().

Este método hacepta normalmente una cadena de caracteres, aunque muchos  Navegadores modernos soportan la posibilidad de incluir in objeto JSON.

En el programa principal debemos activar un Listener que responda al evento “message” y que capture lo que pueda llegar desde el worker. Por ejemplo:

worker.addEventListener('message', f1(e) {
  console.log('Respuesta del Worker: ', e.data);
}, false);

 

Como vemos se puede acceder a los datos del evento a través del parámetro de la función f1. En este caso nos limitamos a sacarlo por el log.

Por otro lado, en el worker debemos incluir el Listener para que esté pendiente de recepcionar los mensajes que le llegan y responder a ellos. Por ejemplo algo como el siguiente código

self.addEventListener('message', f1_worker(e) {
  self.postMessage(e.data);
}, false);

 

Los mensajes que van del programa principal a los Workers y viceversa no son compartidos, en realidad se copias. Los objetos transferidos se serializan y des-serializan en cada fase del proceso.

Por lo tanto, el Worker no comparte la misma instancia que el programa principal, por lo que el resultado final es la creación de un duplicado en cada transferencia.

Para parar el woker usamos dos posibles opciones:

  • worker.terminate() desde la página principal
  • self.close()dentro del propio Worker.

El siguiente ejemplo muestra el ciclo de vida de una llamada a un  WebWorker desde un programa principal.

//Crear un nuevo worker
w1 = new Worker(“trabajo_worker.js"); 
//Mandar un mensaje al worker
w1.postMessage(“Empieza a currar hombre”); 
//Añadir un event listener
w1.addEventListener("message", messageHandler, true); 
//Procesar mensajes entrantes
function messageHandler(e) {
    // procesamos mensajes del worker
} 
//Gestión de errores
w1.addEventListener("error", errorHandler, true); 
//Parar el worker
w1.terminate();

 

 

El siguiente ejemplo muestra un programa principal que llama a un webworker que devuelve el dato que se le pasa en mayúsculas

Programa principal:

<script>
//Crear un nuevo worker
w1 = new Worker("trabajo_worker.js"); 
//Mandar un mensaje al worker
w1.postMessage("pedro"); 
//Añadir un event listener
w1.addEventListener("message", m1, true); 
//Procesar mensajes entrantes
function m1(e) {
    // procesamos mensajes del worker
    console.log('Ese nombre en mayúsculas es: ', e.data);
} 
//Gestión de errores
w1.addEventListener("error", errorHandler, true); 
//Parar el worker
w1.terminate();
</script>

 

El werworker sería el siguiente código:

self.addEventListener('message'       f1(e) {
self.postMessage(e.data.toUpperCase());
    }, false); 

 

Otros ejemplos de uso. Se puede invocar a un worker dentro de otro worker, es decir podemos tener subworkers. A la hora de utilizar los Subworkers es necesario tener en cuenta los siguientes aspectos:

  • Los Subworkers deben situados en el mismo origen que la página principal.
  • La resolución de las URI de los Subworkers está relacionada con la ubicación de su Worker principal.

 

//Trabajar  con elWorkerfunction messageHandler(e) {    postMessage(“mensaje del worker: ” + e.data);} addEventListener(“message”, messageHandler, true);//Podemos llamar a un worker dentro de otro workervar sub1 = new Worker(“subWorker.js”);

Gestión de errores

Al igual que cualquier programa JavaScript, es necesario gestionar los errores que se producen en los Web Workers.

Podemos hacerlo controlando el evento ErrorEvent. La interfaz incluye tres propiedades útiles para descubrir la causa del error:

  • Filename: el nombre del fichero  Worker que causó el error
  • Lineno: el número de línea donde se produjo el error
  • Message: descripción del error

A continuación, se muestra un ejemplo sobre cómo configurar un gestor de eventos onerror para controlar el error.

 <output id=”error” style=”color: red;”></output>

<output id=”result”></output>

<script>

function onError(e) {

document.getElementById(‘error’).textContent = [

'ERROR: Línea ', e.lineno, ' en ', e.filename, ': ', e.message].join(”);

}

function onMsg(e) {

document.getElementById(‘result’).textContent = e.data;

}

var worker = new Worker(‘workerError.js’);

worker.addEventListener(‘message’, onMsg, false);

worker.addEventListener(‘error’, onError, false);

worker.postMessage(); // Arrancar el worker sin un mensaje.

</script>

El worker asociado sería el siguiente:

self.addEventListener('message', function(e) {
  postMessage(1/x); };

 

El resultado sería aparecido al siguiente

 ERROR: Línea 2 en workerError.js: Uncaught ReferenceError: x is not defined

Websocket

Las aplicaciones actuales demandan una latencia cercana a 0. También necesitan comunicación bidireccional. En principio, la funcionalidad actual está basada en la arquitectura request/response de HTTP.

Por ejemplo, un cliente carga una página WEB y no sucede nada hasta que el usuario pulsa algo para pasar a la página siguiente. La incorporación de AJAX permitió disponer de páginas más dinámicas. De todas formas es necesario interactuar y cargar nuevos datos del servidor de forma periódica.

HTTP  es half-duplex, de forma que la información de Header se manda en cada petición y respuesta HTTP lo que produce una sobrecarga indeseada

Si observamos un request HTTP típico

GET /PollingStock//PollingStock HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/PollingStock/
Cookie: showInheritedConstant=false; showInheritedProtectedConstant=false; showInheritedProperty=false; showInheritedProtectedProperty=false; showInheritedMethod=false; showInheritedProtectedMethod=false; showInheritedEvent=false; showInheritedStyle=false; showInheritedEffect=false;

Y un response

HTTP/1.x 200 OK
X-Powered-By: Servlet/2.5
Server: Sun Java System Application Server 9.1_02
Content-Type: text/html;charset=UTF-8
Content-Length: 321
Date: Sat, 07 Nov 2009 00:32:46 GMT

El Overhead innecesario en este ejemplo alcanza 871 bytes. Puede ser mayor y lo peor es que no escala.

WebSocket define una API para establecer conexiones de tipo “socket” entre un navegador y el servidor. Por tanto existe una conexión persistente entre el cliente y el servidor y ambas partes pueden enviar datos en cualquier momento.

Algunos ejemplos de su uso pueden ser las siguientes:

  • Aplicaciones financieras
  • Sociales
  • Juegos online
  • Otras

 

El websocket tiene las siguientes características

  • Protocolos W3C API y IETF Protocol
  • Full-duplex, single socket
  • Comunican las páginas con un Servidor remoto
  • Atraviesa firewalls, proxies, y routers
  • Comparte el puerto con el HTTP
  • Reduce de forma drástica el overhead

La conexión se establece a través del upgrade del protocolo HTTP al protocolo WebSocket usando la misma conexión

Una vez actualizado, los data frames de  WebSocket se pueden enviar de un lado a otro entre el cliente y el servidor en modo full-duplex.

Las Frames se pueden enviar en modo full-duplex en cualquier dirección y en cualquier momento.

Creación de un websocket

Como siempre, lo primero que debemos averiguar es si disponemos de soporte para WebSocket

//Checking for browser support
if (window.WebSocket) {
    document.getElementById("support").innerHTML =
     "HTML5 WebSocket is supported";
  } else {
     document.getElementById("support").innerHTML =
      "HTML5 WebSocket is not supported";
  }

Se puede crear una conexión Websocket llamando al constructor correspondiente:

var con1 = new WebSocket('ws://ejemplo.curso.com', ['soap']);

Se usa el esquema “ws” para conexiones de este tipo. También podemos observar los subprotocolos que se han asignado a la conexión que debe ser uno de los registrados y permitidos por el estándar. Ahora mismo solo se soporta “soap”.

Podemos usar distintos eventos para controlar la gestión de la conexión:

  • Onopen: cuando se establece la conexión
  • Onerror: cuando se produce un error
  • Onmessage: cuando se recibe un mensaje del servidor

Algunos ejemplos:

Con1.onerror = f1(error) {
  console.log('Se ha producido el error:' + error);
}; 
Con1.onmessage = f1 (e) {
  console.log('Mensaje del servidor: ' + e.data);
};

 

Trabajar con WEBSOCKET

Una vez establecida la conexión con el servidor, podemos enviar un mensaje mediante el método send. Tiene el siguiente formato:

conexion.send('your message');

Aunque por ahora solo se soportan cadenas, algunos navegadores están empezando a trabajar con objetos lo que permite una mayor versatilidad.

En el siguiente ejemplo vemos como mandar un mensaje cuando hemos establecido la conexión:

Con1.onopen = f1 () {
  Con1.send('Esto es una prueba'); // Mandar el mensaje
};

Por supuesto, el servidor puede también mandar mensajes. Para recibirlos habilitamos el método callbak “onmessage” como hemos visto en el punto anterior. Este método recibe un objeto de tipo evento con los datos asociados.

Un ejemplo completo de gestión de websocket

//Crear WebSocket
var sock1 = new WebSocket("ws://www.websocket.org”); 
// Asociar un Listener
Sock1.onopen = function(evt) {
    alert("Conexión abierta…”);
}; 
//Capturar mensajes del ervisor
Sock1.onmessage = function(evt) {
    alert(“Received message: “ + evt.data);
}; 
//Al cerrar la conexión
Sock1.onclose = function(evt) {
    alert(“Conexión cerrada…”);
}; 
// Mandar datos
Sock1.send(“Saludos!”); 
//Cerramos el WebSocket
Sock1.close();

 

 

 

 

 

 

 

18
jun 2013
POSTED BY
POSTED IN Tic-tek
DISCUSSION 0 Comments

Oracle11g. Identificación de SQL Cargado

Identificar el SQL Cargado es el primer paso en el proceso de ajuste de SQL. En este capítulo se verán las distintas herramientas disponibles para identificarlo con:

  • ADDM
  • Top SQL
  • Dynamic performance views
  • Statspack

JEE. Mensajería JMS

Introducción JMS

En JEE el concepto de mensajería se refiere a la comunicación con poco acoplamiento entre emisor y receptor y totalmente asíncrona. Se podría definir su comportamiento como buzón de voz, donde un emisor deja un mensaje para que un receptor lo recoja cuando pueda. En terminología JEE tenemos un producer (emisor) que almacena un mensaje en un destino, un almacén específico. Posteriormente un consumer (receptor) comprueba si hay algún mensaje para él en el destino.
Leer más…

Aplicaciones OLAP. Bases de Datos Dimensionales

Introducción a los cubos

Las herramientas OLAP (onLine Analitical Processing) tienen como objetivo fundamental soportar las consultas “ad-hoc” de los usuarios que analizan el negocio. Por lo general estos usuarios están familiarizados con el uso de las hojas de cálculo, las herramientas OLAP, básicamente realizan las mismas operaciones que podríamos realizar con una hoja de cálculo pero además ofrecen:

Administración avanzada de red en Linux. Filtrado de tráfico con Iptables

El Kernel de Linux, a través de Netfilter y las heramientas iptables, es capaz de implementar potentes firewalls hasta nivel 4 de red.

La configuración de un firewall a través de la herramienta iptables puede hacerse de 2 maneras diferentes:

  • Mediante un script de comandos iptables.
  • Mediante la carga y volcado de reglas iptables en memoria a través de los comandos iptables-save e iptables-restore.

Leer más…

Hibernate: Recuperación de objetos. Fetch y Lazy

Hibernate recupera la información de la base de datos de una forma peculiar.

Existen dos conceptos importantes que debemos controlar cuando se trabaja con Hibernate:

  • Cuándo decide Hibernate recuperar la información de la base de datos y cargarla en memoria.
  • De qué forma se trae la información de la base de datos, es decir, qué sentencias SQL utiliza para recuperar la información.

Leer más…

ALFRESCO: El modelo de contenidos

Diseño y desarrollo de los cimientos de un proyecto de gestión de contenidos

Alfresco incorpora un metamodelo en su estructura, es decir, la capacidad para que nosotros declaremos nuevos modelos de contenido.

Un modelo de contenido define la estructura de información acompañará a nuestros documentos digitales.

Dotar de semántica al documento para que posteriormente se puedan implementar búsquedas y procesos más eficientes e “inteligentes”.
Leer más…

HTML5. La etiqueta video

Hasta ahora, no existía un estándar para visualizar una película de vídeo en una página web. Hoy, la mayoría de vídeos se muestran a través de un plug-in del estilo de flash.

HTML5 define un nuevo elemento que especifica una forma estándar para incrustar una vídeo o película en una página web: <video>.

Los navegadores que soportan este elemento a día de hoy son Internet Explorer 9, Firefox, Opera, Chrome, y Safari.
Leer más…

Duplicar una base de datos utilizando RMAN

Introducción

Se puede utilizar RMAN para duplicar una base de datos con el comando DUPLICATE a partir de los backups de la base de datos original manteniendo la base de datos original intacta. La base de datos duplicada (con nuevo DBID) será idéntica a la base de datos target o podrá contener solo una parte de la misma. Por otra parte, la base de datos target y la duplicada pueden estar en el mismo servidor o en servidores diferentes.

Leer más…