Este documento discute cómo mejorar el rendimiento y reducir el uso de memoria al mostrar grandes cantidades de datos en una JTable. Propone usar un ArrayList en lugar de un Vector para almacenar los datos, y usar cursores desplazables con JDBC para obtener los datos de una base de datos bajo demanda en lugar de cargarlos todos en memoria.
Este documento explica los conceptos básicos de multitarea e hilos en Java. La multitarea permite ejecutar varios procesos de forma concurrente para mejorar el rendimiento. En Java, los hilos se implementan utilizando la clase Thread o la interfaz Runnable. El documento incluye un ejemplo de cajeras procesando compras de clientes de forma secuencial y paralela usando hilos.
El documento explica los conceptos de multitarea e hilos. La multitarea permite que el usuario no quede bloqueado mientras se ejecutan tareas pesadas en segundo plano. Los hilos son trozos de código que pueden ejecutarse simultáneamente, lo que mejora el rendimiento. Se ilustra cómo un hilo principal y otro secundario pueden descargar imágenes de forma concurrente, ofreciendo una mejor experiencia de usuario.
Cursos gratis de programación en Java. Metodos. Orientado a Grado, DAM y DAW. Otros cursos disponibles para Android, Swift, Base de datos, javascript, servicios y procesos...
Este documento resume el API JDBC y el mapeo de objetos de bases de datos a clases Java. Brevemente describe los tipos de controladores JDBC, el uso de bloques try-catch para manejar excepciones, y cómo crear clases que representen las tablas de una base de datos, con atributos y métodos para acceder a los datos.
El documento describe los contenidos de un curso sobre JDBC y URM. Incluye secciones sobre JDBC, operaciones con JDBC como cargar drivers, conectarse a una base de datos, enviar órdenes SQL, sentencias preparadas, procedimientos almacenados, transacciones y optimizaciones. También cubre temas de aplicaciones web como JSP, Servlets y el patrón DAO.
Este documento trata sobre excepciones en Java. Explica los dos tipos de excepciones en Java (excepciones comprobadas y no comprobadas), y los mecanismos para controlar excepciones mediante try-catch y throws. También cubre la creación de excepciones personalizadas heredando de la clase Exception.
Este documento resume las clases y objetos en Java. Define una clase como una plantilla para objetos que establece su estructura y comportamiento. Las clases contienen atributos y métodos. Los objetos son instancias de clases que se crean en tiempo de ejecución.
Este documento explica los conceptos básicos de multitarea e hilos en Java. La multitarea permite ejecutar varios procesos de forma concurrente para mejorar el rendimiento. En Java, los hilos se implementan utilizando la clase Thread o la interfaz Runnable. El documento incluye un ejemplo de cajeras procesando compras de clientes de forma secuencial y paralela usando hilos.
El documento explica los conceptos de multitarea e hilos. La multitarea permite que el usuario no quede bloqueado mientras se ejecutan tareas pesadas en segundo plano. Los hilos son trozos de código que pueden ejecutarse simultáneamente, lo que mejora el rendimiento. Se ilustra cómo un hilo principal y otro secundario pueden descargar imágenes de forma concurrente, ofreciendo una mejor experiencia de usuario.
Cursos gratis de programación en Java. Metodos. Orientado a Grado, DAM y DAW. Otros cursos disponibles para Android, Swift, Base de datos, javascript, servicios y procesos...
Este documento resume el API JDBC y el mapeo de objetos de bases de datos a clases Java. Brevemente describe los tipos de controladores JDBC, el uso de bloques try-catch para manejar excepciones, y cómo crear clases que representen las tablas de una base de datos, con atributos y métodos para acceder a los datos.
El documento describe los contenidos de un curso sobre JDBC y URM. Incluye secciones sobre JDBC, operaciones con JDBC como cargar drivers, conectarse a una base de datos, enviar órdenes SQL, sentencias preparadas, procedimientos almacenados, transacciones y optimizaciones. También cubre temas de aplicaciones web como JSP, Servlets y el patrón DAO.
Este documento trata sobre excepciones en Java. Explica los dos tipos de excepciones en Java (excepciones comprobadas y no comprobadas), y los mecanismos para controlar excepciones mediante try-catch y throws. También cubre la creación de excepciones personalizadas heredando de la clase Exception.
Este documento resume las clases y objetos en Java. Define una clase como una plantilla para objetos que establece su estructura y comportamiento. Las clases contienen atributos y métodos. Los objetos son instancias de clases que se crean en tiempo de ejecución.
El documento presenta una serie de boletines de ejercicios de programación en Java que abordan temas como variables, condicionales, bucles, tablas y funciones. Cada boletín contiene varios ejercicios resueltos de manera didáctica sobre un tema concreto para ayudar al aprendizaje de la programación a través de la práctica.
El documento lista 40 comandos y métodos de Java para el desarrollo de interfaces gráficas, manejo de datos, excepciones y depuración. Incluye comandos para crear y personalizar ventanas, botones, mensajes, ingreso de datos, manipulación de cadenas y fechas, y uso de clases como Scanner, Date y JOptionPane. También cubre temas como paquetes, comentarios Javadoc, depuración y manejo de excepciones.
Todo lo que un desarrollador no puede desconocer de javascript tutorial j q...Marcelino Ortiz
El documento proporciona una introducción a conceptos fundamentales y avanzados de JavaScript. Explica que JavaScript es un lenguaje funcional orientado a objetos con herencia de prototipos, y no clases como otros lenguajes. También describe cómo crear variables, funciones, objetos y herencia en JavaScript, así como el ámbito de las variables y el uso de "this". El objetivo es que los desarrolladores conozcan estos conceptos básicos pero también avanzados de JavaScript.
Este documento presenta conceptos fundamentales de programación en Java como lectura de datos, sentencias condicionales, bucles, matrices y un laboratorio de problemas propuestos. Cubre temas como la importación de paquetes, uso de println() y Scanner para entrada, sentencias if, switch y bucles while, do-while y for. También explica el uso de matrices, como acceder a valores, determinar longitud y ordenar matrices.
1. El documento introduce los conceptos de pruebas de aceptación y la importancia de probar programas antes de entregarlos o aceptarlos. 2. Se describe a JUnit, un paquete Java para automatizar pruebas de clases. JUnit permite crear clases de prueba con métodos que comiencen por "test" para ejecutar casos de prueba. 3. Se explican funciones como assertEquals para comparar resultados esperados vs. obtenidos.
Este documento describe los modelos de dos y tres capas para el acceso a datos, así como la configuración de conexión a una base de datos con NetBeans utilizando JDBC. Explica los pasos para incluir la librería JDBC, establecer la conexión, realizar consultas y cerrar la conexión. También define JDBC, sus tipos y aplicaciones, y provee ejemplos de código para insertar datos en una base de datos.
Este documento explica los fundamentos de las conexiones a bases de datos desde aplicaciones Java usando JDBC. Introduce los conceptos de drivers JDBC, el objeto DriverManager, y las diferentes arquitecturas de aplicaciones de dos y n-capas. Explica los cuatro tipos de drivers JDBC y cómo registrarlos y obtener conexiones usando URLs JDBC.
Este documento proporciona una introducción a cómo manejar conexiones a bases de datos con JDBC 3.0. Explica los conceptos básicos detrás de la arquitectura de una aplicación Java que se conecta a una base de datos, incluidos los modelos de dos y n-capas. Luego describe los fundamentos de los drivers JDBC, incluidos los cuatro tipos de drivers y cómo registrar un driver con el DriverManager. Finalmente, proporciona una descripción general de los temas cubiertos en el resto del tutorial.
Actualización 2020 con un enfoque más práctico con Java y MySQL sobre Linux. Diferencias entre la POO y la programación estructurada. Abordaje de temas fundamentales de Java para el desarrollo de aplicaciones. Paquete Java Swing. Formularios y Menus. Diferentes Vistas: Aplicación, Negocio y Datos.
Este documento presenta una introducción al acceso y manipulación de bases de datos MySQL. Explica cómo crear una base de datos y tabla en MySQL y luego conectarse a ella desde Java para realizar operaciones básicas de lectura y escritura. También describe clases en Java para establecer la conexión y métodos para insertar, actualizar y consultar datos.
1. Java con Base de Datos en un tema muy importante, porque abarca conocimientos generales para el desarrollo de Software, es decir en el caso de conocer poco Java, las explicaciones del texto le permitirán comprender los conceptos que se tratan, especialmente si procede de otro lenguaje como C o C++.
Este documento describe el uso de objetos TDatabase en Delphi para administrar conexiones a bases de datos. Explica que estos objetos pueden ser creados explícitamente por el desarrollador o implícitamente por Delphi, y controlan las tablas y consultas activas. También cubre cómo estos objetos permiten modificar parámetros de conexión y controlar transacciones. Finalmente, presenta ejemplos de cómo utilizar alias locales para cambiar dinámicamente la base de datos conectada o interceptar eventos de conexión.
Este documento describe cómo conectar aplicaciones Java a bases de datos utilizando JDBC. Explica los tipos de drivers JDBC, el proceso de consulta a una base de datos con JDBC, incluyendo la creación de sentencias SQL y el uso de objetos como Statement y ResultSet. También define los objetos clave de JDBC como DriverManager, Connection, Statement y ResultSet que permiten la comunicación entre Java y las bases de datos.
Este documento describe el procesamiento de páginas JSP y elementos como directivas, etiquetas e inclusiones. Explica que las páginas JSP combinan código HTML con etiquetas Java para programar scripts de servidor, y que estas páginas son traducidas a servlets de Java antes de su ejecución. También cubre la creación de acciones JSP personalizadas.
El documento habla sobre el soporte de Spring JDBC para simplificar el acceso a datos usando JDBC. Explica cómo Spring reduce la cantidad de código necesario al acceder a una base de datos relacional en comparación con el uso tradicional de JDBC, cubriendo temas como la conexión a la base de datos, recuperación y mapeo de datos, e inserción, actualización y eliminación de datos. También introduce un modelo de datos simple de ejemplo que se usará para ilustrar los conceptos a lo largo del capítulo.
El documento describe cómo conectar una base de datos MySQL a una aplicación Java. Se explica la creación de una clase ConexionDB que establece la conexión y devuelve un objeto Connection. También se muestra el código de una clase Main que llama al método GetConnection de ConexionDB para comprobar que la conexión se realiza correctamente. Finalmente, se detallan los pasos para probar la conexión en NetBeans.
Este documento presenta información sobre el uso de JDBC para conectar aplicaciones Java a bases de datos. Explica que JDBC permite establecer conexiones con bases de datos, enviar instrucciones SQL y procesar los resultados. Además, provee ejemplos de cómo realizar operaciones básicas como consultas, inserciones, actualizaciones y eliminaciones usando JDBC. Finalmente, hace recomendaciones sobre el diseño de aplicaciones que se conectan a bases de datos a través de JDBC.
Este documento presenta información sobre el uso de JDBC para conectar aplicaciones Java a bases de datos. Explica que JDBC permite establecer conexiones con bases de datos, enviar instrucciones SQL y procesar los resultados. Además, provee ejemplos de cómo realizar operaciones básicas como consultas, inserciones, actualizaciones y eliminaciones usando JDBC. Finalmente, da algunas recomendaciones sobre el diseño de aplicaciones que usen esta tecnología.
El documento presenta una serie de boletines de ejercicios de programación en Java que abordan temas como variables, condicionales, bucles, tablas y funciones. Cada boletín contiene varios ejercicios resueltos de manera didáctica sobre un tema concreto para ayudar al aprendizaje de la programación a través de la práctica.
El documento lista 40 comandos y métodos de Java para el desarrollo de interfaces gráficas, manejo de datos, excepciones y depuración. Incluye comandos para crear y personalizar ventanas, botones, mensajes, ingreso de datos, manipulación de cadenas y fechas, y uso de clases como Scanner, Date y JOptionPane. También cubre temas como paquetes, comentarios Javadoc, depuración y manejo de excepciones.
Todo lo que un desarrollador no puede desconocer de javascript tutorial j q...Marcelino Ortiz
El documento proporciona una introducción a conceptos fundamentales y avanzados de JavaScript. Explica que JavaScript es un lenguaje funcional orientado a objetos con herencia de prototipos, y no clases como otros lenguajes. También describe cómo crear variables, funciones, objetos y herencia en JavaScript, así como el ámbito de las variables y el uso de "this". El objetivo es que los desarrolladores conozcan estos conceptos básicos pero también avanzados de JavaScript.
Este documento presenta conceptos fundamentales de programación en Java como lectura de datos, sentencias condicionales, bucles, matrices y un laboratorio de problemas propuestos. Cubre temas como la importación de paquetes, uso de println() y Scanner para entrada, sentencias if, switch y bucles while, do-while y for. También explica el uso de matrices, como acceder a valores, determinar longitud y ordenar matrices.
1. El documento introduce los conceptos de pruebas de aceptación y la importancia de probar programas antes de entregarlos o aceptarlos. 2. Se describe a JUnit, un paquete Java para automatizar pruebas de clases. JUnit permite crear clases de prueba con métodos que comiencen por "test" para ejecutar casos de prueba. 3. Se explican funciones como assertEquals para comparar resultados esperados vs. obtenidos.
Este documento describe los modelos de dos y tres capas para el acceso a datos, así como la configuración de conexión a una base de datos con NetBeans utilizando JDBC. Explica los pasos para incluir la librería JDBC, establecer la conexión, realizar consultas y cerrar la conexión. También define JDBC, sus tipos y aplicaciones, y provee ejemplos de código para insertar datos en una base de datos.
Este documento explica los fundamentos de las conexiones a bases de datos desde aplicaciones Java usando JDBC. Introduce los conceptos de drivers JDBC, el objeto DriverManager, y las diferentes arquitecturas de aplicaciones de dos y n-capas. Explica los cuatro tipos de drivers JDBC y cómo registrarlos y obtener conexiones usando URLs JDBC.
Este documento proporciona una introducción a cómo manejar conexiones a bases de datos con JDBC 3.0. Explica los conceptos básicos detrás de la arquitectura de una aplicación Java que se conecta a una base de datos, incluidos los modelos de dos y n-capas. Luego describe los fundamentos de los drivers JDBC, incluidos los cuatro tipos de drivers y cómo registrar un driver con el DriverManager. Finalmente, proporciona una descripción general de los temas cubiertos en el resto del tutorial.
Actualización 2020 con un enfoque más práctico con Java y MySQL sobre Linux. Diferencias entre la POO y la programación estructurada. Abordaje de temas fundamentales de Java para el desarrollo de aplicaciones. Paquete Java Swing. Formularios y Menus. Diferentes Vistas: Aplicación, Negocio y Datos.
Este documento presenta una introducción al acceso y manipulación de bases de datos MySQL. Explica cómo crear una base de datos y tabla en MySQL y luego conectarse a ella desde Java para realizar operaciones básicas de lectura y escritura. También describe clases en Java para establecer la conexión y métodos para insertar, actualizar y consultar datos.
1. Java con Base de Datos en un tema muy importante, porque abarca conocimientos generales para el desarrollo de Software, es decir en el caso de conocer poco Java, las explicaciones del texto le permitirán comprender los conceptos que se tratan, especialmente si procede de otro lenguaje como C o C++.
Este documento describe el uso de objetos TDatabase en Delphi para administrar conexiones a bases de datos. Explica que estos objetos pueden ser creados explícitamente por el desarrollador o implícitamente por Delphi, y controlan las tablas y consultas activas. También cubre cómo estos objetos permiten modificar parámetros de conexión y controlar transacciones. Finalmente, presenta ejemplos de cómo utilizar alias locales para cambiar dinámicamente la base de datos conectada o interceptar eventos de conexión.
Este documento describe cómo conectar aplicaciones Java a bases de datos utilizando JDBC. Explica los tipos de drivers JDBC, el proceso de consulta a una base de datos con JDBC, incluyendo la creación de sentencias SQL y el uso de objetos como Statement y ResultSet. También define los objetos clave de JDBC como DriverManager, Connection, Statement y ResultSet que permiten la comunicación entre Java y las bases de datos.
Este documento describe el procesamiento de páginas JSP y elementos como directivas, etiquetas e inclusiones. Explica que las páginas JSP combinan código HTML con etiquetas Java para programar scripts de servidor, y que estas páginas son traducidas a servlets de Java antes de su ejecución. También cubre la creación de acciones JSP personalizadas.
El documento habla sobre el soporte de Spring JDBC para simplificar el acceso a datos usando JDBC. Explica cómo Spring reduce la cantidad de código necesario al acceder a una base de datos relacional en comparación con el uso tradicional de JDBC, cubriendo temas como la conexión a la base de datos, recuperación y mapeo de datos, e inserción, actualización y eliminación de datos. También introduce un modelo de datos simple de ejemplo que se usará para ilustrar los conceptos a lo largo del capítulo.
El documento describe cómo conectar una base de datos MySQL a una aplicación Java. Se explica la creación de una clase ConexionDB que establece la conexión y devuelve un objeto Connection. También se muestra el código de una clase Main que llama al método GetConnection de ConexionDB para comprobar que la conexión se realiza correctamente. Finalmente, se detallan los pasos para probar la conexión en NetBeans.
Este documento presenta información sobre el uso de JDBC para conectar aplicaciones Java a bases de datos. Explica que JDBC permite establecer conexiones con bases de datos, enviar instrucciones SQL y procesar los resultados. Además, provee ejemplos de cómo realizar operaciones básicas como consultas, inserciones, actualizaciones y eliminaciones usando JDBC. Finalmente, hace recomendaciones sobre el diseño de aplicaciones que se conectan a bases de datos a través de JDBC.
Este documento presenta información sobre el uso de JDBC para conectar aplicaciones Java a bases de datos. Explica que JDBC permite establecer conexiones con bases de datos, enviar instrucciones SQL y procesar los resultados. Además, provee ejemplos de cómo realizar operaciones básicas como consultas, inserciones, actualizaciones y eliminaciones usando JDBC. Finalmente, da algunas recomendaciones sobre el diseño de aplicaciones que usen esta tecnología.
La interfaz Java Database Connectivity (JDBC) permite la ejecución de operaciones sobre bases de datos desde Java de forma independiente al sistema operativo o base de datos. Se basa en interfaces Java y manejadores de conexión específicos para cada base de datos. Un objeto Statement se usa para enviar sentencias SQL a la base de datos mediante los métodos executeUpdate, executeQuery y execute.
El documento trata sobre el uso de JDBC para conectarse a bases de datos desde Java. JDBC permite el acceso a bases de datos de diferentes tipos mediante una interfaz estandarizada. Explica los dos modelos de acceso a bases de datos que soporta JDBC, así como cómo establecer una conexión, los tipos de controladores y recomendaciones para mejorar el rendimiento.
Este documento describe los pasos para integrar Apache y Tomcat mediante el módulo JK. Se instala y configura el módulo JK, se modifican los archivos de configuración server.xml, workers.properties y jk.conf, y se reinician Apache y Tomcat para que funcionen conjuntamente.
El documento presenta información sobre MATLAB 7.0, incluyendo sus características, ventajas y cómo definir estructuras anidadas. Explica cómo acceder a la ayuda en MATLAB y diferentes tipos de datos como matrices, estructuras y cadenas.
Este documento presenta un tutorial básico sobre cómo acceder a bases de datos desde Java utilizando JDBC. Explica que JDBC requiere manejar manualmente las conexiones y sentencias SQL, lo que implica mucho código acoplado a la base de datos. También introduce los conceptos de POJOs y ORM, y cómo los frameworks ORM como Hibernate abstraen estas diferencias entre los modelos de objetos y relacionales.
Catalogo Cajas Fuertes BTV Amado Salvador Distribuidor OficialAMADO SALVADOR
Explora el catálogo completo de cajas fuertes BTV, disponible a través de Amado Salvador, distribuidor oficial de BTV. Este catálogo presenta una amplia variedad de cajas fuertes, cada una diseñada con la más alta calidad para ofrecer la máxima seguridad y satisfacer las diversas necesidades de protección de nuestros clientes.
En Amado Salvador, como distribuidor oficial de BTV, ofrecemos productos que destacan por su innovación, durabilidad y robustez. Las cajas fuertes BTV son reconocidas por su eficiencia en la protección contra robos, incendios y otros riesgos, lo que las convierte en una opción ideal tanto para uso doméstico como comercial.
Amado Salvador, distribuidor oficial BTV, asegura que cada producto cumpla con los más estrictos estándares de calidad y seguridad. Al adquirir una caja fuerte a través de Amado Salvador, distribuidor oficial BTV, los clientes pueden tener la tranquilidad de que están obteniendo una solución confiable y duradera para la protección de sus pertenencias.
Este catálogo incluye detalles técnicos, características y opciones de personalización de cada modelo de caja fuerte BTV. Desde cajas fuertes empotrables hasta modelos de alta seguridad, Amado Salvador, como distribuidor oficial de BTV, tiene la solución perfecta para cualquier necesidad de seguridad. No pierdas la oportunidad de conocer todos los beneficios y características de las cajas fuertes BTV y protege lo que más valoras con la calidad y seguridad que solo BTV y Amado Salvador, distribuidor oficial BTV, pueden ofrecerte.
Catalogo Buzones BTV Amado Salvador Distribuidor Oficial ValenciaAMADO SALVADOR
Descubra el catálogo completo de buzones BTV, una marca líder en la fabricación de buzones y cajas fuertes para los sectores de ferretería, bricolaje y seguridad. Como distribuidor oficial de BTV, Amado Salvador se enorgullece de presentar esta amplia selección de productos diseñados para satisfacer las necesidades de seguridad y funcionalidad en cualquier entorno.
Descubra una variedad de buzones residenciales, comerciales y corporativos, cada uno construido con los más altos estándares de calidad y durabilidad. Desde modelos clásicos hasta diseños modernos, los buzones BTV ofrecen una combinación perfecta de estilo y resistencia, garantizando la protección de su correspondencia en todo momento.
Amado Salvador, se compromete a ofrecer productos de primera clase respaldados por un servicio excepcional al cliente. Como distribuidor oficial de BTV, entendemos la importancia de la seguridad y la tranquilidad para nuestros clientes. Por eso, trabajamos en colaboración con BTV para brindarle acceso a los mejores productos del mercado.
Explore el catálogo de buzones ahora y encuentre la solución perfecta para sus necesidades de correo y seguridad. Confíe en Amado Salvador y BTV para proporcionarle buzones de calidad excepcional que cumplan y superen sus expectativas.
Catalogo General Electrodomesticos Teka Distribuidor Oficial Amado Salvador V...AMADO SALVADOR
El catálogo general de electrodomésticos Teka presenta una amplia gama de productos de alta calidad y diseño innovador. Como distribuidor oficial Teka, Amado Salvador ofrece soluciones en electrodomésticos Teka que destacan por su tecnología avanzada y durabilidad. Este catálogo incluye una selección exhaustiva de productos Teka que cumplen con los más altos estándares del mercado, consolidando a Amado Salvador como el distribuidor oficial Teka.
Explora las diversas categorías de electrodomésticos Teka en este catálogo, cada una diseñada para satisfacer las necesidades de cualquier hogar. Amado Salvador, como distribuidor oficial Teka, garantiza que cada producto de Teka se distingue por su excelente calidad y diseño moderno.
Amado Salvador, distribuidor oficial Teka en Valencia. La calidad y el diseño de los electrodomésticos Teka se reflejan en cada página del catálogo, ofreciendo opciones que van desde hornos, placas de cocina, campanas extractoras hasta frigoríficos y lavavajillas. Este catálogo es una herramienta esencial para inspirarse y encontrar electrodomésticos de alta calidad que se adaptan a cualquier proyecto de diseño.
En Amado Salvador somos distribuidor oficial Teka en Valencia y ponemos atu disposición acceso directo a los mejores productos de Teka. Explora este catálogo y encuentra la inspiración y los electrodomésticos necesarios para equipar tu hogar con la garantía y calidad que solo un distribuidor oficial Teka puede ofrecer.
HPE presenta una competició destinada a estudiants, que busca fomentar habilitats tecnològiques i promoure la innovació en un entorn STEAM (Ciència, Tecnologia, Enginyeria, Arts i Matemàtiques). A través de diverses fases, els equips han de resoldre reptes mensuals basats en àrees com algorísmica, desenvolupament de programari, infraestructures tecnològiques, intel·ligència artificial i altres tecnologies. Els millors equips tenen l'oportunitat de desenvolupar un projecte més gran en una fase presencial final, on han de crear una solució concreta per a un conflicte real relacionat amb la sostenibilitat. Aquesta competició promou la inclusió, la sostenibilitat i l'accessibilitat tecnològica, alineant-se amb els Objectius de Desenvolupament Sostenible de l'ONU.
1. JTABLE, TABLEMODEL Y RENDIMIENTO
Francesc Rosés / lulio 2004
Con frecuencia nos vemos obligados a visualizar una gran cantidad de datos mediante una
JTable. El resultado es una carga lenta, un scroll penoso y un consumo de RAM intolerable.
Ciertamente, hay alternativas. Uno siempre intenta minimizar los datos que carga e incluso se
inventa algún tipo de caché que necesita un montón de pruebas hasta que se da por aceptable.
La mayor parte de los datos en las cargas masivas suelen tener su origen en una base de datos a la
que accedemos mediante un driver JDBC. En este artículo hago una propuesta de un uso racional
tanto del TableModel como de las posibilidades que nos ofrece JDBC 2.0 (y posteriores) para
reducir a prácticamente nada el coste de la representación de grandes volúmenes de datos
mediante JTables.
¿QUÉ HACEMOS MAL?
Antes de exponer mi propuesta creo que es conveniente analizar algunas de las acciones más
frecuentes que nos llevan a la ineficiencia.
Usar lo que ya está hecho
Bien, “usar lo que ya está hecho” no es malo si lo que está hecho funciona como es debido. Este no
es el caso, por ejemplo, de una de las clases “ya hechas” de JTableModel:
DefaultTableModel. Los más comodones nos limitamos a usarla directamente, y los que lo son
menos, se permiten subclasearla. Sin embargo, DefaultTableModel es el final de una cadena de dos
elementos: la interficie JTableModel y la clase abstracta que la implementa:
AbstractTableModel. La clase DefaultTableModel no es más que una solución de
compromiso que nos ofrece Sun. Yo diría que, en realidad, es tan solo un ejemplo práctico, más o
menos afortunado.
No leer con detalle las APIs que tocan
En realidad, nuestra primera aproximación se basaba en un “copy/paste” del código de un
compañero que en cinco minutos, mientras tomábamos un café, nos contó que eso de las tablas y el
JDBC era muy sencillito, pero que el Swing, ya se sabe, es más lento que el caballo del malo.
En definitiva, sin ver un Javadoc ni por el forro, nos hemos lanzado a escribir nuestra primera
versión de la aplicación.
Os invito a hacer una prueba. Preguntad a vuestros compañeros (y a vosotros mismos, claro está) si
tienen una bookmark de las APIs de Java en su explorador. Veréis qué poquitos la tienen.
¿POR QUÉ ESTÁ MAL LO QUE HACEMOS?
Usar lo que ya está hecho: DefaultTableModel
La clase DefaultTableModel extiende AbstractTableModel y, si bien para algunos casos
simples y con poco volumen de datos puede ser útil, tiene varios problemas. El primero es el uso
1 de 11
2. exhaustivo de la clase Vector. No entraremos en detalles, sólo decir que Vector tiene todos sus
métodos sincronizados lo que es bastante caro y, en la mayor parte de los casos, innecesario. Sería
más conveniente usar una ArrayList para el almacenamiento de datos. Es equivalente a Vector,
pero no tiene sus métodos sincronizados.
Para aquellos casos simples en los que puede ser interesante usar un modelo con las funcionalidades
de DefaultTableModel, he desarrollado un nuevo modelo con la misma funcionalidad que
DefaultTableModel pero basado en una ArrayList: ArrayListTableModel.
Si bien ArrayListTableModel da un mayor rendimiento que DefaultTableModel (un
24% aproximadamente), no es la panacea. Las pruebas se han realizado con una tabla de 68.719
registros que ocupa, aproximadamente, 3,16 MB. Esto significa que, en ambos casos hemos de tener
cargados en RAM una List de, al menos, 3,16 MB.
Bueno, hemos conseguido mejorar el rendimiento, pero no los requisitos de memoria.
No leer con detalle las APIs que tocan
Sé que no se puede leer todo con detalle, pero es conveniente dar una leidita a los Javadoc de las
APIs involucradas en nuestro problema y al menos mantener pointers a lo que nos ha parecido
interesante (aunque no le hayamos visto una aplicación inmediata).
¿Qué APIs están involucradas en nuestro problema? Básicamente, nueve:
• javax.swing.JTable
• javax.swing.table.JTableModel
• javax.swing.table.AbtractTableModel
• javax.swing.table.TableCellRenderer
• java.sql.Connection
• java.sql.DatabaseMetaData
• java.sql.Statement
• java.sql.ResultSet
• java.sql.ResultSetMetaData
Todas aparecen en la solución propuesta y comentaremos con más detalle, en su momento, los
aspectos que nos interesan de cada una de ellas.
SOLUCIÓN CON ArrayList
Se recomienda utilizar ArrayList en vez de Vector siempre que podamos. Tened en cuenta
que Vector existe desde el JDK 1.0 mientras que ArrayList aparece en JDK 1.2. Algo debe
aportar...
Hemos comentado que el factor determinante es que ArrayList no tiene métodos
synchronized. Esto implica que si otro thread modifica nuestra ArrayList, hay que hacer la
sincronización a mano. Si consideramos que este hecho no es importante para nuestra aplicación, y
creo que en el 90% de los casos de modelos de JTable no lo es, podemos usar un modelo basado
en ArrayLists en nuestro modelo, Si lo es, podemos seguir usando el consabido
DefaultTableModel.
2 de 11
3. El problema es que Sun no proporciona ningún modelo basado en ArrayList y nos tocará
escribirlo desde cero. Yo he escrito un nuevo modelo basado en ArrayList,
ArrayListTableModel, que se supone que debe funcionar exactamente igual que
DefaultTableModel y lo pongo a vuestra disposición. Mis pruebas de rendimiento, como he
comentado más arriba, me dan un 24% de mejora de rendimiento respecto a
DefaultTableModel. Recordad, sin embargo, que nadie nos quita el hecho de tener todos los
registros en RAM.
Como es lógico, ArrayListTableModel extiende AbstractTableModel. Si tenéis que
escribir vuestro propio modelo, extended siempre AbstractTableModel, no extendáis
DefaultTableModel.
SOLUCIÓN CON JDBC Y SCROLLABLE CURSORS
Esta es, para mí, la solución óptima ya que cumple con los dos requisitos fundamentales:
1. Mejora el rendimiento
2. Utiliza poca memoria
La solución que propongo es sencilla de implementar y, además, muy eficiente. Podría limitarme a
explicar someramente su implementación y dar el código, pero como no creo que sea una solución
definitiva y es posible que a más de uno se le ocurra algo mejor, escribiré un poco más e intentaré
explicar cómo usa JTable los TableModel.
Es evidente que la solución propuesta no es la panacea. Como veréis el trabajo lo hace el gestor de
bases de datos, lo que supone una conexión abierta con la base de datos mientras se esté ejecutando
nuestra aplicación y una carga para el servidor.
El paradigma MVC (Model View Controller)
Creo que todos sabéis más o menos cómo funciona este paradigma, así que no entraré en detalles
introductorios y me centraré en lo que nos interesa, simplificando (hasta la incorrección) lo que sea
necesario.
Swing no utiliza exactamente el MVC, sino una variante: MD (Model Delegate) en la que el
Delegate incluye View y Controller. Además, JTable es un componente que está formado por
varios subcomponentes y cada uno de ellos con su modelo y su delegate.
JTable y MVC: un ejemplo sencillo
Simplificando mucho, diremos que una JTable muestra unos datos que se encuentran en el
modelo. Una JTable tiene unas dimensiones determinadas en las que “caben” un número concreto
de registros mostrables. JTable lo sabe y le pide al modelo sólo aquellos registros que puede
mostrar. En la mayor parte de los casos, nuestras JTables se encontrarán dentro de un
JScrollPane ya que no disponemos de espacio suficiente para mostrar todos los registros. Cada
vez que, por ejemplo, movemos la barra de desplazamiento vertical del JScrollPane, nuestra
JTable le pide más datos al modelo para poderlos mostrar. La solución es óptima ya que sólo le
pide unos pocos datos: aquéllos que puede representar. El método que utiliza para pedir datos al
modelo es getValueAt(int row, int column).
Imaginemos que tenemos una JTable con dos columnas; la primera muestra los números de 1 a
100 y la segunda, su doble (el valor de la primera columna, multiplicado por dos). Una utilización
3 de 11
4. no recomendable de nuestro modelo mantendría una matriz con los valores de los 100 primeros
números y su doble:
int[][] data = new int[100][2];
[...]
private void fillData() {
for (int i = 1; i <= 100; i++) {
data[i-1][0] = i;
data[i-1][1] = i * 2;
}
}
En nuestro modelo, declaramos una matriz de enteros de 100x2 y la llenamos mediante el método
fillData().
Para pedir datos a nuestro modelo, nuestra JTable usa los siguientes métodos del modelo:
public int getColumnCount() {
return data[0].length;
}
public int getRowCount() {
return data.length;
}
El primero le sirve para acotar el número de columnas. Si tiene 2 columnas, no pregutará por la
onceava...
El segundo le sirve para acotar el número de registros disponibles.
Finalmente, una vez tiene claro cuántas columnas y cuántos registros tiene el modelo de datos,
pregunta por el valor concreto de una celda usando el método Object getValueAt(int
rowIndex, int columnIndex). En nuestro caso, lo podríamos implementar fácilmente así:
public Object getValueAt(int rowIndex, int columnIndex) {
return new Integer(data[rowIndex-1][columnIndex]);
}
Observemos que esta es una implementación sumamente ineficiente. Hay que llenar una matriz y
después consultarla. Esto puede no ser caro para los 100 primeros números, pero si queremos
trabajar, por ejemplo, con los 500.000 primeros números, nuestra implementación empezaría a
renquear.
Veamos una implementación más eficiente:
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return 500000;
}
public Object getValueAt(int rowIndex, int columnIndex) {
if (columnIndex == 0) {
return new Integer(rowIndex);
}
return new Integer((rowIndex*2));
}
En esta segunda implementación optimizamos al máximo los recursos de memoria ya que no
4 de 11
5. almacenamos ningún valor. Los valores se calculan en tiempo de ejecución.
JTable y MVC: un mal ejemplo con JDBC
Si bien el ejemplo anterior es bastante ilustrativo y nos puede venir bien para implementar algunos de
nuestros modelos, no ejemplifica el caso más típico: los datos a representar provienen de una
consulta a la base de datos.
Llegados a este punto, optamos por una solución típicamente ineficiente como esta:
Statement stmt = null;
ResultSet rs = null;
Vector rows = new Vector();
String select = “SELECT NOMBRE, APELLIDO1, APELLIDO2 FROM PERSONAS”;
try {
stmt = connection.createStatement();
rs = stmt.executeQuery(select);
while (rs.next()) {
String nombre = rs.getString(1);
String apellido1 = rs.getString(2);
String apellido2 = rs.getString(3);
Vector row = new Vector();
row.addElement(nombre);
row.addElement(apellido1);
row.addElement(apellido2);
rows.addElement(row);
}
} catch (SQLException e) {
e.printStackTrace();
}
finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
}
}
}
Vector colNames = new Vector(3);
colNames.addElement(“Nombre”);
colNames.addElement(“Primer Apellido”);
colNames.addElement(“Segundo Apellido”);
DefaultTableModel model = new DefaultTableModel(rows, colNames);
miTabla.setModel(model);
Como la lista de personas sea la de la guía telefónica de España, no hay JTable que lo soporte.
Éste suele ser el problema al que nos enfrentamos. Cargar toda la tabla en memoria es realmente
costoso.
Análisis del problema
Fijémonos en el primer ejemplo. El modelo, en realidad, no contiene datos. Los calcula. Es eficiente
porque no tiene un lento proceso de carga y porque prácticamente no usa memoria. Simplemente,
proporciona a la JTable lo que ésta le pide.
En nuestro ejemplo JDBC el modelo contiene todos los datos. Hay que cargarlos y almacenarlos en
memoria. No es, pues, eficiente si los datos son muchos.
5 de 11
6. Observemos, sin embargo, que los datos ya están en la base de datos. Si esto es así, ¿por qué no
“calculamos” los datos que nos pide la JTable pidiéndoselos a nuestra base de datos y simplemente
le retornamos lo que necesita?
Un modelo proporciona datos al delegate siguiendo un protocolo concreto, no es necesario
que él tenga los datos. Basta con que los suministre (calculándolos u obteniéndolos de un
tercero bajo demanda).
UNA POSIBLE SOLUCIÓN: ScrollableTableModel
Hasta la aparición de JDBC 2.0, no podíamos hacer otra cosa que cargar los datos resultantes de
nuestra consulta en memoria. El ResultSet sólo podía moverse en una dirección: hacia adelante.
No podía, pues, dar respuesta a los requerimientos de una tabla capaz de moverse hacia adelante y
hacia atrás. Pero a partir de JDBC 2.0, disponemos de ResultSets que pueden moverse
libremente por el conjunto de resultados de una consulta. El modelo, pues, puede limitarse a
“calcular” los datos que debe devolver y extraerlos del ResultSet.
Determinar si nuestro driver JDBC soporta scrollable cursors
Lamentablemente, no todos los drivers JDBC soportan scrollable cursors. Para determinar si nuestro
driver los soporta, hemos de consultar la metadata de la base de datos:
private boolean supportsScrollInsensitive(Connection con) {
DatabaseMetaData md = null;
try {
md = con.getMetaData();
} catch (SQLException e) {
String errMsg = "Error getting database metadata.";
throw new ScrollableTableModelException(errMsg, e);
}
try {
return md.supportsResultSetType(
ResultSet.TYPE_SCROLL_INSENSITIVE);
} catch (SQLException e) {
String errMsg = "Error getting database metadata.";
throw new ScrollableTableModelException(errMsg, e);
}
} // supportsScrollInsensitive()
Uso de scrollable cursors
Como hemos visto, para que nuestro modelo funcione debemos disponer de scrollable cursors.
Suponiendo que suportsScrollInsensitive() nos devuelva true, podemos definir un
Statement que use scrollable cursors:
stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
No entraré aquí en detalles sobre la sintaxis de este método, sólo diré que el primer parámetro
establece el tipo de scroll y el segundo, el nivel de aislamiento del cursor.
Obtención y retorno de los datos
Una vez disponemos de nuestro ResultSet scrollable, hemos de utilizar sus posibilidades
6 de 11
7. sobrescribiendo el método getValueAt():
public Object getValueAt(int rowIndex, int columnIndex) {
int rowNdx = rowIndex + 1;
int colNdx = columnIndex + 1;
try {
resultSet.absolute(rowNdx);
return resultSet.getObject(colNdx);
} catch (SQLException e) {
String errMsg = "Error getting value at " +
rowIndex + ", " + columnIndex;
throw new ScrollableTableModelException(errMsg, e);
}
}
Lo primero que hace nuestro método es traducir las coordenadas de JTable a coordenadas de
JDBC. En JDBC se empieza a contar desde 1, y en el resto del mundo Java, se empieza a contar
desde 0. Así, si JTable nos pide los datos del registro 0, columna 0, hemos de traducirlo a JDBC
como registro 1, columna 1.
A continuación situamos el cursor en el registro JDBC solicitado:
resultSet.absolute(rowNdx);
Una vez situado el cursor, obtenemos los datos almacenados en la columna JDBC que se nos pide:
resultSet.getObject(colNdx);
Obsérvese que pedimos y devolvemos un Object.
Las clases de las columnas
JTable es capaz de mostrar nuestros datos en función de su tipo. Para ello utiliza clases que
implementan la interfície TableCellRenderer. Pero, como es lógico, alguien tiene que decirle
qué clase de objeto recibe. Si no se le dice, utiliza el método toString() del objeto de datos para
mostrar su contenido.
En nuestro caso, devolvemos un Object y, si no le proporcionamos más datos, nos mostrará lo que
devuelva el método toString() del objeto que devolvemos.
Si no hay un renderer para un tipo de objeto concreto, también utiliza el método toString() de
dicho objeto.
Es conveniente, pues, indicarle qué clase de objeto le estamos devolviendo para cada columna. Esto
se lleva a cabo implementando el método abstracto getColumnClass() de
AbstractTableModel. Lo cierto es que, por ejemplo, DefaultTableModel no implementa
este método. Un motivo más para utilizarlo con precaución.
La implementación para nuestro modelo podría ser la siguiente:
List colClasses = null;
[...]
public Class getColumnClass(int columnIndex) {
if (colClasses == null) {
colClasses = new ArrayList();
ResultSetMetaData md = null;
try {
md = resultSet.getMetaData();
int colCount = md.getColumnCount();
for (int i = 0; i < colCount; i++) {
try {
7 de 11
8. String className = md.getColumnClassName(i + 1);
Class c = Class.forName(className);
colClasses.add(c);
} catch (ClassNotFoundException e) {
String errMsg = "Error getting column classes.";
throw new ScrollableTableModelException(errMsg, e);
}
} // for i
} catch (SQLException e) {
String errMsg = "Error getting column classes.";
throw new ScrollableTableModelException(errMsg, e);
}
}
Class c = (Class)colClasses.get(columnIndex);
return c;
}
Como puede verse, la información sobre el tipo del objeto retornado proviene de
ResultSetMetaData. Para cada una de las columnas, preguntamos cuál es el nombre de la clase
(getColumnClassName(i + 1)), una vez más traduciendo coordenadas de JTable a JDBC.
A partir del nombre de la clase, obtenemos la Class: Class c = Class.forName
(className); que es lo que devolvemos a la JTable. Ella ya se encargará de ver cómo muestra
los datos de esa clase.
Obtención de los nombres de las columnas
Como hemos visto, una de las cosas que JTable pide al modelo son los nombres de las columnas.
Podemos obtener estos nombres directamente del ResultSet utilizando la clase
ResultSetMetaData:
ArrayList colNames = null;
[...]
ResultSetMetaData rsmd = null;
try {
rsmd = resultSet.getMetaData();
int colCount = rsmd.getColumnCount();
if (colCount == 0) {
// TODO: No hay columnas!
}
this.colNames = new ArrayList();
for (int i = 0; i < colCount; i++) {
String colLabel = rsmd.getColumnLabel(i+1);
this.colNames.add(colLabel);
}
} catch (SQLException e) {
e.printStackTrace();
String errMsg = "Error getting ResultSetMetadata";
throw new ScrollableTableModelException(errMsg, e);
}
Obsérvese que utilizo el método getColumnLabel() para obtener el nombre de la columna,
cuando pareciera más lógico usar el método getColumnName(). Lo cierto es que
getColumnLabel() devuelve lo mismo que getColumnCount(), excepto si especificamos
una etiqueta específica en nuestra consulta SQL:
SELECT N AS “Nombre”, A AS “Apellidos” FROM PERSONAS
8 de 11
9. En este ejemplo, getColumnName() devolvería N y A, mientras que getColumnLabel()
devolvería Nombre y Apellidos.
Obviamente, nuestro modelo debe ofrecer la posibilidad de especificar una ArrayList con los
nombres de las columnas.
Lógicamente, habrá que sobrescribir el método getColumnName():
public String getColumnName(int column) {
return (String)colNames.get(column);
}
¿Cuantas columnas?
Como hemos visto más arriba, una de las cosas que JTable necesita saber es el número de
columnas del modelo. Para ello usa el método getColumnCount() que podemos implementar
como sigue:
public int getColumnCount() {
return colNames.size();
}
¿Cuantos registros?
Tal como hemos comentado, JTable necesita saber también cuántos registros tiene el modelo para
poder acotar los parámetros pasados al método getValueAt(int rowIndex, int
columnIndex). Para ello utiliza el método getRowCount(), que podría ser implementado, en
nuestro caso, de la siguiente manera:
int rowCount = -1;
[...]
public int getRowCount() {
if (this.rowCount == -1) {
try {
resultSet.last();
this.rowCount = resultSet.getRow();
} catch (SQLException e) {
String errMsg = "Error scrolling to latest row.";
throw new ScrollableTableModelException(errMsg, e);
}
}
Disponemos de la variable rowCount inicializada a -1, lo que nos indicará que todavía no hemos
calculado su valor.
El el método getRowCount(), pasamos a calcular su valor siempre que éste valga -1 (es decir,
siempre que todavía no lo hayamos inicializado). Para ello, situamos el cursor en el último registro
(resultSet.last()) y asignamos a rowCount el valor devuelto por el método getRow();
esto es, el número del último registro que, en notación JDBC equivale al número de registros.
Rendimientos
Entramos aquí en el apartado más práctico de todos: ¿qué gano en cada caso?
Hemos comentado ya que el modelo ArrayListTableModel suponía una mejora de
rendimiento del 24% respecto al modelo DefaultTableModel. Las pruebas realizadas sobre la
misma base de datos con ScrollableTableModel me indican que la mejora de rendimiento
9 de 11
10. respecto a DefaultTableModel es, aproximadamente, del 600%.
LA CLASE ScrollableTableModel
Como he comentado más arriba, pongo a disposición pública la clase ScrollableTableModel.
Si bien, hasta ahora he comentado algunos aspectos de la implementación, no he hablado todavía del
uso. Vamos, pues, a ello.
Constructores
public ScrollableTableModel(Connection con, String select)
Parámetro Comentario
con Una conexión abierta con la base de datos
select La instrucción SELECT necesaria para obtener los datos
Los nombres de las columnas se obtienen a partir del ResultSetMetaData, tal como he
comentado más arriba.
ScrollableTableModel(Connection con, String select, List colNames)
Parámetro Comentario
con Una conexión abierta con la base de datos
select La instrucción SELECT necesaria para obtener los datos
colNames Una java.util.List (p.e. ArrayList) con los nombres de las columnas
El número de elementos de colNames deberá coincidir con el número de columnas devuelto por la
consulta.
public ScrollableTableModel(ResultSet rs)
Parámetro Comentario
rs Un ResultSet configurado con Scroll Intensive.
Recordemos que para que el ResultSet soporte scroll, debemos especificarlo en el momento de
creación del Statement. Por ejemplo:
stmt = connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_READ_ONLY);
Los nombres de las columnas se obtienen a partir del ResultSetMetaData, tal como he
comentado más arriba.
10 de 11
11. public ScrollableTableModel(Statement stmt)
Parámetro Comentario
stmt Un Statement configurado con Scroll Intensive conteniendo un
ResultSet.
Los nombres de las columnas se obtienen a partir del ResultSetMetaData, tal como he
comentado más arriba.
public ScrollableTableModel(ResultSet rs, List colNames)
Parámetro Comentario
rs Un ResultSet configurado con Scroll Intensive.
select La instrucción SELECT necesaria para obtener los datos
colNames Una java.util.List (p.e. ArrayList) con los nombres de las columnas
public ScrollableTableModel(Statement stmt, List colNames)
Parámetro Comentario
Stmt Un Statement configurado con Scroll Intensive conteniendo un
ResultSet.
select La instrucción SELECT necesaria para obtener los datos
colNames Una java.util.List (p.e. ArrayList) con los nombres de las columnas
Ejemplo de uso
El siguiente código muestra un sencillo ejemplo de uso de ScrollableTableModel, usando tan
solo una connexión a base de datos y un select:
public class ScrollableTableModelTest {
public static void main(String[] args) {
Connection con = null;
[... Carga del Driver JDBC y connexión a BD ...]
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTable tabResults = new JTable();
JscrollPane spTabResults = new JscrollPane(tabResults);
f.getContentPane().add(spTabResults, BorderLayout.CENTER);
String sel = “SELECT * FROM PERSONAL”;
ScrollableTableModel model = new ScrollableTableModel(con, sel);
tabResults.setModel(model);
f.pack();
// Ventana centrada en la pantalla
f.setLocationRelativeTo(null);
f.setVisible(true);
} // main()
}
11 de 11