Con el mapeo objeto relacional
declaramos en que tablas y columnas de nuestra base de datos relacional se
guarda la información de nuestro componente.
Para los que estén familiarizado con herramientas O/R decir que esta
información se usa para generar el código y archivos xml necesarios para
el mapeo. Actualmente se genera código para:
- Hibernate 3.x.
- EntityBeans CMP 2 de JBoss 3.2.x y 4.0.x.
- EntityBeans CMP 2 de Websphere 5, 5.1 y 6.
Para los que no estén familiarizados con herramientas O/R decir que una
herramienta de este tipo nos permite trabajar con objetos, en vez de con
tablas y columnas y genera automáticamente el código SQL necesario para
leer y actualizar la base de datos.
OpenXava genera un conjunto de clases java que representa la capa del
modelo de nuestra aplicación (los conceptos de negocio con sus datos y
funcionalidad). Nosotros podemos usar estos objetos directamente sin
necesidad de acceder directamente a la base de datos con SQL, pero para
eso tenemos que definir con precisión como se mapean nuestras clases a
nuestras tablas, y eso es lo que se hace en la parte del mapeo.
Mapeo
de entidad
La sintaxis para mapear la entidad principal es:
<mapeo-entidad tabla="tabla"> <!-- 1 -->
<mapeo-propiedad ... /> ... <!-- 2 -->
<mapeo-referencia ... /> ... <!-- 3 -->
<mapeo-propiedad-multiple ... /> ... <!-- 4 -->
</mapeo-entidad>
- tabla (obligado): Para relacionar la entidad
principal del componente con esa tabla.
- mapeo-propiedad (varios, opcional): Mapea una
propiedad con una columna de la tabla de base de datos.
- mapeo-referencia (varios, opcional): Mapea una
referencia con una o más columna de la tabla de base de datos.
- mapeo-propiedad-multiple (varios, opcional): Mapea
una propiedad con varias columnas de la tabla de base de datos. Para
cuando propiedad corresponde a varias columnas.
Un ejemplo sencillo de mapeo puede ser:
<mapeo-entidad tabla="XAVATEST@separator@TIPOALBARAN">
<mapeo-propiedad propiedad-modelo="codigo" columna-tabla="CODIGO"/>
<mapeo-propiedad propiedad-modelo="descripcion" columna-tabla="DESCRIPCION" />
</mapeo-entidad>
Nada más fácil.
Vemos como en el nombre de tabla la ponemos calificada (con el nombre de
colección/esquema delante). También vemos que como separador en lugar de
un punto ponermos @separator@, esto es útil porque podemos dar valor a
separator en nuestro
build.xml y así una misma aplicación puede
ir contra bases de datos que soportan y no soportan las colecciones o
esquemas.
Mapeo
propiedad
La sintaxis para mapear una propiedad es:
<mapeo-propiedad
propiedad-modelo="propiedad" <!-- 1 -->
columna-tabla="columna" <!-- 2 -->
tipo-cmp="tipo" <!-- 3 -->
formula="formula"> <!-- 4 New in v3.1.4 -->
<conversor ... /> <!-- 5 -->
</mapeo-propiedad>
- propiedad-modelo (obligada): El nombre de una
propiedad definida en la parte del modelo.
- columna-tabla (opcional desde v3.1.4):
Nombre de la columna de la tabla. Si se omite se asume el nombre de la
propiedad.
- tipo-cmp (opcional): Indica el tipo Java que usará
internamente nuestro objeto para guardar la propiedad. Esto nos
permite usar tipos Java más cercanos a lo que tenemos en la base de
datos sin ensuciar nuestro modelo. Se suele usar en combinación con un
conversor.
- formula (opcional): (Nuevo en v3.1.4)
Para calcular el valor de la propiedad usando la base de datos. Tiene
que ser un fragmento válido de SQL. No funciona con EntityBeans CMP2.
- conversor (uno, opcional): Permite indicar nuestra
propia lógica para convertir del tipo usado en Java al tipo de la db.
Hemos visto ya ejemplos de un mapeo sencillo de propiedad con columna. Un
caso más avanzado sería el uso de un conversor. Un conversor se usa cuando
el tipo de Java y el tipo de la base de datos no coincide, en ese caso
usar un conversor es una buena idea. Por ejemplo supongamos que en la base
de datos el código postal es de tipo VARCHAR mientras que en Java nos
interesa que sea un
int. Un
int de Java no se puede
asignar directamente a una columna VARCHAR de base de datos, pero podemos
poner un conversor para convertir ese int en un
String. Veamos:
<mapeo-propiedad
propiedad-modelo="codigoPostal"
columna-tabla="CP"
tipo-cmp="String">
<conversor clase="org.openxava.converters.IntegerStringConverter"/>
</mapeo-propiedad>
Con
tipo-cmp indicamos el tipo al que convertirá nuestro
conversor y es el tipo que tendrá el atributo interno de la clase
generada, ha de ser un tipo cercano (asignable directamente con JDBC) al
de la columna de la tabla.
El código del conversor será:
package org.openxava.converters;
/**
* In java an int and in database a String.
*
* @author Javier Paniza
*/
public class IntegerStringConverter implements IConverter { // 1
private final static Integer ZERO = new Integer(0);
public Object toDB(Object o) throws ConversionException { // 2
return o==null?"0":o.toString();
}
public Object toJava(Object o) throws ConversionException { // 3
if (o == null) return ZERO;
if (!(o instanceof String)) {
throw new ConversionException("conversion_java_string_expected");
}
try {
return new Integer((String) o);
}
catch (Exception ex) {
ex.printStackTrace();
throw new ConversionException("conversion_error");
}
}
}
Un conversor ha de implementar
IConverter (1), esto le obliga a tener un
método
toDB() (2), que recibe el objeto del tipo que usamos en
Java (en este caso un Integer) y devuelve su representación con otro tipo
más cercano a la base de datos (en este caso
String y por ende
asignable a una columna VARCHAR). El método toJava() tiene el cómetido
contrario, coge el objeto en el formato de la base de datos y tiene que
devolver un objeto del tipo que se usa en Java.
Ante cualquier problemas podemos lanzar una
ConversionException.
Vemos como este conversor está en
org.openxava.converters, es
decir es un conversor genérico que viene incluido en la distribución de
OpenXava. Otro conversor genérico bastante útil es
ValidValuesLetterConverter,
que permite mapear las propiedades de tipo valores-posibles. Por ejemplo
podemos tener una propiedad como ésta:
<entidad>
...
<propiedad nombre="distancia">
<valores-posibles>
<valor-posible valor="local"/>
<valor-posible valor="nacional"/>
<valor-posible valor="internacional"/>
</valores-posibles>
</propiedad>
...
</entidad>
Los valores-posibles generan una propiedad Java de tipo
int
donde el 0 se usa para indicar un valor vacío, el 1 será 'local', el 2
'nacional' y el 3 'internacional'. ¿Pero que ocurre si en la base de datos
se almacena una L para local, una N para nacional y una I para
internacional? Podemos hacer lo siguiente en el mapeo:
<mapeo-propiedad
propiedad-modelo="distancia" columna-tabla="DISTANCIA" tipo-cmp="String">
<conversor clase="org.openxava.converters.ValidValuesLetterConverter">
<poner propiedad="letters" valor="LNI"/>
</conversor>
</mapeo-propiedad>
Al poner 'LNI' como valor para letters, hace corresponder la L con 1, la N
con 2 y la I con 3. Vemos como el que se puedan configurar propiedades del
conversor (como se hacía con los calculadores, validadores, etc) nos
permite hacer conversores reutilizables.
Usando el atributo
formula (nuevo en v3.1.4) podemos definir un
cálculo para nuestra propiedad. Este cálculo se expresa usando SQL, y es
ejecutado en la propia base de datos, en vez de por Java. Simplemente
hemos de escribir un fragmento válido de SQL:
<mapeo-propiedad propiedad-modelo="precioUnitarioConIVA" formula="PRECIOUNITARIO * 1.16"/>
El uso es simple. Hemos de poner el cálculo como lo hariamos si lo
tuvieramos que poner en una sentencia SQL.
Las propiedades con
formula son propiedades de solo lectura.
Cuando el objeto es leído de la base de datos se hace el cálculo por la
misma base de datos y se rellena la propiedad con el resultado.
Esto es una alternativa a las propiedades calculadas. Tiene la ventaja de
que el usuario puede filtrar por esta propiedad en modo lista, y la
desventaja de que hemos de usar SQL en vez de Java, y no se recalcula el
valor en vivo.
Mapeo
referencia
La sintaxis para mapear una referencia es:
<mapeo-referencia
referencia-modelo="referencia" <!-- 1 -->
>
<detalle-mapeo-referencia ... /> ... <!-- 2 -->
</mapeo-referencia>
- referencia (obligada): La referencia que se quiere
mapear.
- detalle-mapeo-referencia (varias, obligada): Para
mapear una columna de la tabla con un propiedad de la clave para
obtener la referencia. Si la clave del objeto referenciado es múltiple
habrá varios detalle-mapeo-referencia.
Hacer un mapeo de una referencia es sencillo. Por ejemplo si tenemos una
referencia como ésta:
<entidad>
...
<referencia nombre="factura" modelo="Factura"/>
...
</entidad>
Podemos mapearla de esta forma:
<mapeo-entidad tabla="XAVATEST@separator@ALBARAN">
<mapeo-referencia referencia-modelo="factura">
<detalle-mapeo-referencia
columna-tabla="FACTURA_AÃ?O"
propiedad-modelo-referenciado="año"/>
<detalle-mapeo-referencia
columna-tabla="FACTURA_NUMERO"
propiedad-modelo-referenciado="numero"/>
</mapeo-referencia>
...
</mapeo-entidad>
FACTURA_NUMERO y FACTURA_AÑO son columnas de la tabla ALBARAN que nos
permiten acceder a su factura, digamos que es la clave ajena, aunque el
que esté declarada como tal en la base de datos no es preceptivo. Estas
columnas las tenemos que relacionar con las propiedades clave en
Factura,
como sigue:
<entidad>
<propiedad nombre="año" tipo="int" clave="true" longitud="4" requerido="true">
<calculador-valor-defecto
clase="org.openxava.calculators.CurrentYearCalculator"/>
</propiedad>
<propiedad nombre="numero" tipo="int"
clave="true" longitud="6" requerido="true"/>
...
Si tenemos una referencia a un modelo cuyo clave incluye referencia para
definirlo en el mapeo lo hacemos como sigue:
<mapeo-referencia referencia-modelo="albaran">
<detalle-mapeo-referencia
columna-tabla="ALBARAN_FACTURA_AÑO"
propiedad-modelo-referenciado="factura.año"/>
<detalle-mapeo-referencia
columna-tabla="ALBARAN_FACTURA_NUMERO"
propiedad-modelo-referenciado="factura.numero"/>
<detalle-mapeo-referencia
columna-taba="ALBARAN_TIPO"
propiedad-modelo-referenciado="tipo.codigo"/>
<detalle-mapeo-referencia
columna-tabla="ALBARAN_NUMERO"
propiedad-modelo-referenciado="numero"/>
</mapeo-referencia>
Como se ve al indicar la propiedad del modelo referenciado podemos
calificarla.
También es posible usar conversores cuando mapeamos referencias:
<mapeo-referencia referencia="permisoConducir">
<detalle-mapeo-referencia
columna-tabla="PERMISOCONDUCIR_TIPO"
propiedad-modelo-referenciado="tipo"
tipo-cmp="String"> <!-- 1 En esta caso esta linea puede ser omitida -->
<conversor clase="org.openxava.converters.NotNullStringConverter"/> <!-- 2 -->
</detalle-mapeo-referencia>
<detalle-mapeo-referencia
columna-tabla="PERMISOCONDUCIR_NIVEL"
propiedad-modelo-referenciado="nivel"/>
</mapeo-referencia>
Podemos usar el conversor igual que en el caso de una propiedad simple
(1). La diferencia en el caso de las referencias es que si no asignamos
conversor no se usa ningún conversor por defecto, esto es porque aplicar
de forma indiscriminada conversores sobre información que se usa para
buscar puede ser problemático. Podemos usar
tipo-cmp (1)
(nuevo
en v2.0) para indicar que tipo para el atributo es usado
internamente en nuestro objeto para almacenar el valor. Esto nos permite
usar un tipo Java más cercano al de la base de datos;
tipo-cmp
no es necesario si el tipo de la base de datos es compatible con el tipo
Java.
Mapeo
propiedad multiple
Con
<mapeo-propiedad-multiple/> podemos hacer que varias
columnas de la tabla de base de datos correspondan a una propiedad en
Java. Esto es útil, por ejemplo cuando tenemos propiedades cuyo tipo Java
son clases definidas por nosotros que tienen a su vez varias propiedades
susceptibles de ser almacenadas, y también se usa mucho cuando nos
enfrentamos a esquemas de bases de datos legados.
La sintaxis de este tipo de mapeo es:
<mapeo-propiedad-multiple
propiedad-modelo="propiedad" <!-- 1 -->
>
<conversor ... /> <!-- 2 -->
<campo-cmp ... /> ... <!-- 3 -->
</mapeo-propiedad-multiple>
- propiedad-modelo (obligada): Nombre de la propiedad
que se quiere mapear.
- conversor (uno, obligado): Clase con la lógica para
hacer la conversión de Java a base de datos y viceversa. Ha de
implementar IMultipleConverter.
- campo-cmp (varios, obligado): Hace corresponder
cada columna de la base de datos con una propiedad del conversor.
Un ejemplo típico sería usar el conversor genérico
Date3Converter,
que permite almacenar en la base de datos 3 columnas y en Java una
propiedad
java.util.Date.
<mapeo-propiedad-multiple propiedad-modelo="fechaEntrega">
<conversor clase="org.openxava.converters.Date3Converter"/>
<campo-cmp
propiedad-conversor="day" columna-tabla="DIAENTREGA" tipo-cmp="int"/>
<campo-cmp
propiedad-conversor="month" columna-tabla="MESENTREGA" tipo-cmp="int"/>
<campo-cmp
propiedad-conversor="year" columna-tabla="AÑOENTREGA" tipo-cmp="int"/>
</mapeo-propiedad-multiple>
DIAENTREGA, MESENTREGA y AÑOENTREGA son las tres columnas que en la base
de datos guardan la fecha de entrega, y
day,
month y
year
son propiedades que podemos encontrar en
Date3Converter. Y aquí
Date3Converter:
package org.openxava.converters;
import java.util.*;
import org.openxava.util.*;
/**
* In java a <tt>java.util.Date</tt> and in database 3 columns of
* integer type. <p>
*
* @author Javier Paniza
*/
public class Date3Converter implements IMultipleConverter { // 1
private int day;
private int month;
private int year;
public Object toJava() throws ConversionException { // 2
return Dates.create(day, month, year);
}
public void toDB(Object objetoJava) throws ConversionException { // 3
if (objetoJava == null) {
setDay(0);
setMonth(0);
setYear(0);
return;
}
if (!(objetoJava instanceof java.util.Date)) {
throw new ConversionException("conversion_db_utildate_expected");
}
java.util.Date fecha = (java.util.Date) objetoJava;
Calendar cal = Calendar.getInstance();
cal.setTime(fecha);
setDay(cal.get(Calendar.DAY_OF_MONTH));
setMonth(cal.get(Calendar.MONTH) + 1);
setYear(cal.get(Calendar.YEAR));
}
public int getYear() {
return year;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public void setYear(int i) {
year = i;
}
public void setDay(int i) {
day = i;
}
public void setMonth(int i) {
month = i;
}
}
El conversor tiene que implementar
IMultipleConverter (1) lo que le obliga a
tener un método
toJava() (2) que a partir de lo contenido en sus
propiedades (en este caso
year,
month y
day)
ha de devolver un objeto Java con el valor de la propiedad mapeada (en
nuestro ejemplo el valor de la
fechaEntrega); y el método
toDB()
(3) que recibe el valor de la propiedad Java (el de
fechaEntrega)
y tiene que desglosarlo para que se queda almacenado en las propiedades
del conversor (
year,
month y
day).
Mapeo
de referencias a agregados
Una referencia a un agregado contiene información que en el modelo
relacional se guarda en la misma tabla que la entidad principal. Por
ejemplo si tenemos un agregado
Direccion asociado a un
Cliente,
los datos de la dirección se guardan en la misma tabla que los del
cliente. ¿Cómo se expresa eso en OpenXava? Es muy sencillo. En el modelo
nos encontramos:
<entidad>
...
<referencia nombre="direccion" modelo="Direccion" requerido="true"/>
...
</entidad>
<agregado nombre="Direccion">
<implementa interfaz="org.openxava.test.ejb.IConMunicipio"/>
<propiedad nombre="calle" tipo="String" longitud="30" requerido="true"/>
<propiedad nombre="codigoPostal" tipo="int" longitud="5" requerido="true"/>
<propiedad nombre="municipio" tipo="String" longitud="20" requerido="true"/>
<referencia nombre="provincia" requerido="true"/>
</agregado>
Sencillamente una referencia a un agregado, y para mapearlo lo hacemo así:
<mapeo-entidad tabla="XAVATEST@separator@CLIENTE">
...
<mapeo-propiedad propiedad-modelo="direccion_calle" columna-tabla="CALLE"/>
<mapeo-propiedad
propiedad-modelo="direccion_codigoPostal"
columna-tabla="CP" tipo-cmp="String">
<conversor clase="org.openxava.converters.IntegerStringConverter"/>
</mapeo-propiedad>
<mapeo-propiedad
propiedad-modelo="direccion_municipio" columna-tabla="MUNICIPIO"/>
<mapeo-referencia referencia-modelo="direccion_municipio">
<detalle-mapeo-referencia
columna-tabla="PROVINCIA" propiedad-modelo-referenciado="codigo"/>
</mapeo-referencia>
</mapeo-entidad>
Vemos como los miembros del agregado se mapean en el mapeo de la entidad
que lo contienen, solo que ponemos como prefijo el nombre de la referencia
a agregado con un subrayado (en esta caso direccion_). Podemos observar
como podemos mapear referencias y propiedades y usar conversores.
Mapeo
de agregados usados en colecciones
En el caso de que tengamos una colección de agregados, supongamos las
líneas de una factura, obviamente la información de las líneas se guarda
en una tabla diferente que la información de cabecera de la factura. En
este caso los agregados han de tener su propio mapeo. Veamos el ejemplo de
las líneas de una factura.
En la parte de modelo del componente
Factura tenemos:
<entidad>
...
<coleccion nombre="lineas" minimo="1">
<referencia modelo="LineaFactura"/>
</coleccion>
...
</entidad>
<agregado nombre="LineaFactura">
<propiedad nombre="oid" tipo="String" clave="true" oculta="true">
<calculador-valor-defecto
clase="org.openxava.test.calculadores.CalculadorOidLineaFactura"
al-crear="true"/>
</propiedad>
<propiedad nombre="tipoServicio">
<valores-posibles>
<valor-posible valor="especial"/>
<valor-posible valor="urgente"/>
</valores-posibles>
</propiedad>
<propiedad nombre="cantidad" tipo="int" longitud="4" requerido="true"/>
<propiedad nombre"precioUnitario" estereotipo="DINERO" requerido="true"/>
<propiedad nombre="importe" estereotipo="DINERO">
<calculador clase="org.openxava.test.calculadores.CalculadorImporteLinea">
<poner propiedad="precioUnitario"/>
<poner propiedad="cantidad"/>
</calculador>
</propiedad>
<referencia modelo="Producto" requerido="true"/>
<propiedad nombre="fechaEntrega" tipo="java.util.Date">
<calculador-valor-defecto
clase="org.openxava.calculators.CurrentDateCalculator"/>
</propiedad>
<referencia nombre="vendidoPor" modelo="Comercial"/>
<propiedad nombre="observaciones" estereotipo="MEMO"/>
</agregado>
Vemos una colección de
LineaFactura que es un agregado,
LineaFactura
se ha de mapear así:
<mapeo-agregado agregado="LineaFactura" tabla="XAVATEST@separator@LINEAFACTURA">
<mapeo-referencia referencia="factura"> <!-- 1 -->
<detalle-mapeo-referencia
columna-tabla="FACTURA_AÑO"
propiedad-modelo-referenciado="año"/>
<detalle-mapeo-referencia
columna-tabla="FACTURA_NUMERO"
propiedad-modelo-referenciado="numero"/>
</mapeo-referencia>
<mapeo-propiedad propiedad-modelo="oid" columna-tabla="OID"/>
<mapeo-propiedad propiedad-modelo="tipoServicio" columna-tabla="TIPOSERVICIO"/>
<mapeo-propiedad
propiedad-modelo="precioUnitario" columna-tabla="PRECIOUNITARIO"/>
<mapeo-propiedad propiedad-modelo="cantidad" columna-tabla="CANTIDAD"/>
<mapeo-referencia referencia="producto">
<detalle-mapeo-referencia
columna-tabla="PRODUCTO_CODIGO"
propiedad-modelo-referenciado="codigo"/>
</mapeo-referencia>
<mapeo-propiedad-multiple propiedad-modelo="fechaEntrega">
<conversor clase="org.openxava.converters.Date3Converter"/>
<campo-cmp
propiedad-conversor="day"
columna-tabla="DIAENTREGA" tipo-cmp="int"/>
<campo-cmp
propiedad-conversor="month"
columna-tabla="MESENTREGA" tipo-cmp="int"/>
<campo-cmp
propiedad-conversor="year"
columna-tabla="AÑOENTREGA" tipo-cmp="int"/>
</mapeo-propiedad-multiple>
<mapeo-referencia referencia="vendidoPor">
<detalle-mapeo-referencia
columna-tabla="VENDIDOPOR_CODIGO"
propiedad-modelo-referenciado="codigo"/>
</mapeo-referencia>
<mapeo-propiedad
propiedad-modelo="observaciones" columna-tabla="OBSERVACIONES"
</aggregate-mapping>
Los mapeos de agregado se ponen a continuación del mapeo de entidad, y
debe haber tantos como agregados usados en colecciones. El mapeo de un
agregado tiene exactamente las misma posibilidades que el mapeo de entidad
ya visto, con la salvedad de que necesitamos definir el mapeo de la
referencia al objeto contenedor aunque ella no esté en el modelo. Esto es
aunque nosotros no definamos en
LineaFactura una referencia a
Factura,
el OpenXava la añade automáticamente y por ende nosotros en el mapeo
tenemos que reflejarlo (1).
Conversores
por defecto
Vemos como podemos declarar un conversor a cada mapeo de propiedad. Pero
¿qué pasa cuando no declaramos conversor? En realidad en OpenXava todas
las propiedades (a excepción de las que son clave) tienen un conversor
aunque no se indique explícitamente. Los conversores por defecto están
definidos en el archivo
OpenXava/xava/default-converters.xml,
que tiene un contenido como este:
<?xml version = "1.0" encoding = "ISO-8859-1"?>
<!DOCTYPE converters SYSTEM "dtds/converters.dtd">
<!--
In your project use the name 'converters.xml' or 'conversores.xml'
-->
<converters>
<for-type type="java.lang.String"
converter-class="org.openxava.converters.TrimStringConverter"
cmp-type="java.lang.String"/>
<for-type type="int"
converter-class="org.openxava.converters.IntegerNumberConverter"
cmp-type="java.lang.Integer"/>
<for-type type="java.lang.Integer"
converter-class="org.openxava.converters.IntegerNumberConverter"
cmp-type="java.lang.Integer"/>
<for-type type="boolean"
converter-class="org.openxava.converters.Boolean01Converter"
cmp-type="java.lang.Integer"/>
<for-type type="java.lang.Boolean"
converter-class="org.openxava.converters.Boolean01Converter"
cmp-type="java.lang.Integer"/>
<for-type type="long"
converter-class="org.openxava.converters.LongNumberConverter"
cmp-type="java.lang.Long"/>
<for-type type="java.lang.Long"
converter-class="org.openxava.converters.LongNumberConverter"
cmp-type="java.lang.Long"/>
<for-type type="java.math.BigDecimal"
converter-class="org.openxava.converters.BigDecimalNumberConverter"
cmp-type="java.math.BigDecimal"/>
<for-type type="java.util.Date"
converter-class="org.openxava.converters.DateUtilSQLConverter"
cmp-type="java.sql.Date"/>
</converters>
Si usamos una propiedad de un tipo que no tenemos definido aquí por
defecto se le asigna el conversor
NoConversionConverter, que es
un conversor tonto que no hace nada.
En el caso de las propiedades clave no se asigna conversor en absoluto,
aplicar conversor a las propiedades claves puede ser problemático en
ciertas circunstancias, pero si aun así lo queremos podemos declarar
explicitamente en nuestro mapeo un conversor para una propiedad clave y se
le aplicará.
Si queremos modificar el comportamiento de los conversores por defecto
para nuestra aplicación no debemos modificar este archivo sino crear uno
llamado
converters.xml o
conversores.xml en el
directorio
xava de nuestro proyecto. Podemos asignar también
conversor por defecto a un estereotipo (usando
<para-estereotipo/>
o
<for-stereotype/>).
Mapeo
por defecto (nuevo en v2.1.3)
Desde la versión 2.1.3 OpenXava permite definir componentes sin mapeo, y
se asume un mapeo por defecto para él. Por ejemplo, podemos escribir:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE componente SYSTEM "dtds/componente.dtd">
<componente nombre="Alumno">
<entidad>
<propiedad nombre="numero" tipo="int" clave="true"
longitud="2" requerido="true"/>
<propiedad nombre="nombre" tipo="String"
longitud="40" requerido="true"/>
<referencia nombre="profesor"/>
</entidad>
</componente>
Este componente está mapeado a la tabla
Alumno, y las
propiedades numero y nombre están mapeadas a las columnas numero y nombre.
La referencia profesor está mapeada a una columna llamada
profesor_numero
(si la propiedad clave de
Profesor se llama numero).
Filosofia
del mapeo objeto-relacional
OpenXava ha nacido y se ha desarrollado en un entorno en el que nos hemos
visto obligados a trabajar con bases de datos existentes sin poder
modificar su estructura, esto hace que:
- Ofrezca gran flexibilidad para mapear contra bases de datos legadas.
- No ofrezca algunas características propias de la OOT y que requieren
poder manipular el esquema, como por ejemplo el soporte de herencia o
consultas polimórficas.
Otras característica importante del mapeo de OpenXava es que las
aplicaciones son 100% portables entre JBoss CMP2 y Websphere CMP2 sin
tener que reescribir nada por parte del desarrollador. Además, la
portabilidad entre Hibernate, JPA y EJB2 de una aplicación es muy alta,
los mapeos y todos los controladores automáticos son portables al 100%,
obviamente el código propio escrito con EJB2, JPA o Hibernate no lo es
tanto.