JAVA CON BASE DE DATOS
|
1. CONTENIDO
a) DEFINICION
Es una API que permite la
ejecución de operaciones sobre bases de datos desde el lenguaje de programación Java, independientemente
del sistema operativo donde se ejecute o de la base de datos a la cual se
accede, utilizando el dialecto SQL del modelo de base de datos que se
utilice.
Se presenta como una colección de interfaces Java y métodos de gestión
de manejadores de conexión hacia cada modelo específico de base de datos. Un
manejador de conexiones hacia un modelo de base de datos en particular es un
conjunto de clases que implementan las
interfaces Java y que utilizan los
métodos de registro para declarar los tipos de localizadores a base de datos
(URL) que pueden manejar.
Para utilizar una base de datos particular, el usuario ejecuta su programa
junto con la biblioteca de conexión apropiada al modelo de su base de datos,
y accede a ella estableciendo una conexión; para ello provee el localizador a
la base de datos y los parámetros de conexión específicos. A partir de allí
puede realizar cualquier tipo de tarea con la base de datos a la que tenga
permiso: consulta, actualización, creación, modificación y borrado de tablas,
ejecución de procedimientos almacenados en la base de datos.
Una base
de datos es una colección de información organizada de forma que un
programa de ordenador pueda seleccionar rápidamente los fragmentos de datos
que necesite. Una base de datos es un sistema de archivos electrónico.
Las
bases de datos tradicionales se organizan por campos, registros y archivos.
Un campo es una pieza única de información; un registro es un
sistema completo de campos; y un archivo es una colección de registros.
Por ejemplo, una guía de teléfono es análoga a un archivo. Contiene una lista
de registros, cada uno de los cuales consiste en tres campos: nombre,
dirección, y número de teléfono.
El driver con la base de
datos
Lo
primero que necesitamos para conectarnos con una base de datos es
un Driver (o Conector) con ella. Ese Driver es la clase que,
de alguna forma, sabe cómo hablar con la base de datos. Desgraciadamente (y
hasta cierto punto es lógico), java no viene con todos los Drivers de todas
las posibles bases de datos del mercado. Debemos ir a internet y obtener el
Driver, normalmente en la página de nuestra base de datos
Para
el caso de MySQL, podemos descargarlo de. Nos bajamos
el mysql-connector-java-5.0.5.zip, lo desempaquetamos en algún sitio y
nos quedamos con el mysql-connector-java-5.0.5-bin.jar que viene
dentro. En ese jar está la clase Driver que nos interesa.
Tendremos
que poner ese jar accesible en nuestro proyecto. Dependiendo de qué
utilicemos para programar en java hay muchas opciones.
Guardarlo
en la carpeta <DIRECTORIO_DE_JAVA>/jre/lib/ext. Si has hecho una
instalación por defecto en Windows, estará en C:\Archivos de
Programa\Java\jdk1.5.0_05\jre\lib\ext. Esta es la carpeta en la que java nos
deja poner jar adicionales para que se encuentren por defecto. Es buena idea
ponerlo aquí si vamos a hacer muchos programas con base de datos. Si solo
vamos a hacer uno, es mejor no ponerlo aquí. Si decidimos usar esta carpeta,
también debemos tener la precaución de ir retirando jars de versiones
antiguas cuando pongamos las nuevas, o tendremos problemas.
Ponerlo
en la variable de entorno CLASSPATH, siempre que nuestro IDE (eclipse,
netbeans, etc) haga caso de esa variable. Si trabajas con una ventana de
ms-dos (símbolo del sistema), puedes poner esto
C:\>
set CLASSPATH=<PATH_DEL_JAR>\mysql-connector-java-5.0.5-bin.jar
Añadirlo
en nuestro IDE. En el ejemplo de eclipse, damos con el botón derecho del
ratón sobre el proyecto, para sacar el menú y elegimos
"properties"->"java build
path"->"Libraries"->"Add external JARs..." y
seleccionamos nuestro jar.
Conectarnos
con la base de datos
Una
vez que java tiene el jar accesible y sabe dónde encontrarlo, ya podemos
empezar con el código. Lo primero es conectarse con la base de datos
El
código puede ser como este
import
java.sql.Connection;
import java.sql.DriverManager; ... try { Class.forName("com.mysql.jdbc.Driver"); Connection conexion = DriverManager.getConnection("jdbc:mysql://localhost/agenda", "root", "LA_PASSWORD"); ...
En
primer lugar hemos hecho los import adecuados para poder obtener la
conexión.
Luego
hay que asegurarse de que se inicializa el Driver y se registra. Para ello
hay dos opciones. Hacer un new de él o bien instanciarlo con
Class.forName("nombre de clase"), que es como hacer el new, pero de
una forma rara.
La
ventaja de hacerlo con Class.forName() es que sólo necesitaremos el Driver de
una base de datos si lo usamos. Me explico. Imagina que haces un programa que
permite permite conectarse con varias bases de datos distintas: MySQL,
PostGres, Oracle, etc. En algún sitio damos a elegir al usuario qué tipo de
base de datos tiene.
Si
hacemos new de los Driver, tendremos que hacer unos if para en función de la
elegida, hacer new de uno o de otro. El problema es que en nuestro código
estarán los import y los new de todos los Driver de todas las bases de datos
necesarias, los vayamos a usar o no. El programa no compilará y no correrá si
no tiene todos los Driver accesibles.
/*
Todos estos import son necesarios para que compilen los news correspondientes
*/
import driver_de_mysql; import driver_de_postgres; import driver_de_oracle; ... if (ha_elegido_mysql) new driver_de_mysql(); if (ha_elegido_postgres) new driver_de_postgres(); if (ha_elegido_oracle) new driver_de_oracle();
Sin
embargo, con Class.forName() no necesitamos el import. Haremos los mismos if
de antes, pero usaremos simplemente String distintos para llamar a
Class.forName(). No necesitamos los import y no necesitamos los jar con los
Driver, salvo el jar con el Driver que realmente elija el usuario. Es cosa
suya tener instalado SU driver de SU base de datos.
/*
No hacen falta imports */
... if (ha_elegido_mysql) Class.forName("driver_de_mysql"); if (ha_elegido_postgres) Class.forName("driver_de_postgres"); if (ha_elegido_oracle) Class.forName("driver_de_oracle");
Una
vez que nos hemos asegurado que java tiene el Driver cargado, simplemente
pediremos conexión con la base de datos a la clase DriverManager.
Connection
conexion =
DriverManager.getConnection("jdbc:mysql://localhost/agenda",
"root", "LA_PASSWORD");
DriverManager
tiene muchos métodos getConnection() con parámetros variados. Todos
son variantes de lo mismo y la información que suministramos es la misma.
Aquí hemos utilizado uno con tres parámetros String, que vamos a explicar.
url:
Es una cadena que nos permite localizar la base de datos. Para mysql, el
formato es
"jdbc:mysql://ordenador_donde_corre_la_base_de_datos/nombre_base_datos".
Donde se pone el nombre o IP del ordenador en el que se encuentra nuestro
servidor de base de datos y el nombre de la base de datos. En nuestro
ejemplo, tenemos el servidor de base de datos corriendo en el mismo ordenador
que el programa java, por lo que ponemos localhost. La base de datos la
he llamado agenda. El comando SQL para crear la base de datos agenda
sería
mysql>
CREATE DATABASE agenda;
user:
Un usuario válido para la base de datos.
password:
La clave del usuario.
Si
todo va bien, tendremos nuestra conexión a la base de datos. Si va mal,
saltará una excepción. Por eso es importante (y obligatorio para que compile)
meter todo esto en un try-catch.
Esta
forma de obtener una conexión está bien para aplicaciones sencillas, en el
que únicamente se establece una conexión con la base de datos, no hay muchos
hilos trabajando, etc. Si nuestra aplicación es algo más compleja/seria, en
el que varios hilos pueden trabajar simultáneamente, en vez de obtener las
conexiones directamente con DriverManager.getConnection(), es mejor obtenerlas a través de un Pool de
Conexiones.
|
||||||||||||||||||
|
Un
objeto Statement se usa para enviar sentencias SQL a la base de datos.
Actualmente hay tres tipos de objetos Statement, todos los cuales actúan como
contenedores para la ejecución de sentencias en una conexión dada: Statement,
PreparedStatement que hereda de Statement y CallableStatement que hereda de
PreparedStatement. Estas estàn especializadas para enviar tipos particulares
de sentencias SQL, Un objeto Statement se usa para ejecutar una sentencia SQL
simple sin parámetros. Un objeto PreparedStatement se usa para ejecutar
sentencias SQL precompiladas con o sin parámetros IN; y un objeto
CallableStatement se usa para ejecutar un procedimieno de base de datos
almacenado.
La
interfase Statement suminstra métodos básicos para ejecutar sentencias y
devolver resultados. La interfase PreparedStatement añade métodos para
trabajat con los parámetros IN; y la interfase CallableStatement añade
métodos para trabajar con parameters OUT.
Creación
de objetos Statement
Una
vez establecida la conexión con una base de datos particular, esta conexión
puede usarse para enviar sentencias SQL. Un objeto Statement se crea mediante
el método de Connection createStatement, como podemos ver en el siguiente
fragmento de código.
Connection
con = DriverManager.getConnection(url, "sunny", "");
Statement stmt = con.createStatement();
La
sentencia SQL que será enviada a la base de datos es alimentada como un
argumento a uno de los métodos de ejecución del objeto Statement. Por
ejemplo:
ResultSet
rs = stmt.executeQuery("SELECT a, b, c FROM Table2");
b) OBJETO
CONNECTION
Visual
Studio .NET 2003
El
objeto Connection representa una conexión HTTP entre la prueba dinámica (el
cliente) y el servidor Web. La prueba abre la conexión, aunque tanto la
prueba como el servidor Web pueden cerrarla. Se pueden enviar múltiples
solicitudes mediante una sola conexión, siempre que esta última permanezca
abierta.
Propiedades
Métodos
b) Statement:
Tiene
muchos métodos, pero hay dos interesentantes: executeUpdate() y executeQuery().
El primero se usa para sentencias SQL que impliquen modificaciones en la base
de datos (INSERT, UPDATE, DELETE, etc). El segundo sólo para consultas
(SELECT y similares).
Nuestra
creación de tabla afecta a la base de datos, así que con executeUpdate().
st.executeUpdate("CREATE
TABLE contacto (id INT AUTO_INCREMENT, PRIMARY KEY(id), nombre VARCHAR(20),
apellidos VARCHAR(20), teléfono VARCHAR(20))");
Esto
crea una tabla contacto con cuatro
campos: id, nombre, apellidos y teléfono.
Para
borrar la tablita esta, lo mismo, pero con DROP en vez
de CREATE.
st.executeUpdate("DROP
TABLE contacto");
Insertar
datos en la base de datos
Vamos
a hacer un esfuerzo de imaginación y supongamos que no hemos borrado la
tabla contacto, que sigue existiendo en base de datos. Vamos a meterle
datos.
String
nombres[]={"Juan","Pedro","Antonio"};
String apellidos[]={"Gomez","Lopez","Alvarez"}; String telefonos[]={"123","456","789"}; ... for (int i=0;i<nombres.length;i++) st.executeUpdate("INSERT INTO contacto (nombre, apellidos, telefono) VALUES ('"+nombres[i]+"','"+apellidos[i]+"','"+telefonos[i]+"' )");
También
en un try-catch.
He
puesto los datos a insertar en unos arrays. Tú puedes recogerlos de un sitio
con más sentido. Por ejemplo, si es una agenda de contactos, lo mejor es
pedírselos al usuario. Yo, por simplicidad y porque para el ejemplo va que
chuta, los pongo en un array y con un bucle los voy insertando.
Fíjate
que la sentencia INSERT se va componiendo a base de sumar cadenas. Sería más eficiente
con un StringBuffer, pero así se simplifica algo el ejemplo.
Fíjate
que en el INSERT metemos comillas simples para los valores de cadenas, es
decir, en nombre, apellidos y teléfono. El INSERT sería,
de verdad, así
INSERT
INTO contacto (nombre, apellidos, teléfono) VALUES ('Juan', 'Gomez', '123');
Ahí
se ven más claras las comillas simples para los datos que definimos
como VARCHAR en la creación de la tabla, es
decir, Juan, Gomez y 123. Por eso en el código las hemos
puesto
...VALUES
('"+nombres[i]+"','"...
Si
fuesen datos numéricos no harían falta, son cosas de SQL, pero tenemos que
tener cuidado de componerlas bien.
Consultar
datos de la base de datos
Vamos
a hacer ahora una consulta de los datos que acabamos de insertar en la base
de datos. Las consultas se hacen con executeQuery() y nos
devolverán un ResultSet.
El ResultSet de
alguna forma representa una conexión hacia los datos. En
el ResultSet NO están todavía los datos. Según se los vayamos
pidiendo, los irá trayendo de base de datos. Esto quiere decir que si una
consulta devuelve muchos resultados, no se nos va a llenar la memoria por el
hecho de hacer la consulta.
Para
traer el primer resultado, debemos llamar el
método next() del ResulSet. Para el siguiente
otro next() y así sucesivamente hasta que next() devuelva
false, indicando que ya no quedaban datos. El código puede ser así
ResultSet
rs = st.executeQuery("SELECT * FROM contacto");
while (rs.next()) { System.out.println("nombre="+rs.getObject("nombre")+ ", apellidos="+rs.getObject("apellidos")+ ", telefono="+rs.getObject("telefono")); } rs.close();
Hemos
hecho un SELECT para obtener los datos. Luego un
bucle while(rs.next()), es decir, mientras next() vaya
trayendo resultados.
Después
de next(), el resultado recién traido está disponible en
el ResulSet. La forma de recoger los campos es pedirlos con algún
método get(). Si sabemos de qué tipo es el dato, podemos pedirlo
con getInt(), getString(), etc. Si no lo sabemos o nos da igual
(como en este caso), bastará con un getObject(), capaz de traer
cualquier tipo de dato.
En
estos métodos get() podemos pasar como parámetro un entero,
empezando en 1, que es el número del campo en el SELECT. Es decir, si
hacemos SELECT campo1, campo2, campo3..., si
pedimos getObject(1) obtenemos el valor de campo1,
para getObject(2) el de campo2, etc.
Otra
opción que a mi me gusta más, es pasar el nombre del campo, como se muestra
en el código. Así, en el ejemplo de
antes, getObject("campo1") nos devuelve el valor
delcampo1.
Update
en la base de datos
Para UPDATE usamos executeUpdate().
Vamos a cambiar el número de teléfono de Juan. Ya que en la tabla hemos
puesto un campo id, vamos primero a obtener
el id deJuan para luego usarlo en el UPDATE. Esto no tiene
por qué ser así, es sólo el ejemplo.
Para
obtener el id:
rs
= st.executeQuery("SELECT id FROM contacto WHERE nombre='Juan'");
rs.next(); int id = rs.getInt("id");
Es
un SELECT para obtener el campo id de Juan.
Con rs.next() hacemos que venga el primer resultado de la consulta
(y único en nuestro ejemplo). Como sabemos que es unINT, lo recogemos
con getInt() y lo guardamos.
Para
hacerlo bien, deberíamos ver si rs.next() devuelve o no resultado
(quizás no haya nadie que se llame Juan en la base de datos) o si
devuelve más de uno (más de unJuan en la base de datos), pero no vamos a
complicarnos la vida en este ejemplo sencillo.
Ahora,
sabiendo el id, podemos hacer el UPDATE.
st.executeUpdate("UPDATE
contacto SET telefono='111' WHERE id="+id);
Esta
vez, como el campo id es numérico, no hemos puesto las comillas
simples.
Ejecución de sentencias
usando objetos Statement.
La
interfase Statement nos suministra tres métodos diferentes para ejecutar
sentencias SQL, executeQuery, executeUpdate y execute. El método a usar está
determinado por el producto de la sentencia SQL
El
método executeQuery está diseñado para sentencias que producen como resultado
un único result set tal como las sentencias SELECT.
El método executeUpdate se usa para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL (Data Definition Language) como CREATE TABLE o DROP TABLE. El efecto de una sentencia INSERT, UPDATE o DELETE es una modificación de una o más columnas en cero o más filas de una tabla. El valor devuelto de executeUpdate es un entero que indica el número de filas que han sido afectadas (referido como update count). Para sentencias tales como CREATE TABLE o DROP TABLE, que no operan sobre filas, le valor devuelto por executeUpdate es siempre cero.
El
método execute se usa para ejecutar sentencias que devuelven más de un result
set, más que un update count o una combinación de ambos. Como es esta una
característica avanzada que muchos programadores no necesitan nunca se verá
en su propia sección.
Todos
los métodos que ejecutan sentencias cierran los objetos Resultset abiertos
como resultado de las llamadas a Statement. Esto quiere decir que es
necesario completar el proceso con el actual objeto Resulset antes de ejecutar
una sentencia Statement.
Debe
notarse que la interfase PreparedStatement, que hereda los métodos de la
interfase Statement, tiene sus propias versiones de los métodos executeQuery,
executeUpdate y execute. Los objetos Statement en sí mismos no contienen una
sentencia SQL, por tanto debe suministrarse como un argumento a los métodos
Statement.execute. Los objetos PreparedStatement no suministran una sentencia
SQL como argumento a estos métodos puesto que ya tienen la sentencia
precompilada. Los objetos CallableStatement heredan las formas de estos
métodos de PreparedStatement. Usar un parámetro de query con las versiones de
los métodos de PreparedStatement o CallableStatement producirá una
SQLException,.
Realización de Statement Cuando una conexión está en modo auto-commit, las sentencias ejecutadas son ‘comitadas’ o rechazadas cuando se completan. Una sentencia se considera completa cuando ha sido ejecutada y se han devuelto todos los resultados. Pare el método executeQuery, que devuelve un único result set, la sentencia se completa cuando todas las filas del objeto ResultSet se han devuelto. Para el método executeUpdate, una sentencia se completa cuando se ejecuta. En los raros casos en que se llama al método execute, de cualquier modo, no se completa hasta que los result sets o update counts que se generan han sido devueltos.
Algunos
DBMS tratan cada sentencia en un procedimiento almacenado como sentencias
separadas. Otros tratan el procedimiento entero como una sentencia compuesta.
Esta diferencia se convierte en importante cuando está activo el modo
auto-commit porque afecta cuando se llama al método commit. En el primer
caso, cada sentencia individual es commitada. En el segundo, se commiten
todas juntas.
Cerrar objetos
Statement.
Los
objetos Statement se cerrarán automáticamente por el colector de basura de Java
(garbage collector). No obstante se recomienda como una buena práctica de
programación que se cierren explicitamente cuando no sean ya necesarios. Esto
libera recursos DBMS inmediatamente y ayuda a evitar potenciales problemas de
memoria.
Sintaxis de Escape SQL
en objetos Statement
Los
objetos Statement pueden contener sentencias SQL que usen sintaxis de escape
SQL. La sintaxis de escape señala al driver que el código que lleva debe ser
tratado diferentemente. El driver buscará por cualquier sintaxis de escape y
lo traducirá en código que entiende la base de datos en particular. Esto hace
que la sintaxis de escape sea independiente de la DBMS y permite al
programador usar características que de otro modo no estarían disponibles.
Una
cláusula de escape se enmarca entre llaves y tiene una palabra clave:
{keyword
. . . parameters . . . }
La palabra clave (keyword) indica el tipo de cláusula de escape, según se muestra:
•
escape para caracteres LIKE
Los
caracteres “%” y “_” trabajan como wildcards en la cláusula SQL LIKE (“%”
significa cero o más caracteres y “_” significa exactamente un carácter”. En
orden a interpretarlos literalmente, pueden estar precedidos por un backslash
(‘\’), que es un carácter de escape especial en cadenas. Se puede especificar
un carácter que se use como carácter de escape por la inclusión de la
sintaxis siguiente al final de la consulta.
{escape
'escape-character'}
Por
ejemplo, la siguiente query, usando backslash como carácter de escape,
encuentra nombres de identificador que comiencen con ‘_’.
stmt.executeQuery("SELECT
name FROM Identifiers
WHERE Id LIKE `\_%' {escape `\'}; • fin para funciones escalares
Casi
todas las DBMS tienen funciones numéricas, de cadena, de fecha y conversión
sobre valores escalares. Una de estas funciones puede usarse colocándola en
la sintaxis de escape con la clave fn seguida del nombre de la función
deseada y sus argumentos. Por ejemplo, para llamar a la función concat con
dos argumentos que serán concatenados:
{fn
concat("Hot", "Java")};
El
nombre del usuario actual de la base de datos puede obtenerse mediante:
{fn
user()};
Las
funciones escalares pueden estar soportadas por diferentes DBMS con ligeras
diferencias de sintaxis, y pueden no estar disponibles en todos los drivers.
Varios métodos de DatabaseMetaData nos listarán las funciones que están
soportadas. Por ejemplo, el método getNumericFunctions devuelve una lista de
los nombres de las funciones numéricas separadas por comas, el método
getStringFunction nos devuelve los nombres de las funciones de cadena, y así
varías más.
EL
driver o bien mapeará la llamada a la función ‘escapada’ en su propia
sintaxis o implementará la función el mismo.
•
d, t y ts para literales de fecha y tiempo
Las
DBMS difieren en la sintaxis que usan para los literales de fecha, tiempo y
timestamp. JDBC soporta un formato estándar ISO para estos literales y usa
una cláusula de escape que el driver debe traducir a la representación del
DBMS.
Por
ejemplo, una fecha se especifica en SQL JDBC mediante la sintaxis:
{d
`yyyy-mm-dd'}
En
esta sintaxis, yyyy es el año, mm es el mes y dd es el día. El driver
reemplazará la cláusula de escape por la representación propia equivalente de
la DBMS. Por ejemplo, el driver reemplazaría {d 1999-02-28} por ’28-FEB-99’
si este es el formato apropiado para la base subyacente.
Hay
cláusulas de escape análogas para TIME y TIMESTAMP
{t
`hh:mm:ss'}
{ts `yyyy-mm-dd hh:mm:ss.f . . .'} La parte fraccional de los segundos (.f . . .) del TIMESTAMP puede omitirse.
•
call ó ? = call para procedimientos almacenados
Si
una database soporta procedimientos almacenados, estos pueden ser invocados
desde JDBC mediante:
{call
procedure_name[(?, ?, . . .)]}
o,
cuando el procedimiento devuelve como resultado un parámetro
{?
= call procedure_name[(?, ?, . . .)]}
Los
corchetes indican que el material encerrado en ellos es opcional. Estos no
forman parte de la sintaxis.
Los
argumentos de entrada pueden ser bien literales, bien parámetros. Ver la
sección 7 “CallableStatement” de esta guía.
Se
puede llamar al método DatabaseMetaData.supportsStoredProcedures para ver si
la base de datos soporta procedimientos almacenados.
•
oj para joins de salida
La
sintaxis para un outer join es:
{oj
outer-join}
donde
outer-join es de la forma:
table
LEFT OUTER JOIN {table | outer-join} ON search-condition
Las Outer joins son una característica avanzada, y solo puede chequearse la gramática SQL mediente una explicación de ella. JDBC provee tres métodos de DatabaseMetaData para determinar qué tipos de outer joins soporta un driver: supportsOuterJoins, supportsFullOuterJoins, y supportsLimitedOuterJoins. El método Statement.setEscapeProcessing activa o desactiva el procesamiento de escape. Por defecto la característica se encuentra activada. Un programador debería desactivar esta característica en tiempo de ejecución cuando el rendimiento ha de ser máximo, pero normalmente debe estar activado. Debería notarse que setEscapeProcesing no trabaja con objetos PreparedStatement por que la sentencia ya está preparada para enviar a la base de datos antes de poder ser llamada.
Uso del método execute
El
método execute debería usarse solamente cuando es posible que una sentencia
nos devuelva más de un objeto Resultset., más de un update count o una
combinación de ambos. Estas múltiples posibilidades para resultados, aunque
raras, son posibles cuando se ejecutan ciertos procedimientos almacenados o
por la ejecución dinámica de una string SQL desconocida (esto es, desconocida
para el programador de la aplicación en tiempo de compilación). Por ejemplo, una
usuario podría ejecutar un procedimiento almacenado (usando una objeto
CallableStatement y este procedimiento podría ejecutar una actualización,
después una select, luego una actualización, después una select y así.
Normalmente, alguien que usa un procedimiento almacenado sabrá que se le va a
devolver.
Porque
el método execute maneja los casos que se salen de lo ordinario, no sorprende
que los resultados devueltos requieren algún manejo especial. Por ejemplo,
supongamos que se sabe que el procedimiento devuelve dos result sets.
Después de usar el método execute para ejecutar el procedimiento, se debe llamar al método getResultSet para conseguir el primer result set y después los métodos apropiados getXXX para recuperar los valores de él. Para conseguir el segundo result set, se necesita llamar al método getMoreResults y y despues a getResultSet de nuevo. Si se sabe que el procedimiento devuelve dos upadte counts, se llama primero al método getUpdateCount, seguido de getMoreResults y de nuevo getUpdateCount.
Aquellos
casos en los que no se conoce que devolverá se nos presentan una situación
más compleja. El método execute devuelve true si el resultado es un objeto
ResultSet y false si es un int Java. Si devuelve un int, esto quiere decir
que el resultado o bien es un update count o que la sentencia que ha
ejecutado es un comando DDL. Lo primero que hay que hacer después de llamar
execute es llamar o bien a getResultSet o getUpdateCount. Al método
getResultSet se le llama para conseguir el primero de los dos o más objetos
ResultSet y al método getUpdateCount para conseguir el primero de dos o más
update counts.
Cuando
el resultado de una sentencia SQL no es un result set, el método getResultSet
devolverá null. Esto quiere decir que el resultado es un update count o que
no hay más resultados. La única manera de encontrar que significa el valor
null en este caso es llamar al método getUpdateCount, que devolverá un
entero. Este entero será el número de filas afectadas por la sentencia
ejecutada o –1 para indicar o bien que el resultado es un result set o bien
que no hay más resultados. Si el método getResultSet ya ha devuelto null, el
resultado no puede ser un objeto ResultSet, por lo que el valor devuelto de
–1 tiene que ser que no hay más resultados.
|
||||||||||||||||||
b) Los Connection, Statement y ResultSet con conexiones abiertas con base
de datos. Debemos cerrarlas.
ResultSet se
cierra solo cuando hacemos otra
llamada execute() al Statement del que obtuvimos
este ResultSet o bien cuando el recolector de basura
"recolecta" al ResultSet. No nos preocupa en principio que se
quede abierto, porque se acabará cerrando solo.
Eso
sí, no podemos hacer nada con el Statement hasta que hayamos
terminado con el ResultSet o se nos cerrará. Si necesitamos realizar
otra cosa con base de datos, debemos crear otro Statement distinto.
Cuando
terminemos con el Statement, lo cerramos con st.close().
Cuando
terminemos con la Connection, la cerramos con conexion.close().
MANIPULACIÓN DE LOS DATOS
DE UN RESULTSET EN JAVA
Algo
que no me agrada de la manipulación de datos SQL en Java es que
algunas cosas que son tan fáciles de realizar en .NET y otros lenguajes de
programación, no lo son en Java.
Un ejemplo sencillo de esto es el poder determinar la cantidad de filas que retorna una consulta SQL en un objeto ResultSet; en muchos foros de programación recomiendan el realizar nuevamente una consulta a la BD con un COUNT pero eso es algo que no me resulta muy funcional, especialmente en BD excesivamente grandes como las que manejo en la empresa (600Gb), piensen: "realizar otra consulta".
Después de un tiempo logré diseñar una solución que en realidad es muy simple; en Java existe una librería llamada java.util que contiene una clase List, la cual permite agregar objetos a la lista de forma dinámica (como ya saben en java los vectores son de longitud fija y por esta razón no podemos utilizarla ya que no sabemos la cantidad de filas retornadas), utilizando ésta Clase podemos implementar un método que consulte por ejemplo todos los Empleados de un Departamento X y que este método nos retorne un vector de tipo Empleado con todos los datos extraídos de la BD.
c) EJEMPLOS
Un ejemplo sencillo de esto es el poder determinar la cantidad de filas que retorna una consulta SQL en un objeto ResultSet; en muchos foros de programación recomiendan el realizar nuevamente una consulta a la BD con un COUNT pero eso es algo que no me resulta muy funcional, especialmente en BD excesivamente grandes como las que manejo en la empresa (600Gb), piensen: "realizar otra consulta".
Después de un tiempo logré diseñar una solución que en realidad es muy simple; en Java existe una librería llamada java.util que contiene una clase List, la cual permite agregar objetos a la lista de forma dinámica (como ya saben en java los vectores son de longitud fija y por esta razón no podemos utilizarla ya que no sabemos la cantidad de filas retornadas), utilizando ésta Clase podemos implementar un método que consulte por ejemplo todos los Empleados de un Departamento X y que este método nos retorne un vector de tipo Empleado con todos los datos extraídos de la BD.
c) EJEMPLOS
CONECCTION, STATEMENT Y
RESUELTSET:
package
ar.com.et3.lab8.ejercicio1.administrador;
import
java.sql.Connection;
import java.sql.DriverManager;
import java.sql.DriverManager;
/**
*
@author Martin
*/
public
abstract class AdministradorDeConexiones {
public AdministradorDeConexiones() {
}
public static Connection getConnection() throws Exception
{
// Establece el nombre del driver a utilizar
String dbDriver = "com.mysql.jdbc.Driver";
String dbDriver = "com.mysql.jdbc.Driver";
// Establece la conexion a utilizar contra la base de datos
String dbConnString = "jdbc:mysql://localhost/6to_ET3";
String dbConnString = "jdbc:mysql://localhost/6to_ET3";
// Establece el usuario de la base de datos
String dbUser = "root";
String dbUser = "root";
// Establece la contraseña de la base de datos
String dbPassword = "";
String dbPassword = "";
// Establece el driver de conexión
Class.forName(dbDriver).newInstance();
Class.forName(dbDriver).newInstance();
// Retorna la conexión
return DriverManager.getConnection(dbConnString, dbUser, dbPassword);
return DriverManager.getConnection(dbConnString, dbUser, dbPassword);
}
}
Como realizar una consulta
// Define la conexión
Connection laConexion = AdministradorDeConexiones.getConnection();
// Arma la consulta y la ejecuta
String laConsulta = "SELECT * FROM alumnos";
String laConsulta = "SELECT * FROM alumnos";
Statement stmtConsulta = laConexion.createStatement();
ResultSet rs = stmtConsulta.executeQuery(laConsulta);
ResultSet rs = stmtConsulta.executeQuery(laConsulta);
// Muestra los datos
while( rs.next() )
System.out.println( "ID: " + rs.getInt("alu_id") + " -- " + "Nombre: " + rs.getString("alu_nombre") + " -- " + "Apellido: " + rs.getString("alu_apellido") );
while( rs.next() )
System.out.println( "ID: " + rs.getInt("alu_id") + " -- " + "Nombre: " + rs.getString("alu_nombre") + " -- " + "Apellido: " + rs.getString("alu_apellido") );
// Cierra el Statement y la Connection
stmtConsulta.close();
laConexion.close();
stmtConsulta.close();
laConexion.close();
Como realizar una
inserción
// Define la conexión
Connection laConexion = AdministradorDeConexiones.getConnection();
// Arma la sentencia de inserción y la ejecuta
String laInsercion = "INSERT INTO alumnos (alu_id, alu_nombre, alu_apellido) VALUES (101, 'Manuel', 'Santos')";
String laInsercion = "INSERT INTO alumnos (alu_id, alu_nombre, alu_apellido) VALUES (101, 'Manuel', 'Santos')";
Statement stmtInsercion = laConexion.createStatement();
stmtInsercion.execute(laInsercion);
stmtInsercion.execute(laInsercion);
// Cierra el Statement y la Connection
stmtInsercion.close();
laConexion.close();
stmtInsercion.close();
laConexion.close();
// Informa que la inserción ha sido realizada con éxito
System.out.println("La inserción ha sido realizada con éxito...");
System.out.println("La inserción ha sido realizada con éxito...");
Como realizar una
actualización
// Define la conexión
Connection laConexion = AdministradorDeConexiones.getConnection();
// Arma la sentencia de actualización y la ejecuta
String laActualizacion = "UPDATE alumnos SET alu_apellido = 'Trobbiani' WHERE alu_id = 101";
String laActualizacion = "UPDATE alumnos SET alu_apellido = 'Trobbiani' WHERE alu_id = 101";
Statement stmtActualizacion = laConexion.createStatement();
stmtActualizacion.execute(laActualizacion);
stmtActualizacion.execute(laActualizacion);
// Cierra el Statement y la Connection
stmtActualizacion.close();
laConexion.close();
stmtActualizacion.close();
laConexion.close();
// Informa que la actualización ha sido realizada con éxito
System.out.println("La actualización ha sido realizada con éxito...");
System.out.println("La actualización ha sido realizada con éxito...");
Como realizar una
eliminación
// Define la conexión
Connection laConexion = AdministradorDeConexiones.getConnection();
// Arma la sentencia de eliminación y la ejecuta
String laEliminacion = "DELETE FROM alumnos WHERE alu_id = 101";
String laEliminacion = "DELETE FROM alumnos WHERE alu_id = 101";
Statement stmtEliminacion = laConexion.createStatement();
stmtEliminacion.execute(laEliminacion);
stmtEliminacion.execute(laEliminacion);
// Cierra el Statement y la Connection
stmtEliminacion.close();
laConexion.close();
stmtEliminacion.close();
laConexion.close();
// Informa que la eliminación ha sido realizada con éxito
System.out.println("La eliminación ha sido realizada con éxito...");
System.out.println("La eliminación ha sido realizada con éxito...");
Como tratar excepciones
con el manejo de base de datos
public static void main(String[] args) {
// Declara el objeto de conexión
Connection laConexion = null;
Connection laConexion = null;
try
{
// Obtiene la conexión
laConexion = AdministradorDeConexiones.getConnection();
{
// Obtiene la conexión
laConexion = AdministradorDeConexiones.getConnection();
// Muestra los alumnos en pantalla
mostrarAlumnos(laConexion);
} catch(Exception e) {
System.out.println( e.getMessage() );
} finally {
// Cierra la conexión
try
{
if(laConexion != null)
laConexion.close();
} catch(Exception e){}
}
}
mostrarAlumnos(laConexion);
} catch(Exception e) {
System.out.println( e.getMessage() );
} finally {
// Cierra la conexión
try
{
if(laConexion != null)
laConexion.close();
} catch(Exception e){}
}
}
public static void mostrarAlumnos(Connection conn) throws SQLException
{
{
Statement stmtAlumnos = null;
// Arma la sentencia SQL en forma de text
String consulta = "SELECT * FROM alumnos";
String consulta = "SELECT * FROM alumnos";
// Arma la sentencia SQL y la ejecuta
stmtAlumnos = conn.createStatement();
ResultSet rs = stmtAlumnos.executeQuery( consulta );
stmtAlumnos = conn.createStatement();
ResultSet rs = stmtAlumnos.executeQuery( consulta );
// Muestra los alumnos en pantalla
while(rs.next())
System.out.println( rs.getString("alu_nombre") + " -- " + rs.getString("alu_apellido") );
}
while(rs.next())
System.out.println( rs.getString("alu_nombre") + " -- " + rs.getString("alu_apellido") );
}
Utilización de transacciones
// Declara la conexión
Connection conn = null;
// Declara la conexión
Connection conn = null;
//Declara
los alumnos a insertar
Alumno a1 = new Alumno(“Juan”);
Alumno a2 = new Alumno(“Pedro”);
Alumno a3 = new Alumno(“Mario”);
Alumno a1 = new Alumno(“Juan”);
Alumno a2 = new Alumno(“Pedro”);
Alumno a3 = new Alumno(“Mario”);
try{
// Define la conexión
conn = AdministradorDeConexiones.getConnection();
// Define la conexión
conn = AdministradorDeConexiones.getConnection();
// Setea el auto-commit en falso
conn.setAutoCommit(false);
conn.setAutoCommit(false);
//Acá comienza la transacción
a1.insertar(conn);
a2.insertar(conn);
a3.insertar(conn);
a1.insertar(conn);
a2.insertar(conn);
a3.insertar(conn);
// Confirma los cambios
conn.commit();
} catch(Exception e) {
try{
// Vuelve atras los cambios
conn.rollback();
} catch(Exception ee){//Manejo de errores}
} finally{
try{
// Cierra la conexión
if( conn != null )
conn.close();
} catch(Exception e){//Manejo de errores }
conn.commit();
} catch(Exception e) {
try{
// Vuelve atras los cambios
conn.rollback();
} catch(Exception ee){//Manejo de errores}
} finally{
try{
// Cierra la conexión
if( conn != null )
conn.close();
} catch(Exception e){//Manejo de errores }
2.RESUMEN
JAVA CON BASE DE DATOS
CONTENIDO
DEFINICION
se
presenta como una colección de interfaces Java y métodos de gestión de manejadores de
conexión hacia cada modelo específico de base de datos. Un manejador de
conexiones hacia un modelo de base de datos en particular es un conjunto de
clases que implementan las interfaces Java y que utilizan los métodos de registro
para declarar los tipos de localizadores a base de datos (URL)
que pueden manejar. Para utilizar una base de datos particular, el usuario
ejecuta su programa junto con la biblioteca de conexión apropiada al modelo de
su base de datos, y accede a ella estableciendo una conexión; para ello provee
el localizador a la base de datos y los parámetros de conexión específicos.
El driver con la base de
datos
Lo
primero que necesitamos para conectarnos con una base de datos es
un Driver (o Connector) con ella. Ese Driver es la clase que, de
alguna forma, sabe cómo hablar con la base de datos. Desgraciadamente (y hasta
cierto punto es lógico), java no viene con todos los Drivers de todas las
posibles bases de datos del mercado. Debemos ir a internet y obtener el Driver,
normalmente en la página de nuestra base de datos
Para
el caso de MySQL, podemos descargarlo de. Nos bajamos
el mysql-connector-java-5.0.5.zip, lo desempaquetamos en algún sitio y nos
quedamos con el mysql-connector-java-5.0.5-bin.jar que viene dentro.
En ese jar está la clase Driver que nos interesa.
OBJETO CONNECTION
El
objeto Connection representa una conexión HTTP entre la prueba dinámica (el
cliente) y el servidor Web. La prueba abre la conexión, aunque tanto la prueba
como el servidor Web pueden cerrarla. Se pueden enviar múltiples solicitudes
mediante una sola conexión, siempre que esta última permanezca abierta.
Statement:
tiene
muchos métodos, pero hay dos interesentantes: executeUpdate() y executeQuery().
El primero se usa para sentencias SQL que impliquen modificaciones en la base
de datos (INSERT, UPDATE, DELETE, etc). El segundo sólo para consultas (SELECT
y similares).
Ejecución de sentencias
usando objetos Statement.
La
interfase Statement nos suministra tres métodos diferentes para ejecutar
sentencias SQL, executeQuery, executeUpdate y execute. El método a usar esta
determinado por el producto de la sentencia SQL
El
método executeQuery esta diseñado para sentencias que producen como resultado
un único result set tal como las sentencias SELECT.
El método executeUpdate se usa para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL (Data Definition Language) como CREATE TABLE o DROP TABLE. El efecto de una sentencia INSERT, UPDATE o DELETE es una modificación de una o más columnas en cero o más filas de una tabla. El valor devuelto de executeUpdate es un entero que indica el número de filas que han sido afectadas (referido como update count). Para sentencias tales como CREATE TABLE o DROP TABLE, que no operan sobre filas, le valor devuelto por executeUpdate es siempre cero.
El método executeUpdate se usa para ejecutar sentencias INSERT, UPDATE ó DELETE así como sentencias SQL DDL (Data Definition Language) como CREATE TABLE o DROP TABLE. El efecto de una sentencia INSERT, UPDATE o DELETE es una modificación de una o más columnas en cero o más filas de una tabla. El valor devuelto de executeUpdate es un entero que indica el número de filas que han sido afectadas (referido como update count). Para sentencias tales como CREATE TABLE o DROP TABLE, que no operan sobre filas, le valor devuelto por executeUpdate es siempre cero.
Realización de Statement
Cuando una conexión está en modo auto-commit, las sentencias ejecutadas son ‘comitadas’ o rechazadas cuando se completan. Un sentencia se considera completa cuando ha sido ejecutada y se han devuelto todos los resultados. Pare el método executeQuery, que devuelve un único result set, la sentencia se completa cuando todas las filas del objeto ResultSet se han devuelto. Para el método executeUpdate, un sentencia se completa cuando se ejecuta.
Cuando una conexión está en modo auto-commit, las sentencias ejecutadas son ‘comitadas’ o rechazadas cuando se completan. Un sentencia se considera completa cuando ha sido ejecutada y se han devuelto todos los resultados. Pare el método executeQuery, que devuelve un único result set, la sentencia se completa cuando todas las filas del objeto ResultSet se han devuelto. Para el método executeUpdate, un sentencia se completa cuando se ejecuta.
Sintaxis de Escape SQL en
objetos Statement
Los
objetos Statement pueden contener sentencias SQL que usen sintaxis de escape
SQL. La sintaxis de escape señala al driver que el código que lleva debe ser
tratado diferentemente. El driver buscará por cualquier sintaxis de escape y lo
traducirá en código que entiende la base de datos en particular.
Uso del método execute
El
método execute debería usarse solamente cuando es posible que una sentencia nos
devuelva más de un objeto Resultset., mas de un update count o una combinación
de ambos. Estas múltiples posibilidades para resultados, aunque raras, son
posibles cuando se ejecutan ciertos procedimientos almacenados o por la
ejecución dinámica de una string SQL desconocida (esto es, desconocida para el
programador de la aplicación en tiempo de compilación). Por ejemplo, una
usuario podría ejecutar un procedimiento almacenado (usando una objeto
CallableStatement y este procedimiento podría ejecutar una actualización,
después una select, luego una actualización, después una select y así.
Normalmente, alguien que usa un procedimiento almacenado sabrá que se le va a
devolver.
Los Connection, Statement y ResultSet con conexiones abiertas con base
de datos. Debemos cerrarlas.
ResultSet se
cierra solo cuando hacemos otra
llamada execute() al Statement del que obtuvimos
este ResultSet o bien cuando el recolector de basura
"recolecta" al ResultSet. No nos preocupa en principio que se
quede abierto, porque se acabará cerrando solo.
MANIPULACIÓN DE LOS DATOS
DE UN RESULTSET EN JAVA
Algo
que no me agrada de la manipulación de datos SQL en Java es que
algunas cosas que son tan fáciles de realizar en .NET y otros lenguajes de
programación, no lo son en Java.
Un ejemplo sencillo de esto es el poder determinar la cantidad de filas que retorna una consulta SQLen un objeto ResultSet; en muchos foros de programación recomiendan el realizar nuevamente una consulta a la BD con un COUNT pero eso es algo que no me resulta muy funcional, especialmente en BD excesivamente grandes como las que manejo en la empresa (600Gb), piensen: "realizar otra consulta".
Un ejemplo sencillo de esto es el poder determinar la cantidad de filas que retorna una consulta SQLen un objeto ResultSet; en muchos foros de programación recomiendan el realizar nuevamente una consulta a la BD con un COUNT pero eso es algo que no me resulta muy funcional, especialmente en BD excesivamente grandes como las que manejo en la empresa (600Gb), piensen: "realizar otra consulta".
3. SUMMARY
DATABASE WITH JAVA
CONTENT
DEFINITION
It
is presented as a collection of Java management methods handlers connection to
each specific database model and interfaces. A connection handle to a database
model in particular is a set of classes that implement the Java interfaces and
registration methods used to declare the types of locators to database (URL)
they can handle. To use a particular database, the user runs the program along
with the appropriate connection library to model your database and accessed by
establishing a connection; for it provides the locator to the database and
specific connection parameters.
The
driver with the database
The
first thing you need to connect to a database is a Driver (or Connector) with
it. This Driver is the class that, somehow, knows how to talk to the database.
Unfortunately (and to some extent of course), java does not come with all
Drivers of all possible databases on the market. We must go online and get the
Driver, usually on page our database
In
the case of MySQL, we can download it. We got off the
mysql-connector-java-5.0.5.zip, unpack somewhere and we are left with the
mysql-connector-java-5.0.5-bin.jar coming inside. In the Driver jar is the
class that interests us.
OBJECT
CONNECTION
The
Connection object represents an HTTP connection between the dynamics (the
client) and Web server test. The test opens the connection, although both the
test and the Web server can close it. You can send multiple requests through a
single connection, provided that the latter remains open.
Statement:
has
many methods, but two interesentantes: executeUpdate () and executeQuery ().
The former is used for SQL statements that involve modifications to the
database (INSERT, UPDATE, DELETE, etc). The second only for queries (SELECT and
the like).
Execution
of sentences using Statement objects.
The
Statement interface provides us three different methods to execute SQL
statements, executeQuery, executeUpdate and execute judgments. The method used
is determined by the product of the SQL statement
The
method executeQuery is designed for statements that produce results in a single
result set as SELECT statements.
The
method executeUpdate is used to execute INSERT, UPDATE, or DELETE SQL
statements and DDL (Data Definition Language) as CREATE TABLE or DROP TABLE.
The effect of an INSERT, UPDATE, or DELETE statement is a modification of one
or more columns in zero or more rows from a table. The return value of
executeUpdate is an integer indicating the number of rows that have been
affected (referred to as update count). For statements such as CREATE TABLE or
DROP TABLE, which do not operate on rows, you executeUpdate return value is
always zero.
Making
Statement
When
a connection is in auto-commit mode, the statements executed are 'comitadas' or
rejected when they are completed. A statement is considered complete when it
has been executed and all results have been returned. Stop executeQuery method,
which returns a single result set, the statement is complete when all rows have
been returned ResultSet object. For the executeUpdate method, a statement
completes when running.
SQL
Escape Syntax in Statement Objects
Statement
objects may contain SQL statements that use SQL escape syntax. The escape
syntax signals the driver that the code that bears should be treated
differently. The driver will search for any escape syntax and translate into
code that understands the particular database.
Using
the execute method
The
execute method should only be used when a sentence may return us a Resultset
object., More than one update count or a combination of both. These multiple
possibilities for results, although rare, are possible when certain stored
procedures run or execute a dynamic SQL string unknown (that is, unknown to the
application programmer at compile time). For example, a user could execute a
stored procedure (using a CallableStatement object and this procedure could
execute an update, then a select, then an update, then a select and well.
Normally, someone using a stored procedure will know that it will to return.
The
Connection, Statement and ResultSet with open database connections. We must
close them.
ResultSet
is closed only when we make another execute () call to the Statement of we got
this ResultSet or when the garbage collector "collects" the
ResultSet. We are not concerned in principle it stays open, because you end up
closing alone.
DATA
HANDLING IN JAVA A RESULTSET
Something
I do not like the SQL data manipulation in Java is that some things are so easy
to make .NET and other programming languages are not in Java.
A
simple example of this is the power to determine the number of rows that a
query returns a ResultSet object SQLen; in many programming forums recommend a
query to the database again with a COUNT but that's something I is not very
functional, especially in excessively large BD as those management in the
company (600GB), think: "make another query”.
4. RECOMENDACIONES
Principalmente
vemos la necesidad de conocer cada día más el entorno de las bases de datos.
Aprender de manera didáctica y autodidactica con mayor dedicación.
Es
necesario conocer que la implementación del código debe estar bien estructurado
para evitar algunas redundancias innecesarias.
Conocer
las especificaciones que nos presenta cuando estructuramos las tablas de cada
base de datos, realizando nuestro trabajo más práctico y sencillo.
5. CONCLUSIÓN
A
través del desarrollo de las prácticas en laboratorio he conocido las ventajas
de las bases de datos que se superponen a los sistemas de archivos del pasado,
como sabemos todo evoluciona es así como el modelo relacional que
implementa SQL, nos da una excelente herramienta en la administración,
seguridad y fiabilidad de los datos.
Por
lo tanto se sabe que conocer el proceso interno, la estructura he
implementación de base de datos nos muestra la importancia que realizan en el
mundo laboral, y como cada ente que las utiliza es dependiente de ellas.
6. APRECIACIÓN DEL GRUPO
A
través de Java con la conexión con Base de Datos es una forma más sencilla y
sutil de crear programas más seguros y de mejor calidad utilizando así los
interfaces más comunes como son: Statement, Conecction y Resueltet.
7. GLOSARIO
1. Análogo: Que tiene analogía con otra cosa.
2. Contenedor: Cajón metálico, de gran tamaño, con las
dimensiones normalizadas internacionalmente, usado para el transporte de
mercancías.
3. Sintaxis: Forma correcta en que deben estar
dispuestos los símbolos que componen una instrucción ejecutable por el
ordenador.
4. Cláusula: Oración o proposición gramatical,
conjunto de palabras con sentido completo.
5. Didáctica: Área de la pedagogía que se ocupa de
las técnicas y métodos de enseñanza.
6. Redundancia: Repetición inútil de un concepto.
8. BIBLIOGRAFÍA O
LINOGRAFÍA
9. LINK DE DIAPOSITIVAS
DONDE PUEDE ENCONTRAR MAYOR INFORMACIÓN
http://es.slideshare.net/MagalyPortocarreroLa