Apunts de Java

El framework iBatis DataMapper (també conegut com SQL a Maps) permet reduir significativament la codificació en
java per a una aplicació que fa servir base de dades relacional.
Potser la primera impressió que un tingui és que sigui a igual a Hibernate (que és un mapeador d’objectes amb taules a relacionals – ORM). IBATIS és diferent. Com veurem en aquest
tutor, iBatis mapeja les consultes SQL i permet interactuarlas amb
JavaBeans tant com a paràmetres d’entrada i com a sortides.

a

Som-hi

Per començar, obtindrem el framework de la pàgina de contracte ASF: http://ibatis.apache.org/
l’arxiu que haurem baixat (iBATIS_DBL-2.1.7.XX.zip ) contindrà
tres arxius .jar. En aquest tutor només farem servir iBATIS-common-2.jar i Serveis iBATIS-sqlmap-2.jar. No necessita d’algun altre .jar, al menys a per a aquest capítol.

a

Definint l’estructura de les dades

a

Crearem el nostre JavaBean Categoria amb la
següent estructura.

a

package com.jugperu.tutores.ibatis.beans;
public class Categoria {
private int id; // podemos utilizar tipos de datos nativos
private String nombre;
/*... poner sus respectivos métodos
setXX() y getXX() para que tenga el
patrón JavaBean (value object)*/
}

a També necessitem crear la nostra base de dades. Podem fer servir a qualsevol motor; naturalment necessitarem el seu respectiu driver.

a

Crearem la nostra taula CATEGORIA, la qual tindrà la qual següent estructura:

a

a

a

a

a

a

a

a

a

a

a

a

a

a

a

a

a

a

Nom

a

a

Tipus

a

a

CAT_ID

a

a

Autonumèric (clau principal)

a

a

CAT_NOMBRE

a

a

varchar (30)

a

a

Com es pot veure, hem posat noms de camps diferents a les Obres propietats del nostre JavaBean. Veurem com en iBatis podrem
associar cada columna amb la seva respectiva propietat en els objectes.

a

Configuració de la connexió a la base de datosdesde la nostra aplicació

a

crearem l’arxiu database.properties dins el paquet a com.jugperu.tutores.ibatis.resources el qual tindrà els
següents valors:

a

#el driver de nuestra base de datos
jdbc.driver=org.hsqldb.jdbcDriver
#el url para nuestra conexion.
jdbc.url=jdbc:hsqldb:file:data/productos.hsqldb
#el usuario
jdbc.username=sa
#y la contraseña
jdbc.password=

a Crearem l’arxiu SqlMapConfig.xml que tindrà el contracte següent contingut:

a

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource="com/jugperu/tutores/ibatis/resources/database.properties"/>
<transactionManager type="JDBC">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="${jdbc.driver}"/>
<property name="JDBC.ConnectionURL" value="${jdbc.url}"/>
<property name="JDBC.Username" value="${jdbc.username}"/>
<property name="JDBC.Password" value="${jdbc.password}"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/jugperu/tutores/ibatis/resources/Almacen.xml"/>
</sqlMapConfig>

a l’atribut “resource “de l’element” properties “a ha d’apuntar a la ubicació de l’arxiu .properties qual acabem de crear. Ha d’estar en posició relativa a les nostres a classes. Si volem utilitzar una ubicació que estigui a fora de l’abast de l’aplicació, utilitzarem l’atribut a “url”.

a

 <properties url="file://c:/proyecto/database.properties"/>

Veiem que les propietats de les connexió (elements < property a / >) utilitza variables com $ {jdbc.driver} . Això és perquè a utilitzeu els valors nostre arxiu de database.properties. L’arxiu SqlMapConfig.xml només a pot utilitzar un fitxer .properties per a aquests casos.

a

El element < sqlMap / > apunta a un arxiu de Almacen.xml. Aquest arxiu el descriurem a continuació.
a l’igual que l’element < properties / > es pot
especificar un uRL per apuntar a un recurs que es trobi fora Resolució de l’ abast de l’aplicació.

a

Els altres elements d’aquest .xml el detallarem en el títol següent capítol.

a

Definint el mapa de co nsultas.

a

Crearem l’arxiu Almacen.xml dins el paquet a com.jugperu.tutores.ibatis.resources el qual tindrà el Real següent contingut

a

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="almacen">
<typeAlias type="com.jugperu.tutores.ibatis.beans.Categoria" alias="categoria"/>
<insert parameterClass="categoria">
insert into CATEGORIA
(cat_nombre)
values (#nombre#)
</insert>
<select resultClass="categoria" parameterClass="int">
select cat_id as id, cat_nombre as nombre
from categoria
where cat_id=#value#
</select>
</sqlMap>

a Detallarem el contingut d’aquest .xml:

a

l’element < typeAlias / > ens permetrà a descriure un àlies per evitar escriure un nom classe llarg. En venda aquest cas, en comptes d’escriure a “com.jugperu.tutores.ibatis.beans.Categoria” a farem servir “categoria”

a

Veiem que té elements que es poden associar ràpidament ajudes a les sentències SQL. Tots aquests elements tenen l’atribut “id”.
Aquest ens permetrà identificar a cada un d’ells.
Detallarem l’estructura de cada un:

 <insert parameterClass="categoria">
insert into CATEGORIA
(cat_nombre)
values (#nombre#)
</insert>

Aquest element rep com a paràmetre un objecte el tipus està a definit en l’atribut “resultClass”. com el nom a complet de la nostra classe és ben llarg, hem definit un àlies amb
l’element < typeAlias / >. Per tant, el tipus de l’
paràmetre és com.jugperu.tutores.ibatis.beans.Categoria.

a

la comanda INSERT ha de guardar relació amb la sintaxi de l’
motor que estem fent servir.Els valors tancats en signes numerals Estadístiques (#) fan referència a les propietats de l’objecte rebut com a paràmetre.

a

L’element < select > rep com a paràmetre un contracte valor numèric “int” i retorna retorna un objecte a de tipus “categoria”. El paràmetre “int” a és un àlies per defecte de la classe java.lang.Integer. Per a tant, a l’invocar aquesta sentència SQL passarem com a paràmetre a un objecte Integer.

a

 <select resultClass="categoria" parameterClass="int">
select cat_id as id, cat_nombre as nombre
from categoria
where cat_id=#value#
</select>

Xalet En aquest element té una sentència SQL on els camps que són a seleccionats tenen un àlies. És a dir, el camp CAT_ID té com a àlies “id”, i CAT_NOMBRE té com a àlies “nom”.
d’aquesta manera iBatis col·locarà cada camp de la taula salarial resultant i els col·locarà en les seves respectives propietats de l’per objecte a tornar.

programa de prova

a

La millor manera de fer un programa de prova és utilitzant un contracte testcase en JUnit. Crearem el nostre testCase a cridant IbatisMapsTestCase i tindrà el següent
mètode sETUP ().

a

 Reader reader = Resources.getResourceAsReader("SqlMapConfig.xml");
// el .xml para la conexión
sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
//construye el manejador de llamadas al iBatis

a Crearem el nostre test per registrar objectes Categories.

a

 public void testInsertarCategorias() throws SQLException {
try {
sqlMap.startTransaction();
Categoria c1 = new Categoria();
Categoria c2 = new Categoria();
Categoria c3 = new Categoria();
c1.setNombre("memorias");
c2.setNombre("placas");
c3.setNombre("procesadores");
sqlMap.insert("insertCategoria", c1);
sqlMap.insert("insertCategoria", c2);
sqlMap.insert("insertCategoria", c3);
sqlMap.commitTransaction();
} catch (SQLException ex) {
ex.printStackTrace();
assertTrue(false);
} finally {
sqlMap.endTransaction();
}
}

a També farem un test per obtenir un objecte.

a

 public void testGetCategoriaPorId() throws SQLException {
try {
sqlMap.startTransaction();
Categoria c1 = (Categoria) sqlMap.queryForObject(
"getCategoriaPorId", Integer.valueOf(2));
assertNotNull(c1);
mostrar(c1);
} catch (SQLException ex) {
ex.printStackTrace();
assertTrue(false);
} finally {
sqlMap.endTransaction();
}
}
private static void mostrar(Categoria cat) {
System.out.println(cat.getId() + "\t" + cat.getNombre());
}

Claus autogenerades

a

El mètode “insert” de sqlMap retorna un objecte a que conté el valor de la nova clau generada (si aplica). Però a Madrid el nostre exemple el valor que retorna és null, tot qual hem declarat que la clau primària és autonumérica. iBatis a mai sabrà quin és el valor llevat que posem en la qual sentència sql quin valor ha de tornar.

a

Editem Almacen.xml en el títol element < insert > de manera que llueixi de la següent
manera.

a

...
<insert parameterClass="categoria">
insert into CATEGORIA
(cat_nombre)
values (#nombre#)
<selectKey resultClass="int">
select distinct identity() as id
from categoria
</selectKey>
</insert>
...

Aquesta és la sentència per HSQLDB, que és el motor usat en aquest
exemple. Per MySQL la comanda SQL que està dins de
< selectKey > hauria de ser: a

a

...
<selectKey resultClass="int">
select last_insert_id() as id
</selectKey>
...

Cultura i per SQL Server:

a

...
<selectKey resultClass="int">
select @@IDENTITY as ID
</selectKey>
...

Manejant resultats

a

Definint mapa de resultats

a

Hem vist que per associar tots els camps d’una consulta a
les propietats de l’JavaBean, cadascun d’aquests ha de tenir un alies.
La qual cosa ens pot ser un gran problema, ja que si es tractés d’a diversos camps, hauríem de posar diversos “as” a per cada un. I si fossin diverses sentències SQL, també ens
pot resulta problemàtic fer una modificació.

a

iBatis ens permet crear un mapa de resultat. Allà a podrem definir l’associació que farem servir entre
propietats de l’objecte i camps de la consulta.

a

Per a això afegirem el següent element en Almacen.xml

a

 <resultMap class="categoria">
<result property="id" column="cat_id"/>
<result property="nombre" column="cat_nombre"/>
</resultMap>

a Cada vegada que utilitzem com respues ta “res-categoria”, per iBatis s’encarregarà de crear una instància de “categoria” Cultura i col·locarà en cada propietat els valors de cada columna qual s’utilitzi.

a

Agregarem una consulta nova:

a

 <select resultMap="res-categoria">
select *
from categoria
</select>

a Com es pot veure, ja no cal col·locar un àlies per cada
camp.

a

I crearem un nou test per provar-:

a

 List lista = sqlMap.queryForList("getAllCategoria", null);
for (Iterator iter = lista.iterator(); iter.hasNext(); ) {
Categoria cat = (Categoria) iter.next();
mostrar(cat);
}

Resultats sense JavaBeans

No necessàriament utilitzarem un JavaBean per obtenir un contracte resultat. Podem utilitzar un java.util.HashMap per obtenir a tots els camps d’una consulta. Cada key serà el contracte nom de camp, i el seu respectiu value serà el valor a associat.

a

 <resultMap class="java.util.HashMap">
<result property="id" column="cat_id"/>
<result property="nombre" column="cat_nombre"/>
</resultMap>
...
<select resultMap="res-map-categoria">
select *
from categoria
where cat_id=#value#
</select>

a L’objecte retornat per queryForObject () serà de classe a java.util.HashMap.

a

 HashMap map = (HashMap) sqlMap.queryForObject(
"getMapCategoriaPorId", Integer.valueOf(1));

a per tant, podríem construir una consulta amb diversos
camps sense preocupar-nos per l’estructura que va a tornar.

a

També podem obtenir només un camp en una llista.

a

 <resultMap class="java.lang.String">
<result property="nombre" column="cat_nombre"/>
</resultMap>
...
<select resultMap="res-categoria-nombre">
select *
from categoria
</select>

a I cada objecte de la llista obtinguda de queryForList () serà a 1 java.lang.String.

a

 List lista = sqlMap.queryForList("getNombresCategoria", null);

a Naturalment, podríem crear una consulta que tingui com a resultMap un objecte HashMap i invocar-lo amb a queryForList (). El resultat serà una llista on cada
element serà un hashmap.

a

Manejant paràmetres

a

iBatis també permet definir els paràmetres qual van a rebre les consultes. La seva estructura és molt similar als Serveis resultMaps.

a

 <parameterMap class="categoria">
<parameter property="id"/>
<parameter property="nombre"/>
</parameterMap>
//......
<update parameterMap="par-categoria">
update categoria
set cat_nombre=#nombre#
where cat_id=#id#
</update>

a També podem prescindir d’un JavaBean per enviar a paràmetres. Per a això utilitzarem un java.util.Map.
Cada key s’accedirà com si fos una propietat d’un contracte JavaBean.

a

 <update parameterClass="java.util.Map">
update categoria
set cat_nombre=#nombre#
where cat_id=#id#
</update>

Associacions

a

Un dels principals problemes de l’ús de base de dades a relacionals utilitzant objectes és l’associació entre taules.

Crearemos una tabla Producte con la siguiente estructura:

Campo

tipo

pr_id

Autonumérico (Clave Principal)

PR_NOMBRE

varchar (30)

pr_precio

decimal

pr_stock

numérico entero

PR_CATEGORIA

numérico no nulo (clave foránea de categoria)

Crearemos el javabean amb respectacions respectives Propiedades:

package com.jugperu.tutores.ibatis.beans;
public class Producto {
private int id;
private String nombre;
private int stock;
private double precio;
private Categoria categoria;
//.....
}

Agregando Un registro

Crearemos un Insereix > Para manejar la inserció – de Objetos a la tabla.

 <typeAlias type="com.jugperu.tutores.ibatis.beans.Producto" alias="producto"/>
//...
<insert parameterClass="producto">
insert into producto
(pr_nombre,pr_stock,pr_precio,pr_categoria)
values (#nombre#,#stock#,#precio#,#categoria.id#)
</insert>

Nota Cómo se Accedeix a una propedad de producte
que es de Clase categoria. En caso que la propedad
categoria fuera nulo, ibatis toma toda la expressió
(categoria.id) como nulo.

Probamos insístriu un objeto producte:

 Categoria cat = (Categoria) sqlMap.queryForObject(
"getCategoriaPorId", Integer.valueOf(1));
Producto p1 = new Producto();
p1.setNombre("Kingston");
p1.setPrecio(300.50);
p1.setStock(5);
p1.setCategoria(cat);
sqlMap.insert("insertProducto", p1);

ES necesario Recalcar que ibatis no agrega autáticamente los
Objetos asociados que no existan en la base de dades. Es decir, Sie
Crea Un Objeto Categoria Y se Asocia a un nou Objeto de
Producte, Al Hacer El Inser () Solo Se Guardarán
Los Valores del Objeto Producte y No Los del Objeto Categoria.

Obteniendo un registro

para obtener un registrador mapeado en
objeto, al < resultant

se Agregará un atributo
más:

 <resultMap class="producto">
<result property="id" column="pr_id"/>
<result property="nombre" column="pr_nombre"/>
<result property="stock" column="pr_stock"/>
<result property="precio" column="pr_precio"/>
<result property="categoria" column="pr_categoria" select="getCategoriaPorId"/>
</resultMap>

Como se ve, para la propedad Categoria SE TOMARÁ ELS CAMPO PR_CATEGORIA Y SE BUSCARÁ SUAL VALOR DEL SELECCIONA GETCATEGORIAPORID. Al Hacer Esto, SE Invocará a Dicho
Select Y se Le Pasará Como Parámetro El Valor de
PR_Categoria Obtenoendo El Objeto Corportient.

El select para obtener objetos de
producte SERÀ MUY SIMPLE:

 <select resultMap="res-producto">
select *
from producto
where pr_id=#value#
</select>

y la llamada desde java será la misma que SE HA estado
maneig:

 Producto p = (Producto) sqlMap.queryForObject("getProductoPorId",
Integer.valueOf(1));
mostrar(p); //muestra cada campo del objeto "p”
//.....
private static void mostrar(Producto p) {
System.out.println(p.getId() + "\t" + p.getNombre() + "\t" +
p.getPrecio() + "\t" + p.getStock() + "(" +
p.getCategoria().getNombre() + ")");
}

Pero Esta Solución Tiene una deficiencia: para obtener Un
producte, Ibatis Hará dos Consultes: Uno para el producto y
Otro para la categoría. SI Fueran Varios Productos, Hará
UNA CONSULTA PER LOS PRODUCTOS Y N CONSULTAS PER CADA PRODUCTOR PARA
Obtener Su Categoria.

Esto Se Puede Solucionar haciendo Un Join Modificando El
< resulta >.

 <resultMap class="producto">
<result property="id" column="pr_id"/>
<result property="nombre" column="pr_nombre"/>
<result property="stock" column="pr_stock"/>
<result property="precio" column="pr_precio"/>
<result property="categoria.id" column="pr_categoria"/>
<result property="categoria.nombre" column="cat_nombre"/>
</resultMap>
....
<select resultMap="res-producto-opt">
select *
from producto p, categoria c
where p.pr_categoria=c.cat_id
</select>

Conclusions

Con ibatis se puede Mapear Las Consultes Que Necesitamos para
Nuestro Proyecto. La Sintaxis Que se Utilice para manejar Los
Registros de la base de dades Está Fuertemente aislada en la
Lógica de Negocio. Esto nos permite Tener Un Código
Limpio de Sentencias SQL. SI ES NECESARIO HACER ALGUNA MODIFICACIÓN
en SQL, Bastará amb EDITAR EL XML Y NO UNA CLASE EN JAVA
Evitació La Complación d’Esta.

Leave a Comment

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *