“Múltiples inquilinos”. La nueva arquitectura de Oracle12c.


¿Qué significa la “c” en Oracle 12c?

Tras el éxito de la anterior base de datos, Oracle11g (“g” identifica grid computing ‑red/rejilla), la versión más reciente de base de datos de Oracle (sobre la versa esta documentación) es Oracle12c, “c” representa cloud computing. Pero ¿qué significan estas denominaciones?

Grid Computing

El término grid computing se refiere a una infraestructura que permite la integración y el uso colectivo de ordenadores de alto rendimiento, redes y bases de datos que son propiedad y están administrados por diferentes instituciones.

Universidades, laboratorios de investigación o empresas se asocian para formar un grid para lo cual utilizan algún tipo de software que implemente este concepto.

La computación en grid ofrece muchas ventajas frente a otras tecnologías alternativas. La potencia que ofrecen multitud de ordenadores conectados en red usando grid es prácticamente ilimitada, además de que ofrece una perfecta integración de sistemas y dispositivos heterogéneos, por lo que las conexiones entre las diferentes máquinas no generarán ningún problema.

Se trata de una solución altamente escalable, potente y flexible, ya que evitarán problemas de falta de recursos (cuellos de botella) y nunca queda obsoleta, debido a la posibilidad de modificar el número y características de sus componentes.



 Cloud Computing

Cloud computing (computación en la nube) es una arquitectura donde los servicios (tales como bases de datos, aplicaciones, entornos de desarrollo, o incluso la infraestructura de servidores) están disponibles través de la red Internet para el uso por parte de los usuarios.

En este tipo de tecnología todo lo que permite un sistema informático se ofrece como servicio, de modo que los usuarios puedan acceder a los servicios disponibles “en la nube de Internet” sin conocimientos (o, al menos sin ser expertos) en la gestión de los recursos que usan.

Es un paradigma en el que la información se almacena de manera permanente en servidores de Internet y se envía a cachés temporales de cliente, lo que incluye equipos de escritorio, portátiles, tablets, etc.

Es un nuevo modelo de prestación de servicios de negocio y tecnología, que permite al usuario acceder a un catálogo de servicios estandarizados y responder con ellos a las necesidades de su negocio, de forma flexible y adaptativa, en caso de demandas no previsibles o de picos de trabajo, pagando únicamente por el consumo efectuado, o incluso gratuitamente en caso de proveedores que se financian mediante publicidad o de organizaciones sin ánimo de lucro.

El cambio que ofrece cloud computing es que permite aumentar el número de servicios basados en la red. Esto genera beneficios tanto para los proveedores, que pueden ofrecer, de forma más rápida y eficiente, un mayor número de servicios, como para los usuarios que tienen la posibilidad de acceder a ellos, disfrutando de la “transparencia” e inmediatez del sistema y de un modelo de pago por consumo. Así mismo, el consumidor ahorra los costes en inversión económica para infraestructuras (locales, material especializado, etc).

Oracle12c está diseñado para ejecutarse en la nube y que sea accesible como un servicio. A través de la virtualización y de la arquitectura multi-tenant, cada aplicación de base de datos se presenta como una base de datos privada, pero en realidad, el sistema es un entorno compartido de base de datos. El uso de los recursos compartidos y la virtualización es un método utilizado por las empresas y los proveedores de bases de datos para reducir costes.

Sin embargo, no hay ningún requisito obligatorio para que Oracle12c deba ejecutarse en la nube, puede ejecutarse perfectamente como en versiones anteriores de Oracle sin necesidad de utilizar esta tecnología.

Cloud computing

Oracle Multitenant

En la nueva versión del gestor de base de datos Oracle Database 12c han sido incorporadas más de 500 nuevas características, sin embargo el icono principal de la versión radica en la nueva arquitectura denominada Oracle Multitenant.

Oracle Multitenant es la nueva opción para Oracle12c Enterprise Edition, la cual ayuda a los clientes a reducir costes a través de la simplificación, aprovisionamiento, consolidación y actualización de la base de datos.

La nueva arquitectura está fundamentada en una base de datos contenedora Container Database (CDB) la cual puede albergar otras muchas bases de datos más pequeñas denominadas Pluggable Databases (PDB).

La base de datos contenedora (Container) actúa como una instancia de base de datos raíz y cada una de las Pluggable Databases funciona dentro de ese único contenedor como inquilinos. Cuando un CDB contenga varios PDB estamos ante una arquitectura multi‑tenancy  (cada uno de los contenedores contiene múltiples inquilinos).

Cada PDB contiene sólo los esquemas de bases de datos, tablas, índices y un mini diccionario de datos para seguir siendo autónomo dentro del soporte más amplio del contenedor CDB.

CDB Multi-Tenant

Esta arquitectura es escalable y aplicable de forma total a soluciones ya conocidas como RAC (Oracle Real Application Clusters) y Oracle Data Guard. Una base de datos no Pluggable Database o también llamada Non-CDB (Non Container Database) puede ser convertida fácilmente a una Pluggable Database sin afectar a su contenido, operación y manejo para las aplicaciones relacionadas con la misma.

Los principales beneficios de la arquitectura Oracle Multitenant pueden ser resumidos en cuatro grandes factores:

  • Alta posibilidad de consolidación: las distintas PDB (Pluggable Databases) poseen como base de operación la misma base de de datos contenedora CBD (Container Database) compartiendo la instancia (memoria y procesos background), esto conlleva una gran ventaja, cada PDB no tiene su propia SGA, solo existirá solo una memoria SGA para todas las bases de datos.

En esta nueva arquitectura existe la posibilidad de trabajar con más bases de datos en un mismo servidor o servidores respecto a las versiones anteriores. Esta técnica permite obtener un beneficio similar a la llamada concepción de consolidación de esquemas (schemas), pero son bien conocidas las barreras, dificultades e implicaciones al aplicar esta última consolidación en temas de seguridad.

  • Rápido aprovisionamiento y clonación utilizando sentencias SQL, una PDB puede ser desconectada de un CBD y ser conectada a otro. Alternativamente se puede duplicar una Pluggable Database en el mismo Container o clonar la misma de un CDB a otro CDB, estas operaciones pueden ser llevadas a cabo a en tan solo unos pocos minutos.

Aprovisionamiento y clonación

  • Nuevos paradigmas para un rápido parcheado (patching) o actualización (upgrade): la inversión de tiempo y esfuerzo para aplicar un patch en una CBD conlleva el resultado de aplicar el mismo parche a todas las PDB, si se desea aplicar el patch o upgrade solo un número limitado de Pluggable Databases el procedimiento es crear otro Database Containter, desconectar las PDBs del anterior CDB, incorporar las mismas al nuevo CDB y allí realizar el trabajo particular de parcheado o actualización en este nuevo Container.
  • Manejar varias bases de datos como una sola: consolidando las bases de datos existentes como Pluggable Databases, los administradores podrán manejar varias PDBs como si fueran una sola. Por ejemplo, las tareas de copia de seguridad y recuperación son llevadas a cabo desde del CBD, toda la administración podrá ser llevada a cabo de forma centralizada.
  • Gestión dinámica de los recursos entre Pluggable Databases: Oracle12c Resource Manager tiene funciones extendidas para controlar el consumo de recursos entre los distintos CDBs y PDBs.

 

Ventajas de Oracle Multitenant

Es común en tiempos actuales encontrar en las empresas bases de datos distribuidas a lo largo de varios servidores. Los costes asociados al mantenimiento, licencias y repetición de tareas en cada una de ellas, hacen que el área TIC estuviese en constante búsqueda de mecanismos para optimizar tareas evitando realizar varias veces la misma o que se pensase disminuir costes reduciendo la cantidad de servidores.

Oracle Multitenant es la respuesta a estas necesidades. Esto podría verse reflejado en las siguientes áreas:

  • Memoria: reducción de memoria global requerida por cada instancia de base de datos al consolidar la SGA de todas las instancias en una sola y poseer solo un conjunto de background processes en lugar de varios, uno por cada instancia.
  • Aprovisionamiento de bases de datos: para duplicar/clonar una base de datos por lo general se utilizan técnicas que requieren gran cantidad de tiempo, tales como: comando Duplicate de RMAN, operaciones de Restore/Recover, Cold Backups, utilidades Export/Import. Estas posibilidades requieren primeramente la creación de los archivos principales de una base de datos los cuales suelen ser realizados a través del DBCA (Database Configuration Assistant) o de forma manual. Oracle Multitenant posee la capacidad de crear y/o duplicar una base de datos con solo un comando.
  • Parcheo (patching): de forma convencional las tareas de parcheo deben de ser ejecutadas en cada base de datos, lo cual dificulta el proceso cuando se dispone de gran cantidad. Oracle Multitenant posee una arquitectura interna en la cual los metadatos de todas las Pluggable Databases se encuentran en la CDB contenedora. En este área se encuentra el diccionario de datos y estructura base de cada una de las base de datos. Entonces, esta zona es clave para hacer cambios en el diccionario de datos (upgrades) o de los binarios de Oracle afectados por patchings, de esta manera al realizar cualquier actualización del CBD el efecto se verá también reflejado en todas las Pluggable Databases conectadas con el correspondiente Container.
  • Upgrade: la tarea de upgrade/migración de una base de datos consiste en actualizar el catalogo/diccionario de la misma y por consiguiente el compilado de todos los objetos de los usuarios de la base de datos (procedimientos, vistas, funciones, …) que pudiesen haberse afectados en su validez a causa de invalidez temporales de otros objetos dependientes ( Catalogo de la BBDD ), para el caso de “Upgrades”, los objetos dependientes son aquellos pertenecientes al catalogo de la BBDD.

Hasta versiones previas a Oracle12c el realizar el upgrade/downgrade de una base de datos requería una ardua labor realizada en varias etapas, duplicar la base de datos original para realizar Manual Rolling Upgrade, uso del DBUA (Database Upgrade Assistant) y otras más.

Una de las tantas inquietudes de muchos clientes siempre ha radicado en si existe un método para realizar downgrades rápidos en caso de posibles problemas con la nueva versión implementada o como poder deshacer un patch de la manera más rápida posible en caso de problemas con el mismo sin tener que realizar operaciones de riesgo o sin tener que asegurar el estado anterior de los binarios a través de un backup de los binarios del gestor.

Todo el proceso de reversión radica en los cambios realizados en el núcleo (core) de la base de datos (catalogo de la base de datos y binarios), si ahora el centro de la base de datos son los CDBs y existe la posibilidad de poseer varias versiones de Containers entonces la arquitectura Oracle Multitenant hace posible que nuestro core sea tan dinámico y flexible para las bases de datos. Solo basta con desconectar una base de datos de un Container para conectarla a otro y así poder acceder a una Pluggable Database en versiones y/o patchs diversos casi de manera inmediata.

  • Backups y Recover: la gestión de copias de seguridad y recuperaciones hasta versiones anteriores a Oracle12c se tenía que realizar de forma local obligatoriamente en cada base de datos, con Oracle Multitenant la gestión se lleva a cabo desde el CDB correspondiente.

 

 Características de Oracle Multitenant

  • División del diccionario de datos: Cada PDB tendrá su propio diccionario de datos con la información de los metadatos y la CDB la información general del espacio denominado CDB$ROOT (Diccionario de los metadatos de la base de datos contenedora).
  • En arquitectura Multitenant el diccionario de datos esta virtualizado.
  • En Oracle 12.1 puede haber un máximo de 252 bases de datos por Container.
  • Después de un upgrade las nuevas bases de datos 12c pueden ser Pluggable Databases o Non-Pluggable Databases.
  • Total reconocimiento entre bases de datos Pluggable Databases y Non-Pluggable Databases, el funcionamiento para las aplicaciones es exactamente igual en ambas.
  • La conexión/desconexión (plug/unplug) de las PDBs de/a las CDBs se realiza internamente mediante una combinación de la operación de Transportable Tablespaces en conjunto con una 3ra generación de Data Pump.

El proceso unplug/plug se podrá realizar entre sistemas operativos de diferentes endian formats.

  • Las conexiones Oracle NET hacia las PDBs siguen siendo iguales.
  • Las herramientas SQL Developer y Enterprise Manager han sido ampliadas para poder manejar todo lo relacionado con la arquitectura Multitenant.
  • Las operaciones de Oracle Active Data Guard son realizadas a nivel de CDBs.
  • La desconexión y conexión a distintos CDBs puede ser llevada a cabo entre Containers de diversas versiones.
  • La nueva arquitectura Multitenant está disponible en las versiones Standard, Standard Edition One y Enterprise Edition del servidor de base de datos. Sin la licencia de opción Multitenant se tendrá derecho a solo una PDB.

 

Arquitectura física de un CDB

Desde el punto de vista físico, un CDB tiene básicamente la misma estructura que un Non‑CDB, a excepción de que cada PDB tiene su propio conjunto de espacios de tabla (incluyendo sus propios tablespaces SYSTEM y SYSAUX) y archivos de datos.

La siguiente figura muestra la arquitectura de almacenamiento física de un CDB con dos PDBs: pdb1 y pdb2.

14
feb 2014
POSTED BY
POSTED IN Sin categoría
DISCUSSION 0 Comments
TAGS

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…