jueves, 24 de septiembre de 2015

Learning Project Mariadb Tutorial (3): Creación del resto de tablas en SQL

Learning Project Mariadb Tutorial (3): Creación del resto de tablas en SQL



Continuación de Learning Project Mariadb Tutorial (2): Creación de las tablas en SQL , antes de seguir con en este ejemplo te recomendamos que accedas al apartado anterior.


A continuación, vamos a crear el resto de las tablas que desarrollamos en el proyecto para Customerdb para MariaDB.

Tabla cb_currency


Empecemos con cb_currency, nuestra tabla de monedas para el proyecto, la utilizaremos para definir la moneda del país (cb_country y cb_enterprise por ejemplo), este el código:


CREATE TABLE cb_currency
(
  idcurrency INT NOT NULL AUTO_INCREMENT,
  currency VARCHAR(60) NOT NULL,
  description  VARCHAR(255) NOT NULL ,
  isactive VARCHAR(1) NOT NULL DEFAULT 'N',
  isocode VARCHAR(3) NOT NULL,
  cursymbol VARCHAR(10),
  precisionstd DECIMAL(10,0) NOT NULL,
  precisioncost DECIMAL(10,0) NOT NULL,
  precisionprize DECIMAL(10,0) NOT NULL DEFAULT 0,
  CONSTRAINT pk_cb_currency PRIMARY KEY (idcurrency),
  CONSTRAINT u_cb_currency_currency UNIQUE (currency),
  CONSTRAINT u_cb_currency_isocode UNIQUE (isocode)
)
ENGINE = InnoDB
COMMENT='Tabla  donde se definen las monedas disponibles y sus relaciones a partir de las monedas bases.';
GRANT ALL ON TABLE cb_currency TO xulescode;

Usamos idcurrency como clave primaria un tipo integer con  AUTO_INCREMENT (generación automática de un contador único):
Algunas consideraciones a tener en cuenta al definir los valores AUTO_INCREMENT:
  • Puede utilizarse para generar una identidad única para nuevas filas. Al insertar un nuevo registro a la tabla el valor automáticamente será incrementado.
  • Las columnas AUTO_INCREMENT comienzan a partir del 1 de forma predeterminada. El valor generado automáticamente nunca puede ser inferior a 0.
  • Cada tabla puede tener sólo una columna AUTO_INCREMENT. Debe definirse como una clave (no necesariamente la clave principal o clave UNIQUE). Si la clave consiste en varias columnas, la columna AUTO_INCREMENT tiene que ser el primero, a menos que el motor de almacenamiento es Aria o MyISAM.

Para la definición de clave primaria que explicamos en la anterior publicación, usamos el siguiente código SQL:

CONSTRAINT pk_cb_currency PRIMARY [Nombre de la clave] KEY (idcurrency) [Indicamos el campo que forma la clave primaria]

En este caso también definimos como clave única currency, es decir, que este valor no se puede repetir, para ellos utilizamos: CONSTRAINT u_cb_currency_currency UNIQUE (currency), lo mismo hacemos con isocode: CONSTRAINT u_cb_currency_isocode UNIQUE (isocode) recordemos la explicaciòn de su uso:

CONSTRAINT u_cb_currency_currency [Nombre para la clave única] UNIQUE (currency) [Indicamos el campo que queremos definir como único]

Para consultar los tipos de datos que podemos usar en MariaDB aquí tienes toda la información: Data Types, veamos los tipos básicos utilizados hasta ahora:
  • INT
    • Integer desde -2147483648 hasta 2147483648
  • INTEGER
    • Sinónimo para INT
  • DECIMAL
    • A packed "exact" fixed-point number
  • DEC, NUMERIC, FIXED
    • Sinónimo para DECIMAL
  • VARCHAR
    • Cadena con tamaño variable, como puedes ver en las definiciones de las tablas utilizamos diferentes tamaños de cadenas para limitar los tamaños de las variables utilizadas según nos interese.

Tabla cb_country


La tabla cb_country es la tabla de países para el proyecto, en este caso para cada país indicaremos cual es el idioma y su moneda, este el código:

CREATE TABLE cb_country
(
  idcountry INT NOT NULL AUTO_INCREMENT,
  country VARCHAR(100) NOT NULL,
  description VARCHAR(255),
  countrycode VARCHAR(2) NOT NULL,
  hasregion VARCHAR(1) NOT NULL DEFAULT 'N',
  regionname VARCHAR(60),
  expressionphone VARCHAR(20),
  displaysequence VARCHAR(20) NOT NULL,
  isdefault  VARCHAR(1) NOT NULL DEFAULT 'N',
  ibannodigits NUMERIC,
  ibancountry VARCHAR(2),
  isactive BOOLEAN NOT NULL DEFAULT true,
  idlanguage VARCHAR(6),
  idcurrency INT,
  CONSTRAINT pk_cb_country PRIMARY KEY (idcountry),
  CONSTRAINT fk_cb_country_idcurrency FOREIGN KEY (idcurrency)
      REFERENCES cb_currency (idcurrency) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_country_idlanguage FOREIGN KEY (idlanguage)
      REFERENCES cb_language (idlanguage) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT un_cb_country_countrycode UNIQUE (countrycode),
  CONSTRAINT ch_cb_country_hasregion_check CHECK (hasregion IN ('Y', 'N')),
  CONSTRAINT ch_cb_country_isdefault_check CHECK (isdefault IN ('Y', 'N'))
)
ENGINE=InnoDB
COMMENT='Tabla donde se definen todos los países con sus características principales: idioma, nombre, ..., y diferentes datos íntrinsecos a cada país.';
GRANT ALL ON TABLE cb_country TO xulescode;

Usamos idcountry como clave primaria: CONSTRAINT pk_cb_country PRIMARY KEY (idcountry), en este caso también definimos como clave única countrycode, es decir, que este valor no se puede repetir, para ellos utilizamos: CONSTRAINT un_cb_country_countrycode UNIQUE, como ya se explicó anteriormente.

En este caso para los países definimos el idioma y la moneda por lo que vamos a relacionar cb_country con las tablas correspondientes de cb_language y cb_currency, para esto vamos a definir las claves foráneas (foreign key) correspondientes:
  • Definimos la clave foránea para cb_currency, que consiste en relacionar el valor de una tabla con otra estableciendo la relación, en este caso por el id de la tabla:
  CONSTRAINT fk_cb_country_idcurrency [Nombre de la tabla] FOREIGN KEY (idcurrency) [Campo en cb_country]
      REFERENCES cb_currency (idcurrency) [Tabla relacionada y el campo] MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION [Definición de las acciones]
  • Definimos la clave foránea para cb_language, que consiste en relacionar el valor de una tabla con otra estableciendo la relación, en este caso por el id de la tabla:
  CONSTRAINT fk_cb_country_idlanguage [Nombre de la tabla] FOREIGN KEY (idlanguage) [Campo en cb_country]
      REFERENCES cb_language (idlanguage)
[Tabla relacionada y el campo] MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
[Definición de las acciones]

Tabla cb_paymentmethod


La tabla cb_paymentmethod es la tabla de métodos de pago que vamos a definir para los clientes:

CREATE TABLE cb_paymentmethod
(
  idpaymentmethod INT NOT NULL AUTO_INCREMENT,
  paymentmethod VARCHAR(100) NOT NULL,
  description VARCHAR(150),
  paymentterms VARCHAR(250),
  paymententity VARCHAR(50),
  CONSTRAINT pk_cb_paymentmethod PRIMARY KEY (idpaymentmethod),
  CONSTRAINT un_cb_paymentmethod_paymentmethod UNIQUE (paymentmethod)
)
ENGINE=InnoDB
COMMENT='Métodos de pago definidos para el cliente u otras entidades';
GRANT ALL ON TABLE cb_paymentmethod TO xulescode;

Esta tabla no tiene nada de particular definimos idpaymentmethod como clave primaria con  un entero y AUTO_INCREMENT :

idpaymentmethod INT NOT NULL AUTO_INCREMENT

CONSTRAINT pk_cb_paymentmethod [Nombre para la clave primaria] PRIMARY KEY (idpaymentmethod) [Campo que forma la clave primaria]


Definimos paymentmethod como clave única como se indico anteriormente:

CONSTRAINT un_cb_paymentmethod_paymentmethod [Nombre para la clave única] UNIQUE (paymentmethod)[Campo que forma la clave primaria]

Tabla cb_addresses


La tabla cb_addresses es la tabla donde se asocian las direcciones que tiene un cliente , cada cliente tendrá un número ilimitado de direcciones definidas en cb_address, que se asociarán mediante el id generado en esta tabla y que se relacionará directamente con el cliente.

Está es la definición de la tabla, que definimos como una agrupación de las direcciones asignadas a una entidad:


CREATE TABLE cb_addresses
(
  idaddresses INT NOT NULL AUTO_INCREMENT,
  addressesentity VARCHAR(100) NOT NULL,
  CONSTRAINT pk_cb_addresses PRIMARY KEY (idaddresses)
)
ENGINE=InnoDB
COMMENT='Agrupación de las direcciones asignadas a una entidad.';
GRANT ALL ON TABLE cb_addresses TO xulescode;

Tabla cb_address

La tabla  cb_address es la tabla de direcciones que vamos a definir para los clientes u otras entidades que lo necesiten, a través de la relación que establecemos mediante cb_addresses para cada entidad, este es el código SQL de la tabla:


CREATE TABLE cb_address
(
  idaddress INT NOT NULL AUTO_INCREMENT,
  idaddresses INT,
  address VARCHAR(500),
  postalnumber VARCHAR(20),
  mainphone VARCHAR(100),
  movilephone VARCHAR(100),
  phone2 VARCHAR(100),
  phone3 VARCHAR(100),
  carrier VARCHAR(200),
  addresstype VARCHAR(100),
  locality VARCHAR(250),
  estate VARCHAR(250),
  idcountry INT,
  notes1 VARCHAR(500),
  CONSTRAINT pk_cb_address PRIMARY KEY (idaddress),
  CONSTRAINT fk_cb_address_idaddresses FOREIGN KEY (idaddresses)
      REFERENCES cb_addresses (idaddresses) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_address_idcountry FOREIGN KEY (idcountry)
      REFERENCES cb_country (idcountry) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
ENGINE=InnoDB
COMMENT='Direcciones para: Clientes, Empresas,... ';
GRANT ALL ON TABLE cb_address TO xulescode;

Usamos idaddress como clave primaria: CONSTRAINT pk_cb_address PRIMARY KEY (idaddress), definimos los campos habituales para la dirección entre ellos los teléfonos y el país, para este usamos una clave foránea para relacionar el país con la dirección por medio de idcountry.

CONSTRAINT fk_cb_address_idcountry FOREIGN KEY (idcountry)
      REFERENCES cb_country (idcountry) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION

Para almacenar todas las direcciones de una entidad las relacionamos por e campo idaddresses para el que podemos tener una o varias direcciones, este campo se genera en la tabla cb_addresses y para ello tenemos que relacinarlo con una clave foránea:

CONSTRAINT fk_cb_address_idcountry FOREIGN KEY (idcountry)
      REFERENCES cb_country (idcountry) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION

De momento vamos a dejar las acciones sin hacer nada, tanto aquí como en cb_addresses y cb_address, para más adelante ver la conveniencia de realizar acciones de actualización y borrado en cadena.

Tabla cb_enterprise

La tabla cb_enterprise es la tabla de empresas de la base de datos Customerdb, con lo que cada empresa tendrá sus clientes, es el SQL con el que implementamos está tabla:


CREATE TABLE cb_enterprise
(
  identerprise INT NOT NULL,
  enterprise VARCHAR(150),
  description VARCHAR(250),
  enterprisealias VARCHAR(100),
  contact VARCHAR(250),
  estate VARCHAR(30),
  balance DECIMAL(10,3),
  ei VARCHAR(100),
  enterprisepayer VARCHAR(20),
  idcountry INT,
  idcurrency INT,
  idlanguage VARCHAR(6),
  CONSTRAINT pk_enterprise PRIMARY KEY (identerprise),
  CONSTRAINT cb_enterprise_idlanguage FOREIGN KEY (idlanguage)
      REFERENCES cb_language (idlanguage) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_enterprise_idcountry FOREIGN KEY (idcountry)
      REFERENCES cb_country (idcountry) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_enterprise_idcurrency FOREIGN KEY (idcurrency)
      REFERENCES cb_currency (idcurrency) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
ENGINE=InnoDB
COMMENT='Tabla para controlar las empresas que se usan en la aplicación, la aplicación se desarrolla en función de estos parámetros ya que habrá algunas tablas que serán comunes a las empresa y otras que no, por ejemplo, cada empresa tendrá sus propios clientes, pero tendrá los mismos idiomas, monedas y países de trabajo.';
GRANT ALL ON TABLE cb_enterprise TO xulescode;

Usamos identerprise como clave primaria: CONSTRAINT pk_enterprise PRIMARY KEY (identerprise), además también definimos las relacionales para indicar el idioma (cb_language), la moneda (cb_currency) y el país (cb_country), de la misma forma que hicimos en las otra tablas.

En este caso es un decisión de diseño para este base de datos definir el idioma y la moneda en particular para la empresa ya que como vimos antes los valores los tenemos relacionados por país, en este caso, defino el idioma y la moneda con la que trabaja la empresa que no tiene porque coincidir con la del país.

Tabla cb_customer

La tabla cb_customer es la tabla donde se almacenarán los clientes de las diferentes empresas, se entiende cliente como aquel que compra a una empresa, veamos el código SQL para nuestra tabla de cliente.


CREATE TABLE cb_customer
(
  idcustomer INT NOT NULL AUTO_INCREMENT,
  identerprise INT,
  customer VARCHAR(15) NOT NULL,
  customername VARCHAR(150),
  customeralias VARCHAR(100),
  contact VARCHAR(250),
  customerstate VARCHAR(30),
  sale DECIMAL(10,3),
  identitynumber VARCHAR(100),
  customerpayer VARCHAR(20),
  idpaymentmethod INT,
  idcountry INT,
  idcurrency INT,
  idlanguage VARCHAR(6),
  idaddresses INT,
  CONSTRAINT pk_cb_customer PRIMARY KEY (idcustomer),
  CONSTRAINT fk_cb_customer_idaddresses FOREIGN KEY (idaddresses)
      REFERENCES cb_addresses (idaddresses) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_customer_idcountry FOREIGN KEY (idcountry)
      REFERENCES cb_country (idcountry) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_customer_idcurrency FOREIGN KEY (idcurrency)
      REFERENCES cb_currency (idcurrency) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_customer_identerprise FOREIGN KEY (identerprise)
      REFERENCES cb_enterprise (identerprise) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_customer_idlanguage FOREIGN KEY (idlanguage)
      REFERENCES cb_language (idlanguage) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk_cb_customer_idpaymentmethod FOREIGN KEY (idpaymentmethod)
      REFERENCES cb_paymentmethod (idpaymentmethod) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT un_cb_customer_cb_enterprise UNIQUE (identerprise, customer)
)
ENGINE=InnoDB
COMMENT='Tabla donde se almacenarán los clientes de las diferentes empresas, se entiende cliente como aquel que compra a una empresa.';
GRANT ALL ON TABLE cb_customer TO xulescode;

Usamos idcustormer como clave primaria: CONSTRAINT pk_cb_customer PRIMARY KEY (idcustomer), como queremos separar los clientes por empresa necesitamos indicar a que empresa pertenece cada cliente, para ello usamos identerprise para relacionarlos con la empresa de la tabla cb_enterprise , como se puede ver en la tabla usamos la clave foránea: fk_cb_customer_identerprise para establecer la relación.

Además también definimos las relacionales para indicar el idioma (cb_language), la moneda (cb_currency) ,  el país (cb_country) y las formas de pago (cb_paymentmethod).

También, definimos para los clientes, lo hacemos a través de la tabla cb_addresses, tabla que utilizaremos para almacenar varias direcciones de cliente en la tabla cb_address. En la tabla de cb_customer simplemente establecemos la relación con cb_addresses con la columna idaddresses como hicimos en otros casos:

CONSTRAINT fk_cb_customer_idaddresses FOREIGN KEY (idaddresses)
      REFERENCES cb_addresses (idaddresses) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION

Será a través de esta tabla como obtendremos las direcciones reales del cliente almacenadas en cb_address.

Por si no quieres hacerlo tabla a tabla te facilito un script para hacer la creación de las tablas y puedes hacer las pruebas que quieras:  Script creación de tablas Customerdb..

Borrado de tablas


Por si fuera necesario durante la programación el orden del borrado de tablas sería el siguiente:


DROP TABLE cb_customer;
DROP TABLE cb_enterprise;
DROP TABLE cb_paymentmethod;
DROP TABLE cb_address;
DROP TABLE cb_addresses;
DROP TABLE cb_country;
DROP TABLE cb_currency;
DROP TABLE cb_language;

La sintaxis es sencilla simplemente se utiliza la sintaxis DROP TABLE, y  a continuación, el nombre de la tabla.


En el siguiente capítulo facilitaré un script para cargar con datos la base de datos y empezar con las consultas básicas.

Espero que te haya sido útil.

miércoles, 23 de septiembre de 2015

Learning Project Openxava Tutorial (3.1): Actualizando la presentación

Nos hemos trasladado a www.codigoxules.org , consulta la actualización de esta entrada en Tutorial Openxava (3.1): Actualizando la presentación con View


Después de los dos primeros capítulos de este tutorial donde instalamos y configuramos nuestra aplicación en OpenXava, donde creamos las clases para definir nuestras tablas e implementar la aplicación para darle funcionalidad, toca profundizar un poco más.

Vamos a ver como configuramos los formularios en OpenXava, como modificamos los campos utilizados y otras propiedades. Para ello en este capítulo vamos a estudiar con nuestro proyecto: las vistas, los estereotipos y la internacionalización (i18n), además de otras cosas.

Actualizamos la presentación de CbLanguage

Vamos a definir la vista de presentación de CbLanguage, para ello siguiendo las indicaciones de OpenXava creamos una vista:

@Entity
@View(members = // Vista sin nombre, será la vista por defecto.
        "idlanguage, name;" +
        "isactive, isbaselanguage, issystemlanguage;" +
        "languageiso, countrycode; "
        )

@Table(name="cblanguage")
public class CbLanguage {

Para más información sobre las vista accede al wiki de OpenXava: OpenXava View, para definir una vista la sintaxis básica es:

@View(
 name="nombre", // Nombre de la vista, no es obligatorio
 members="miembros", // Definimos que miembros se visualizan y como se presentan
 extendsView="view" // Nos permite extender una vista heredando todos sus valores
)
public class MiEntidad {


Como en nuestro caso no hemos definido un nombre a la vista (name="nombre") esta será la que se use por defecto.

Veamos que significado tiene lo que hemos escrito, en la variable members podemos escoger que miembros queremos que aparezcan y en que orden, además de esto, decidimos la colocación de los elementos. Observando nuestra vista podemos ver que hemos utilizados comas y puntos y coma para separar los elementos, esto nos sirve para indicar la disposición, con la coma la variables se pone a continuación, y con punto y coma en la línea siguiente, con esta vista el resultado es el siguiente:


Así es como veíamos antes el formulario de CbLanguage:



Si te fijas y comparas las imágenes comprobarás que la colocación de los campos es diferente, y también se actualizado los valores de todas las etiquetas y los menús.

Una vez colocados los elementos vamos a cambiar los nombre de las etiquetas que salen asociados hasta ahora, como vimos antes los nombres que salían son los nombres de los campos en al base de datos. Para ello vamos a editar el fichero EtiquetasCustomerdb_es.properties en la carpeta i18n, con el nombre del campo y un igual indicamos el nuevo valor:

Customerdb=Gestión de clientes
# Componentes de CbLanguage
cbLanguage=Idioma
idlanguage=Idioma
name=Nombre
isactive=Activo
isbaselanguage=Base del sistema
issystemlanguage=Idioma del sistema
languageiso=Iso idioma
countrycode=Código país

Una vez hecho esto la presentación quedaría así:



 

Actualizamos la presentación de CbCurrency


Vamos a definir la vista de presentación de CbCurrency, para ello siguiendo las indicaciones de OpenXava creamos una vista:

@Entity
@View(members =
        "description;" +
        "isactive, iso_code, cursymbol;" +       
        "precisionstd, precisioncost, precisionprize"
)

@Table(name="cbcurrency")
public class CbCurrency {

En este caso, no tiene más complicación, igual que antes colocamos los elementos según como queramos colocarlos elementos y actualizamos el fichero EtiquetasCustomerdb_es.properties en la carpeta i18n con las nuevas etiquetas para esta clase:

# Componentes de CbCurrency
cbCurrency=Moneda
currency=Moneda
isocode=Iso moneda
cursymbol=Símbolo       
precisionstd=Precisión base
precisioncost=Precisión coste
precisionprize=Precisión precio

Este es el resultado final:



Actualizamos la presentación de CbCountry

Vamos a definir la vista de presentación de CbCountry, para ello siguiendo las indicaciones de OpenXava creamos una vista:

@Entity
@View(members = // This view has no name, so it will be the view used by default
        "country, isactive;" +
        "description;" +
        "countrycode;" +
        "hasregion, regionname;" +
        "expressionphone;" +
        "cbCurrency, cbLanguage;"
)
@Table(name="cb_country")
public class CbCountry {

Igual que antes colocamos los elementos y actualizamos el fichero EtiquetasCustomerdb_es.properties en la carpeta i18n con las nuevas etiquetas para esta clase:

# Componentes de CbCountry
cbCountry=País
country=País
countrycode=Código de país
hasregion=Tiene región
regionname=Nombre región
expressionphone= Extensión tlf.

Lo único que podemos resaltar aquí en la vista es que para mostrar la posición y colocación de las tablas relacionadas (cbCurrency y cbLanguage) procedemos de la misma forma con la colocación de las variables si queremos que aparezcan.

Aquí, vamos a hacer algo más, como ya hemos definido y presentado la variable @DescriptionList, vamos a ir un poco más allá, para evitar presentar todos los idiomas y todas las monedas vamos a establecer unos filtros y a indicar el orden de las tablas que se presentan.

    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_country_idcurrency"))
    @DescriptionsList(
            descriptionProperties = "currency",
            condition = "${isactive} = 'Y'", // 5

            order = "${description}" // 6
    )

    private CbCurrency cbCurrency;
   
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_country_idlanguage"))
    @DescriptionsList(
            descriptionProperties = "name",
            condition = "${isactive} = 'Y'", // 5

            order = "${name} " // 6
    )

    private CbLanguage cbLanguage;


Los campos utilizados son los siguientes (para más informacion en  OpenXava View: @DescriptionList, aquí tenéis otros campos que se pueden utilizar para personalizar la presentación en los combos y una explicación detallada):
  • descriptionProperties (= "name"): con esta propiedad indicamos que campo vamos a mostrar en el combo de selección.
  • condition (= "${isactive} = 'Y'"): aquí establecemos una condición de filtrado.
  • order (= "${name} " ): indicamos el campo por el que ordenamos en la presentación.

Una vez hecho esto la presentación quedaría así:




Veamos que valores se muestran en la moneda y el idioma,  para las monedas he actualizado la base de datos directamente para dejar como activos (isactive = 'Y') los valores de Euro y US Dollar, como se puede ver en la imagen:


Para los idiomas he hecho lo mismo dejando solo los valores que se ven en la imagen como activos.


 

Compruébalo tu mismo compilando y reiniciando el servidor con el filtro activo y desactivado, así de fácil.


Actualizamos la presentación de CbPaymentmethod


Vamos a definir la vista de presentación de CbPaymentmethod, para ello siguiendo las indicaciones de OpenXava creamos una vista:

@Entity
@View(members =
    "paymentmethod;" +
    "description;" +       
    "paymententity;" +
    "paymentterms"
)

@Table(name = "cb_paymentmethod")
public class CbPaymentmethod {

    @Id
    @Hidden
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idpaymentmethod", nullable = true)
    private Integer idpaymentmethod;
   
    ...

    @Stereotype("MEMO")
    @Column(name = "paymentterms", length = 250, nullable = true)
    private String paymentterms;

La vista sigue las misma instrucciones que antes en este caso ponemos cada valor en una línea diferente. Incorporamos una etiqueta nueva: @Hidden ,con ello indicamos que este campo se oculta en las presentaciones aunque se utilice internamente.

Igual que antes colocamos los elementos y actualizamos el fichero EtiquetasCustomerdb_es.properties en la carpeta i18n con las nuevas etiquetas para esta clase:


# Componentes de CbPaymentmethod
cbPaymentmethod= Método de pago
paymentmethod= Método
paymententity= Entidad
paymentterms= Términos de pago


Vamos a empezar a utilizar también los estereotipos: @Stereotype, que son la forma de determinar un comportamiento específico dentro de un tipo, en este caso usamos: MEMO, que nos presentará un cajetín de texto en vez de una entrada normal en la imagen aparece marcado en azul:

Los esteriotipos con los que OpenXava viene configurado son (para más información consulta la wiki del modelo: OpenXava model Estereotipo:
  • DINERO, MONEY
  • FOTO, PHOTO, IMAGEN, IMAGE
  • TEXTO_GRANDE, MEMO, TEXT_AREA
  • ETIQUETA, LABEL
  • ETIQUETA_NEGRITA, BOLD_LABEL
  • HORA, TIME
  • FECHAHORA, DATETIME
  • GALERIA_IMAGENES, IMAGES_GALLERY (instrucciones)
  • RELLENADO_CON_CEROS, ZEROS_FILLED
  • TEXTO_HTML, HTML_TEXT (texto con formato editable)
  • ETIQUETA_IMAGEN, IMAGE_LABEL (imagen que depende del contenido de la propiedad)
  • EMAIL
  • TELEFONO, TELEPHONE
  • WEBURL
  • IP
  • ISBN
  • TARJETA_CREDITO, CREDIT_CARD
  • LISTA_EMAIL, EMAIL_LIST
  • LIBRERIA_DOCUMENTOS, DOCUMENT_LIBRARY (nuevo en v4m6, sólo funciona dentro de Liferay)
  • CONTRASENA, PASSWORD (nuevo en v4.1)
  • MAC (nuevo en v4.8)
  • ARCHIVO, FILE (nuevo en v5.0) (instrucciones)
  • ARCHIVOS, FILES (nuevo en v5.1) (instrucciones

También se pueden crear esteriotipos propios, pero esto lo veremos en este tutorial más adelante, si quieres adelantes aquí tienes todas la información: OpenXava model Estereotipo, está bien explicado y se puede hacer en pocos siguiente las instrucciones.



Definimos la información de los módulos


Para finalizar esta publicación vamos a definir los módulos en nuestro fichero EtiquetasCustomerdb_es.properties, que hemos estado actualizando a lo largo de este tutorial.
Para añadir las etiquetas y definiciones para los módulos de la aplicación Customerdb procedemos como te indico a continuación:

Customerdb=Gestión de clientes

# Módulos
CbEnterprise.module=Empresas
CbEnterprise.module[description]=Definición de las empresas
CbCustomer.module=Clientes
CbCustomer.module[description]=Definición de los clientes
CbCountry.module=Paises
CbCountry.module[description]=Definición de los países
CbLanguage.module=Idiomas
CbLanguage.module[description]=Definición de los idiomas
CbCurrency.module=Monedas
CbCurrency.module[description]=Definición de las monedas
CbPaymentmethod.module=Métodos de pago
CbPaymentmethod.module[description]=Definición de los métodos de pago
CbAddress.module=Dirección
CbAddress[description]=Definición de la dirección
CbAddresses.module=Direcciones
CbAddresses[description]=Definición de la direcciones de una entidad (clientes)

Donde CbEnterprise.module se utiliza para darle nombre al módulo y CbEnterprise.module[description] se usa para dar una descripción, que se muestra por ejemplo al seleccionar Inicio en el menú, como se puede ver en la imagen.


Hasta aquí hemos llegado hoy, en la continuación de esta publicación, que será Learning Project Openxava Tutorial (3.2): Actualizando la presentación, finalizaremos la presentación definiendo las clases que nos faltan y entrando más en detalle en algunas posibilidades adicionales que podemos utilizar para las vistas.

Espero que te haya sido útil.





domingo, 20 de septiembre de 2015

Learning Project Mariadb Tutorial (2): Creando las tablas

Learning Project Mariadb Tutorial (2): Creación de las tablas en SQL


Para facilitar que puedas usar este ejemplo explicaré cada tabla en orden de creación con lo que copiando y ejecutando directamente en un script tendrías tu base de datos de ejemplo creada.

Con el editor Netbeans para bases de datos puedes crear las tablas directamente con el entorno gráfico que proporciona, pero esto lo veremos otro día, ahora nos vamos a centrar en la creación de las tablas directamente en la base de datos con SQL.

Antes de empezar, aquí os presento el esquema real final de la base de datos que vamos a crear:



Creando la primera tabla cb_language

 

Vamos a definir como clave el campo idlanguage y en este caso no utilizamos un tipo AUTO INCREMENT (generación automática de un contador único), sino que como clave primaria usamos la codificación del idioma i18n e i10n, las principales: es_ES y en_EN, que serán las que se usarán por defecto.



CREATE TABLE cb_language
(
  idlanguage VARCHAR(6) NOT NULL COMMENT 'Como clave primaria usamos la codificación del idioma i18n e i10n, las principales: es_ES y en_EN, que serán las que se usarán por defecto.',
  namelanguage VARCHAR(60) NOT NULL COMMENT 'Nombre del idioma en el idioma por defecto del sistema (castellano).',
  isactive VARCHAR(1) NOT NULL DEFAULT 'N',
  languageiso VARCHAR(2),
  countrycode VARCHAR(2),
  isbaselanguage VARCHAR(1) NOT NULL DEFAULT 'N',
  issystemlanguage VARCHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT pk_cb_language PRIMARY KEY (idlanguage),
CONSTRAINT u_cb_language_namelanguage UNIQUE (namelanguage),   
CONSTRAINT ch_cb_language_isactive_check CHECK (isactive IN ('Y', 'N')),
CONSTRAINT ch_cb_language_isbaselang_check CHECK(isbaselanguage IN ('Y', 'N')),   
CONSTRAINT ch_cb_language_issysang_check CHECK (issystemlanguage IN ('Y', 'N'))
)
ENGINE = InnoDB
COMMENT='Como clave primaria usamos la codificación del idioma i18n e i10n, las principales: es_ES y en_EN, que serán las que se usarán por defecto.';
GRANT ALL ON TABLE cb_language TO xulescode;

En la web de MariaDB encontramos la documentación sobre CREATE TABLE SQL, la estructura para crear una tabla es la siguiente:

CREATE TABLE nombre_de_la_tabla(
....
); 


La sintaxis completa para CREATE TABLE sería:

CREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name (create_definition,...) [table_options ]... [partition_options] CREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)] [table_options ]... [partition_options] select_statement CREATE [OR REPLACE] [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name { LIKE old_table_name | (LIKE old_table_name) }
Inicialmente, nos quedaremos con lo que vamos a necesitar que es la sintaxis básica de creación de la tabla y ver como creamos los índices, las columnas,...

Clave primaria (Primary key)

Con esto ya creamos nuestra tabla, ahoramos veamos como definimos la clave primaria (primary key), en este caso lo indicamos con la estructura CONSTRAINT pk_cb_language PRIMARY KEY (idlanguage), aunque también se puede definir en el propio campo de la siguiente forma: idlanguage VARCHAR(6) NOT NULL PRIMARY KEY, en nuestro ejemplo quedaría así:

1ª opción: 
   CONSTRAINT pk_cb_language PRIMARY KEY (idlanguage)
2ª opción:

     idlanguage VARCHAR(6) NOT NULL PRIMARY KEY    


Definición de las columnas


La sintaxis para la definición de las columnas en MariaDB es la siguiente, y con ella puedes empezar a entender la creación de la primera tabla de nuestro proyecto:


create_definition: { col_name column_definition | index_definition | CHECK (expr) }
column_definition: data_type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}] [reference_definition] | data_type [GENERATED ALWAYS] AS (expression) {VIRTUAL | PERSISTENT} [UNIQUE [KEY]] [COMMENT 'string']


Utilizamos la sintaxis arriba mencionada para crear nuestras columnas.


  idlanguage VARCHAR(6) NOT NULL COMMENT 'Como clave primaria usamos la codificación del idioma i18n e i10n, las principales: es_ES y en_EN, que serán las que se usarán por defecto.',
  namelanguage VARCHAR(60) NOT NULL COMMENT 'Nombre del idioma en el idioma por defecto del sistema (castellano).',
  isactive VARCHAR(1) NOT NULL DEFAULT 'N',
  languageiso VARCHAR(2),
  countrycode VARCHAR(2),
  isbaselanguage VARCHAR(1) NOT NULL DEFAULT 'N',
  issystemlanguage VARCHAR(1) NOT NULL DEFAULT 'N',

En este caso solo estamos definiendo un tipo de dato VARCHAR en el que con el valor entre paréntesis indicamos su longitud, otras referencias utilizadas son:
  • NOT NULL
    • Indicamos que el campo no puede quedar vacío, sino que tiene que tener un valor distinto de NULL.
  • COMMENT
    • Lo utilizamos para añadir un comentario a la columna explicando su significado.
  • DEFAULT
    • Para indicar un valor por defecto del campo.

Clave única (Unique constraint)

Lo que hacemos al definir una constante de este tipo, es definir una regla para impedir los valores duplicados, la documentación la puedes encontrar en MariaDB Constraint UNIQUE, aquí simplemente presentamos la sintaxis básica:

UNIQUE <Table Constraint> ::= [ CONSTRAINT <Constraint name> ] UNIQUE (<Column name> [ {,<Column name>}... ]) | UNIQUE (VALUE) [ <constraint attributes> ] UNIQUE <Column Constraint> ::= [ CONSTRAINT <Constraint name> ] <Column name> UNIQUE [ <constraint attributes> ]
En nuestro caso ya tenemos definida una clave primaria para la tabla con la columna idlanguage, pero queremos que namelanguage, es decir, el nombre del idioma sea único en la tabla, y por ello necesitamos una clave única:

CONSTRAINT u_cb_language_namelanguage UNIQUE (namelanguage)

Definiendo reglas con CHECK CONSTRAINT


En este caso y para que sirva de ejemplo de utilización hemos dado unos valores por defecto para unos campos VARCHAR, que solo podrán tener esos valores. Para ello definimos una regla mediante CHECK CONSTRAINT la sintaxis es la siguiente:


CHECK <Table Constraint> ::= [ CONSTRAINT <Constraint name> ] CHECK (search condition) [ <constraint attributes> ] CHECK <Column Constraint> ::= [ CONSTRAINT <Constraint name> ] <Column name> CHECK (search condition) [ <constraint attributes> ] CHECK <Domain Constraint> ::= [ CONSTRAINT <Constraint name> ] CHECK (VALUE search condition) [ <constraint attributes> ]

Para nuestro ejemplo, usamos la sintaxis para indicar que la columna isbaselanguage solo puede tener dos valores: Y y N, donde ch_cb_language_isbaselang_check  es el nombre que le daríamos a la regla y CHECK(isbaselanguage IN ('Y', 'N')) es la configuración de la reglas en sí, este es resultado:

CONSTRAINT ch_cb_language_isbaselang_check CHECK(isbaselanguage IN ('Y', 'N')), 


Hasta aquí el segundo post de Learning Project MariaDB Tutorial (1) (MySQL), próximamente en el siguiente post completaremos la creación de las tablas en nuestra base de datos.







miércoles, 16 de septiembre de 2015

Learning Project Mariadb Tutorial (1) (Mysql): Preparación del entorno



MariaDB es un sistema de gestión de bases de datos derivado de MySQL con licencia GPL esta desarrollado por el creador de MySQL Michael (Monty) Widenius, después de la venta a Oracle de esta, Es desarrollado por  (fundador de MySQL) , en la que cuenta con el apoyo de la comunidad de desarrolladores de software libre.

Introduce dos motores de almacenamiento nuevos, uno llamado Aria -que reemplaza con ventajas a MyISAM- y otro llamado XtraDB -en sustitución de InnoDB.

Una de las características principales es que tiene una alta compatibilidad con MySQL ya que posee las mismas órdenes, interfaces, APIs y bibliotecas, lo que permite cambiar un servidor por otro directamente, como ha hecho, por ejemplo, Wikipedia entre otros. 

Empezemos con el tutorial.

Learning Project Mariadb Tutorial (Mysql): Explicación


En este caso vamos a crear una serie de tablas en relación al proyecto que se explica a continuación para poder aprender y hacer pruebas con Mysql con ejemplos, aquí podemos optar por la versión de Oracle o por el fork de Mariadb.

Utiliza el código como quieras y para lo que quieras ya que este es un proyecto de aprendizaje para mi y para todo aquel que lo encuentre útil.

Si ya has consultado el post de Postgresql puedes pasar directamente al apartado de preparación del entorno, ya que para facilitar el aprendizaje y comparación de diferentes bases de datos, usamos siempre el mismo esquema.

Definición

 

El proyecto consiste en la administración de clientes para diferentes empresas, para ello se plantea la necesidad de tener la información de la empresa y de los clientes, cada empresa podrá tener múltiples clientes, para el caso de estudio se plantea que ambas entidades tengan los campos básicos y direcciones que podrán ser una o varias.

Así mismo, y para completar el proyecto con el desarrollo que creemos necesario, se plantea que la tabla clientes tenga como tablas asociadas las tablas de: monedas, países e idiomas, que podrían ser tablas de uso general en la aplicación, y una tabla más específica como podría ser formas de pago.

Esquema inicial


Este no es un diagrama entidad relación clásico sino una simple estructura de las tablas que se van a implementar y de sus relaciones.


Tablas del esquema

Para desarrollar este esquema vamos a necesitar las siguientes tablas, a continuación se explica su utilidad y algunas características básicas, el resto irá directamente sobre el código SQL:

TABLA
DESCRIPCIÓN
CARACTERÍSTICAS DE DISEÑO
cb_enterprise
Empresas de la aplicación, cada empresa tendrá sus clientes.
Las empresas tendrán definido inicialmente: idioma, país y moneda, así como los campos básicos para hacer pruebas.
cb_custormer
Tabla general de cliente,  donde se almacenarán los clientes de las diferentes empresas, se entiende cliente como aquel que compra a una empresa.
Los tendrán definido inicialmente: idioma, país, direcciones, empresas, métodos de pago y moneda, así como los campos básicos para hacer pruebas.
cb_addresses
Tabla de registro de las direcciones, se asocian aquí las direcciones que tienen un cliente, cada cliente tendrá un número ilimitado de direcciones con cb_address relacionado mediante cb_addresses (es básicamente una tabla relacional).
Registro para asociar las direcciones al cliente.
cb_address
Tabla de dirección donde se guardan los datos de la dirección en sí.
Tabla dirección tendrá los campos generales de una dirección, así como números de teléfono, transportista y tipos de dirección.
cb_language
Tabla con los idiomas registrados en la aplicación, se podrá relacionar con múltiples tablas.

cb_country
Tabla con los países registrados en la aplicación, se podrá relacionar con múltiples tablas.
Para cada país se especificará la moneda y el idioma utilizado por defecto.
cb_currency
Tabla con las monedas registradas en la aplicación, se podrá relacionar con múltiples tablas.

cb_paymentmethod
Métodos de pago definidos para el cliente u otras entidades.



Learning Project Mariadb Tutorial (Mysql): Preparación del entorno

 

Instalación de Mariadb

 

No me extenderé en este apartado, las descargas e información para la instalación las puedes encontrar aquí: https://downloads.mariadb.org/, como en mi caso para las pruebas estoy usando Ubuntu ejecuto directamente la instalación del servidor:

sudo apt-get install mariadb-server

Una vez hecha la instalación, vamos a registrar la clave para root y crear la base de datos para las pruebas. Para empezar hacemos login en la cuenta de MySQL root (administrative) usando este comando:
mysql -u root -p
Te preguntará la clave para la cuenta de root de MySQL root cuanto instales el software.
De momento vamos a trabajar con la consola de MySQL directamente, tal y como dije anteriormente que se podía acceder y realizar todas las acciones.

Puesta en marcha básica del servidor


Después de la instalación la base de datos ya queda iniciada automáticamente, y queda funcionando para que al reiniciar el ordenador esta arranque por defecto, algunas opciones de servicio mysql son:
Otras opciones del servicio son: stop|restart|reload|force-reload|status
Por ejemplo, para reiniciar el servidor utilizaríamos:

sudo /etc/init.d/mysql restart

Para ver la configuración y la versión mysql que tenemos instalada:

sudo /etc/init.d/mysql status


Lo que nos saldrá por pantalla será algo así:

 * /usr/bin/mysqladmin  Ver 9.0 Distrib 5.5.44-MariaDB, for debian-linux-gnu on  x86_64
Copyright (c) 2000, 2015, Oracle, MariaDB Corporation Ab and others.

Server version        5.5.44-MariaDB-1ubuntu0.14.04.1
Protocol version    10
Connection        Localhost via UNIX socket
UNIX socket        /var/run/mysqld/mysqld.sock
Uptime:            4 min 17 sec

Threads: 1  Questions: 82  Slow queries: 0  Opens: 13  Flush tables: 2  Open tables: 39  Queries per second avg: 0.319

Creamos una base de datos de prueba, para comprobar la instalación:

CREATE DATABASE pruebadb;

El comando para eliminar la base de datos sería.

DROP DATABASE pruebadb;


Si hasta aquí todo fue bien, ya podemos empezar con la creación de la base de datos del proyecto.

Creación de la base de datos customerdb y el usuario


Creamos la base de datos customerdb:

CREATE DATABASE customerdb;
Creamos el usuario que vamos a utilizar xulescode y la contraseña, en este caso la misma:

CREATE USER xulescode@localhost IDENTIFIED BY 'xulescode';

Damos todos los privilegios al usuario xulescode sobre las base de datos customerdb:

GRANT ALL PRIVILEGES ON customerdb.* TO xulescode@localhost;

El comando para eliminar la base de datos sería.

DROP DATABASE customerdb;
En este caso, para facilitar las pruebas de creación de tablas y consultas voy a utilizar uno de mis IDEs favoritos Netbeans , como entiendo que no es el más común para este tipo de desarrollos, también puedes hacer lo mismos con estos otros programas, utiliza el que ya conozcas: https://mariadb.com/kb/en/mariadb/phpmyadmin/

Características del editor SQL de Netbeans para Bases de Datos

Algunas de las características del editor Netbeans para bases de datos, son por ejemplo:
  • El soporte que proporciona directamente con la incorporación de drivers para MySQL (lo que nos sirve para MariaDB), y para otras bases de datos como Postgresql o Oracle.
    • "NetBeans IDE provides drivers for the Java DB, MySQL, Oracle, and PostgreSQL database servers so that you can connect to these databases very easily. You can also register any other JDBC driver with the IDE, so that you can explore any database that provides a JDBC driver".
    • Así, de forma fácil y solo añadiendo los datos de tu conexión a la base de datos ya tienes fácilmente tu conexión a la base de datos. Como se puede ver en la imagen de ejemplo

Java editor features in NetBeans IDE
  • Proporciona un explorador de bases de datos como se puede ver en la figura superior, desde aquí tendrás cubiertas las necesidades principales para la creación y manejo de tablas.
  • El editor SQL proporciona ayuda en el código directamente sobre la consulta que estás efectuando, también puedeas cargar un script y ejecutarlo directamente desde aquí.

Para conectar la base de datos que hemos creado simplemente completamos los parámetros que se muestran en la imagen para la conexión al servidor y listo:


Si tienes algún problema o dudas consulta este tutorial: Connecting to a MySQL Database , donde lo explican todo detalladamente.


Hasta aquí el primer post de Learning Project MariaDB Tutorial (1) (MySQL), próximamente en el siguiente post empezaremos con la creación de las tablas en nuestra base de datos.

Espero que te haya sido útil.

lunes, 14 de septiembre de 2015

Learning Project Tutorial OpenXava (2): Creación del resto de las clases para las tablas

Nos hemos trasladado a www.codigoxules.org , consulta la actualización de esta entrada en Tutorial OpenXava (2): Creación del resto de las clases para las tablas



Continuación de http://codigoxules.blogspot.com.es/2015/09/learning-project-openxava-1-empezando.html, antes de seguir con en este ejemplo te recomendamos que accedas al apartado anterior, donde se explica el proyecto que estamos implementando.


Objetivo

En este post vamos a finalizar la creación de las clases para el resto de las tablas del proyecto, nuestro objetivo es finalizar este post con todas las clases cumpliendo su funcionalidad de crear, eliminar y consultar sus datos, manejando todas las relaciones.

La parte de presentación la dejaremos para un siguiente post donde le daremos forma a nuestra pantalla.

Veamos antes de empezar un vídeo del resultado final de la definición de las clases que representan las tablas de la base de datos:






Configuración de Tomcat en Eclipse


Antes de empezar vamos a explicar como configurar Tomcat dentro de Eclipse, te recomiendo que lo hagas sino lo has hecho ya por comodidad, en la wiki de OpenXava esta muy bien explicado: Configuración de Tomcat en Eclipse, por lo que solo hago un resumen:
  • Vamos a empezar añadiendo añadiendo Tomcat como servidor de ejecución a Eclipse , para ello seleccionamos Windows > Preferences > Server > Runtime Environments y pulsamos el botón Add...
  • Escogemos Apache Tomcat v7.0
  • Seleccionamos el Tomcat incluido en OpenXava añadiendo la ruta de instalación y finalizamos.
  • Ahora vamos a añadir un servidor Tomcat a Eclipse en el menú Window > Show View > Other , siguiendo las instrucciones ya tendrás añadido el servidor.
Listo ya podemos seguir con el proyecto.

Creamos la clase CbCurrency para la tabla cb_currency


Para hacerlo fácil y comprobar que tenemos todo bien configurado creamos la clase CbCurrency para la tabla cb_currency. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_currency")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idcurrency", nullable = false)
    • private Integer idcurrency;
  • El resto es la definición de las columnas indicando su nombre, tamaño y si pueden ser o no NULL.
  • Una vez escrito este código, generamos los getters y setters para todos los valores.
package org.xulescode.customerdb.model;

import javax.persistence.*;

import org.openxava.annotations.*;
/**
 * Tabla con las monedas registradas en la aplicación, se podrá relacionar con múltiples tablas.
 * @author xulescode
 */
@Entity
@Table(name="cb_currency")
public class CbCurrency {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idcurrency", nullable = false)
    private Integer idcurrency;

    @Required
    @Column(name = "currency", length = 65, nullable = false)
    private String currency;
   
    @Required
    @Column(name = "description", length = 255, nullable = false)
    private String description;
   
    @Required
    @Column(name = "isactive", length = 1, nullable = false)
    private String isactive;

    @Required
    @Column(name = "isocode", length = 3, nullable = false)
    private String isoCode;

    @Column(name = "cursymbol", length = 10, nullable = true)
    private String cursymbol;
 

    @Required
    @Column(name = "precisionstd", length = 10, precision = 0, nullable = false)
    private java.math.BigDecimal precisionstd;

    @Required
    @Column(name = "precisioncost", length = 10, precision = 0, nullable = false)
    private java.math.BigDecimal precisioncost;

    @Required
    @Column(name = "precisionprize", length = 10, precision = 0, nullable = false)
    private java.math.BigDecimal precisionprize;
    // Generar getters y setters de todos los campos
    ...
}


Después de introducir solo este código, ya podemos acceder al módulo CbCurrency y probarlo, así de fácil, para esto te recuerdo los pasos ya explicados en el primer post, actualización de la configuración y ejecución en el servidor para hacer las pruebas:
  • En nuestro proyecto tenemos una fichero ant de ejecución build.xml con diferentes funcionalidades, nosotros usaremos ahora: desplegarWar.
  • Con esto actualizamos el war y podemos ejecutar la aplicación con las últimas actualizaciones.
  • Si actualizamos bien la configuración de Eclipse, simplemente encima de nuestro proyecto, en las opciones disponibles seleccionamos: Run As > Run on Server.

Este es el resultado:




Creamos la clase CbCountry para la tabla cb_country


Para hacerlo fácil y comprobar que tenemos todo bien configurado creamos la clase CbCountry para la tabla cb_country. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_country")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @Hidden
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idcurrency", nullable = false)
    • private Integer idcurrency;
  • Aquí con la nueva propiedad @Hidden indicamos que este campo no se muestra en la presentación de la clase aunque si se utilizará internamente, esto lo hacemos porque este es un campo interno que no tiene significado para el usuario.
  • El resto es la definición de las columnas indicando su nombre, tamaño y si pueden ser o no NULL.
  • Una vez escrito este código, generamos los getters y setters para todos los valores.

package org.xulescode.customerdb.model;

import javax.persistence.*;

import org.openxava.annotations.*;

/**
 * Tabla con los países registrados en la aplicación, se podrá relacionar con múltiples tablas.
 * @author xulescode
 */
@Entity
@Table(name="cb_country")
public class CbCountry {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idcountry", nullable = false)
    private Integer idcountry;

    @Required
    @Column(name = "country", length = 100, nullable = false)
    private String country;

    @Column(name = "description", length = 255, nullable = true)
    private String description;

    @Required
    @Column(name = "countrycode", length = 2, nullable = false)
    private String countrycode;

    @Required
    @Column(name = "hasregion", length = 1, nullable = false)
    private String hasregion;

    @Column(name = "regionname", length = 60, nullable = true)
    private String regionname;

    @Column(name = "expressionphone", length = 20, nullable = true)
    private String expressionphone;

    @Required
    @Column(name = "displaysequence", length = 20, nullable = false)
    private String displaysequence;

    @Column(name = "isdefault", length = 1, nullable = true)
    private String isdefault;

    @Column(name = "ibannodigits", length = 131089, precision = 0, nullable = true)
    private java.math.BigDecimal ibannodigits;

    @Column(name = "ibancountry", length = 2, nullable = true)
    private String ibancountry;

    @Required
    @Column(name = "isactive", nullable = false)
    private boolean isactive;
   
    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_country_idcurrency"))
    @DescriptionsList
    private CbCurrency cbCurrency;
   
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_country_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;

    // Generar getters y setters de todos los campos
    ...

}


Como habrás visto en la clase o si analizaste la relación entre tablas verás que cb_country está relacionado con cb_currency y cb_language, al igual que en la base de datos en la clase también tenemos que definir las relaciones JPA que se utilizan, esto nos será muy útil también en la presentación, ya que en OpenXava gracias a la interpretación de esta configuración JPA y de las anotaciones se nos facilita de forma muy fácil la modificación de la presentación, sin ir más allá aquí utilizaremos @DescriptionList para ver un ejemplo.
La relacion de CbCountry con CbLanguage y CbCurrency es la misma: un pais (CbCountry) puede tener un idioma (CbLanguage) seleccionano uno de todos los que existen, es decir, estamos hablando de una relación de varios a uno (ManyToOne), lo mismo sucede para CbCurrency. Expliquemoslo:
  • @ManyToOne
    • Anotación JPA con la que definimos la relación de uno a muchos de CbCurrency.
  • @JoinColumn( name = "idcurrency", nullable = true, foreignKey = @ForeignKey(name = "fk_cb_country_idcurrency"))
    • Con @JoinColumn seguimos con JPA definiendo el nombre de la columna de la base de datos por la que relacionamos estas dos tablas en este caso idcurrency, en nuestro caso como hemos utilizados un nombre específico para la clave foránea lo tenemos que indicar: foreignKey = @ForeignKey(name = "fk_cb_country_idcurrency")  donde  es el nombre que le hemos dado en la base de datos.
  • @DescriptionsList
    • Con @DescriptionsList indicamos a OpenXava para que visualice la referencia como una lista de descripciones (combo), cuando el número de valores que usamos no es muy grande esto es muy prácitco, más adelante veremos  como podemos filtrar los valores de la selección para que salga un grupo de valores según una condición y no todo el conjunto de idiomas, así como el campo seleccionado en la presentación, pero esto será más adelante, si quieres más información sobre las posibilidades de esta anotación las puedes consultar aquí: OpenXava View: @DescriptionList.
  • private CbCurrency cbCurrency;
    • En CbCountry creamos una clase CbCurrency que es la que hace referencia dentro de CbCountry a la relación y donde definimos los valores arriba descritos que indican la relación y la presentación.

Para CbLanguage la explicación es la misma como puedes ver en el código de la clase:
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_country_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;


Este es el resultado sin usar @DescriptionList, como verás en la imagen a continuación se despliega todo el contenido de CbCurrency y de CbCountry:




Este es el resultado usando @DescriptionList, como verás a continuación se muestran en un combo los contenidos de CbCurrency y de CbCountry:


Creamos la clase CbPaymentmethod para la tabla cb_paymentmethod


Para hacerlo fácil y comprobar que tenemos todo bien configurado creamos la clase CbPaymentmethod para la tabla cb_paymentmethod. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_paymentmethod")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idpaymentmethod", nullable = true)
    • private Integer idpaymentmethod;
  • Una vez escrito este código, generamos los getters y setters para todos los valores.
package org.xulescode.customerdb.model;

import javax.persistence.*;

import org.openxava.annotations.*;

/**
 * Métodos de pago definidos para el cliente u otras entidades.
 * @author xulescode
 */
@Entity
@Table(name = "cb_paymentmethod")
public class CbPaymentmethod {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idpaymentmethod", nullable = true)
    private Integer idpaymentmethod;

    @Required
    @Column(name = "paymentmethod", length = 100, nullable = false)
    private String paymentmethod;

    @Column(name = "description", length = 150, nullable = true)
    private String description;
   
    @Column(name = "paymententity", length = 50, nullable = true)
    private String paymententity;

    @Column(name = "paymentterms", length = 250, nullable = true)
    private String paymentterms;


    // Generar getters y setters de todos los campos
    ...

}


Creamos la clase CbAddresses para la tabla cb_addresses

Para hacerlo fácil y comprobar que tenemos todo bien configurado creamos la clase CbAddresses para la tabla cb_addresses. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_addresses")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idaddresses", nullable = false)
    • private Integer idaddresses;
  • Una vez escrito este código, generamos los getters y setters para todos los valores.
package org.xulescode.customerdb.model;

import java.util.*;
import javax.persistence.*;
import org.openxava.annotations.*;

/**
 * Tabla de registro de las direcciones, se asocian aquí las direcciones que tienen un cliente, cada cliente tendrá un número ilimitado de direcciones con cb_address relacionado mediante cb_addresses (es básicamente una tabla relacional).
 * @author xulescode
 */
@Entity
@Table(name = "cb_addresses")
public class CbAddresses {

    @Id
    @Hidden
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "idaddresses", nullable = true)
    private Integer idaddresses;

    @Hidden   
    @Column(name = "addressesentity", nullable = true)
    private String addressesentity;
   
    @OneToMany(
            mappedBy = "cbAddressesLocal", // El objeto de CbAddress que almacena la relación
            cascade = CascadeType.ALL)
    private Collection<CbAddress> cbAddress = new ArrayList<CbAddress>();

    // Generar getters y setters de todos los campos
    ...

}


En este caso vamos a necesitar definir una nueva relación JPA que hasta ahora no utilizamos y es @OneToMany, se usa para definir una asociación multi- valor a una colección de entidades, debido a que la relación que estamos creando es bidireccional (porque existen referencias a ambos lados de la relación ) el elemento de anotación mappedBy debe utilizarse para especificar el campo que existe en la entidad referenciada, que es el dueño de la relación, para finalizar esto, en la clase relacionada CbAddress deberemos crear un variable para esta entidad referenciada (private CbAddresses cbAddressesLocal) que será del tipo @ManyToOne como veremos a continuación.

En primer lugar analizamos la relación que necesitaremos crear en CbAddress:

  • @ManyToOne
    • Anotación JPA con la que definimos la relación de uno a muchos de CbAddresses.
  • @JoinColumn(name = "idaddresses", nullable = true, foreignKey = @ForeignKey(name = "fk_cb_address_idaddresses"))
    • Como ya vimos antes usamos la anotación @JoinColumn para especificar la columna implicada y el nombre de la clave foránea utilizada.
  • private CbAddresses cbAddressesLocal;
    • Este es la variable que vamos a tener que referenciar en CbAddresses con el campo mappedBy, es decir, esta es la relación entre CbAddresses y CbAddress que es bidireccional.
Ahora vamos a ocuparnos de la definición @OneToMany en la clase CbAddresses que estamos definiendo:

  • @OneToMany( mappedBy = "cbAddressesLocal", cascade = CascadeType.ALL)
    • Anotación JPA con la que definimos una asociación multi- valor a una colección de entidades, debido a que la relación que estamos creando es bidireccional, con mappedBy = "cbAddressesLocal" indicamos la entidad utilizada en la otra clase para la relación, es decir, el objeto CbAddress que almacena la relación, después con otros campos como cascade = CascadeType.ALL podemos especificar el comportamiento de la relación.
  • private Collection<CbAddress> cbAddress = new ArrayList<CbAddress>();
    • Variable con la que definimos CbAddress dentro de CbAddresses.

Cuando definamos CbCustormer, podremos ver más claramente cual es el objetivo de la creación de esta entidad, y su uso.

Creamos la clase CbAddress para la tabla cb_address

Creamos la clase CbAddress para la tabla cb_address. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_address")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idaddress", nullable = false)
    • private Integer idaddress;
  • El resto es la definición de las columnas indicando su nombre, tamaño y si pueden ser o no NULL.
  • Una vez escrito este código, generamos los getters y setters para todos los valores.
package org.xulescode.customerdb.model;

import javax.persistence.*;

import org.openxava.annotations.*;

/**
 * Tabla de dirección donde se guardan los datos de la dirección en sí.
 * @author xulescode
 */
@Entity
@Table(name="cb_address")
public class CbAddress {
   
    @ManyToOne
    @JoinColumn(
            name = "idaddresses",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_address_idaddresses"))
    private CbAddresses cbAddressesLocal; // Esta es la relación entre CbAddresses y CbAddress que es bidireccional.

    @Id
    @Hidden
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idaddress", nullable = true)
    private Integer idaddress;

    @Column(name = "address", nullable = true)
    private String address;

    @Column(name = "postalnumber", length = 20, nullable = true)
    private String postalnumber;

    @Column(name = "mainphone", length = 50, nullable = true)
    private String mainphone;

    @Column(name = "movilephone", length = 50, nullable = true)
    private String movilephone;

    @Column(name = "phone2", length = 50, nullable = true)
    private String phone2;

    @Column(name = "phone3", length = 50, nullable = true)
    private String phone3;

    @Column(name = "carrier", length = 200, nullable = true)
    private String carrier;

    @Column(name = "addresstype", length = 100, nullable = true)
    private String addresstype;

    @Column(name = "locality", length = 250, nullable = true)
    private String locality;

    @Column(name = "state", length = 250, nullable = true)
    private String state;
   
    @Column(name = "notes1", length = 500, nullable = true)
    private String notes1;

    @ManyToOne
    @JoinColumn(
            name = "idcountry",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_address_idcountry"))
    @DescriptionsList(descriptionProperties = "country")
    private CbCountry cbCountry;

    // Generar getters y setters de todos los campos
    ...

}


La relacion de CbCountry con CbLanguage y CbCurrency es la misma: un pais (CbCountry) puede tener un idioma (CbLanguage) seleccionano uno de todos los que existen, es decir, estamos hablando de una relación de varios a uno (ManyToOne), lo mismo sucede para CbCurrency. Expliquemoslo:
  • @ManyToOne
    • Anotación JPA con la que definimos la relación de uno a muchos de CbCountry.
  • @JoinColumn( name = "idcountry", nullable = true, foreignKey = @ForeignKey(name = "fk_cb_address_idcountry")
    • Con @JoinColumn seguimos con JPA definiendo el nombre de la columna de la base de datos por la que relacionamos estas dos tablas en este caso idcountry, en nuestro caso como hemos utilizados un nombre específico para la clave foránea lo tenemos que indicar: foreignKey = @ForeignKey(name = "fk_cb_address_idcountry")) donde  es el nombre que le hemos dado en la base de datos.
  • @DescriptionsList(descriptionProperties = "country")
    • Con @DescriptionsList indicamos que queremos usar un combo, ahora podemos ver como se puede indicar que campo usamos en el combo, esto lo conseguimos con la propiedad descriptionProperties al indicar la columna que usamos de CbCountry en este caso country.
  • private CbCountry cbCountry;
    • En CbAddress creamos la clase CbCountry que es la que hace referencia dentro de CbAddress a la relación y donde definimos los valores arriba descritos que indican la relación y la presentación.
Cuando definamos CbCustormer, podremos ver más claramente cual es el objetivo de la creación de esta entidad, y su uso. En este caso ya podemos ver una imagen de su presentacion, este es el resultado:


  • Listado de la direcciones creadas en la aplicación:

  • Veamos como se muestran los datos si seleccionamos una dirección:





Creamos la clase CbEnterprise para la tabla cb_enterprise

Creamos la clase CbEnterprise para la tabla cb_enterprise  asociamos la clase con la tabla y definimos la clave primaria:
  • Definir el nombre de la tabla: @Table(name="cb_enterprise")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @Required
    • @Column(name = "identerprise", nullable = true)
    • private Integer identerprise;
  • Definimos los campos explicados en el esquema para la tabla empresa, y finalmente, después de definir las relaciones generamos los getters y setters.

package org.xulescode.customerdb.model;

import javax.persistence.*;

import org.openxava.annotations.*;

/**
 * Empresas de la aplicación, cada empresa tendrá sus clientes.
 * @author xulescode
 */

@Entity
@Table(name = "cb_enterprise")
public class CbEnterprise {

    @Id
    @Required
    @Column(name = "identerprise", nullable = true)
    private Integer identerprise;

    @Column(name = "enterprise", length = 150, nullable = true)
    private String name;

    @Column(name = "description", length = 250, nullable = true)
    private String description;

    @Column(name = "enterprisealias", length = 100, nullable = true)
    private String enterprisealias;

    @Column(name = "contact", length = 250, nullable = true)
    private String contact;

    @Column(name = "state", length = 30, nullable = true)
    private String state;
   
    @Column(name = "balance", length = 10, precision = 3, nullable = true)
    private java.math.BigDecimal balance;

    @Column(name = "ei", length = 100, nullable = true)
    private String ei;
   
    @Column(name = "enterprisepayer", length = 20, nullable = true)
    private String enterprisepayer;
   
    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idcurrency"))
    @DescriptionsList
    private CbCurrency cbCurrency;
   
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;

    @ManyToOne
    @JoinColumn(
            name = "idcountry",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idcountry"))
    @DescriptionsList
    private CbCountry cbCountry;


    // Generar getters y setters de todos los campos
    ...

}


En el caso de CbEnterprise vamos a definir tres relaciones como se puede ver en la definición de la clase anteriormente descrita, y son las siguientes.
  • Definimos la moneda de la empresa (CbEnterprise)  mediante CbCurrency , esta es una relación de muchos a uno que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idcurrency"))
    @DescriptionsList
    private CbCurrency cbCurrency;

  • Definimos un único idioma para la empresa (CbEnterprise)  mediante CbLanguage, esta es una relación de muchos a uno que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;
  • Definimos un único país de la empresa (CbEnterprise)  mediante CbCountry, esta es una relación de muchos a uno, en este caso el país (CbCountry) podrá tener una moneda e idioma diferente al que tenga la empresa, que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idcountry",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_enterprise_idcountry"))
    @DescriptionsList
    private CbCountry cbCountry;


   
Veamos como queda la definición de una empresa:


Veamos como queda la definición de una empresa:
  • Edición de una empresa previa selección en la Lista:

  • Creación de una nueva empresa:


Creamos la clase CbCustomer para la tabla cb_customer

Para hacerlo fácil y comprobar que tenemos todo bien configurado creamos la clase CbCustomer para la tabla cb_customer. En esta primera aproximación lo único que haremos es hacer las definiciciones básicas:
  • Definir el nombre de la tabla: @Table(name="cb_customer")
  • Definimos la clave primaria de la tabla:
    • @Id
    • @Required
    • @GeneratedValue(strategy=GenerationType.IDENTITY)
    • @Column(name = "idcustomer", nullable = true)
    • private Integer idcustomer;
  • Definimos los campos explicados en el esquema para la tabla empresa, y finalmente, después de definir las relaciones generamos los getters y setters.
  • Échale un vistazo a la clase, después explicamos las relaciones implementadas.

package org.xulescode.customerdb.model;


import javax.persistence.*;

import org.openxava.annotations.*;
/**
 * Tabla general de cliente. Tabla donde se almacenarán los clientes de las diferentes empresas, se entiende cliente como aquel que compra a una empresa.
 * @author xulescode
 */
@Entity
@Table(name = "cb_customer")
public class CbCustomer {

    @Id
    @Required
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "idcustomer", nullable = true)
    private Integer idcustomer;

    @Column(name = "customer", length = 15, nullable = true)
    private String customer;

    @Column(name = "customername", length = 150, nullable = true)
    private String customername;

    @Column(name = "customeralias", length = 100, nullable = true)
    private String customeralias;

    @Column(name = "contact", length = 250, nullable = true)
    private String contact;

    @Column(name = "customerstate", length = 30, nullable = true)
    private String customerstate;

    @Column(name = "sale", length = 10, precision = 3, nullable = true)
    private java.math.BigDecimal sale;

    @Column(name = "identitynumber", length = 50, nullable = true)
    private String identitynumber;

    @Column(name = "customerpayer", length = 20, nullable = true)
    private String customerpayer;

    @ManyToOne
    @JoinColumn(
            name = "identerprise",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_identerprise"))
    @DescriptionsList
    private CbEnterprise cbEnterprise;

   
    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idcurrency"))
    @DescriptionsList
    private CbCurrency cbCurrency;
   
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;

    @ManyToOne
    @JoinColumn(
            name = "idcountry",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idcountry"))
    @DescriptionsList
    private CbCountry cbCountry;
 
    @ManyToOne
    @JoinColumn(
            name = "idpaymentmethod",
            nullable = true,
            foreignKey = @ForeignKey(name = "cb_customers_idpaymentmethod"))
    @DescriptionsList(descriptionProperties = "paymentmethod")
    private CbPaymentmethod cbPaymentmethod;
   
    @OneToOne
    @JoinColumn(
            name = "idaddresses",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idaddresses"))

    @AsEmbedded
    private CbAddresses cbAddresses;



    // Generar getters y setters de todos los campos
    ...

}


En el caso de CbCustomer vamos a definir tres relaciones como se puede ver en la definición de la clase anteriormente descrita, y son las siguientes.
  • Definimos la moneda del cliente (CbCustomer)  mediante CbCurrency , esta es una relación de muchos a uno que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idcurrency",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idcurrency"))
    @DescriptionsList
    private CbCurrency cbCurrency;

  • Definimos un único idioma para la empresa (CbCustomer)  mediante CbLanguage, esta es una relación de muchos a uno que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idlanguage",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idlanguage"))
    @DescriptionsList
    private CbLanguage cbLanguage;

  • Definimos un único país del cliente (CbCustomer)  mediante CbCountry, esta es una relación de muchos a uno, en este caso el país (CbCountry) podrá tener una moneda e idioma diferente al que tenga la empresa, que definimos así:
   
    @ManyToOne
    @JoinColumn(
            name = "idcountry",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_idcountry"))
    @DescriptionsList
    private CbCountry cbCountry;  

  • Definimos el método de pago del cliente (CbCustomer)  mediante CbLanguage, esta es una relación de muchos a uno que definimos así:
    @ManyToOne
    @JoinColumn(
            name = "idpaymentmethod",
            nullable = true,
            foreignKey = @ForeignKey(name = "cb_customers_idpaymentmethod"))
    @DescriptionsList(descriptionProperties = "paymentmethod")
    private CbPaymentmethod cbPaymentmethod;

  • Definimos las direcciones del cliente (CbCustomer) que queremos que tenga, una o varias por ello utilizamos las tablas cb_addresses que nos sirve para agrupar las direcciones del cliente y cb_address donde definimos la dirección en sí y que serán las del cliente con la relación que establecemos usando CbAddresses y CbAddress respectivamente, veamos como:
    • @OneToOne
      • Define un solo valor de asociación a otra entidad que tiene como multiplicidad uno a uno. Si la relación fuese bidireccional (que no es el caso) utilizaríamos mappedBy para completar la definición.
    • @JoinColumn( name = "idaddresses", nullable = true, foreignKey = @ForeignKey(name = "fk_cb_customer_idaddresses"))
      • Como ya explicamos antes definimos la columna implicada en la clave foránea y el nombre que utilizamos para la clave.
    • private CbAddresses cbAddresses;
      • Definición de la variable para definir la relación. En el siguiente post donde mejoramos la presentación para incrustar las direcciones directamente haciendo CbAddresses transparente para el usuario. En las imágenes del final puedes ver la presentación de las direcciones.

  • Y por último definimos la empresa a la que se asigna el cliente, con lo que en nuestro proyecto una empresa podrá tener uno o varios cliente, y cada cliente podrá pertenecer únicamente a una empresa:
    @ManyToOne
    @JoinColumn(
            name = "identerprise",
            nullable = true,
            foreignKey = @ForeignKey(name = "fk_cb_customer_identerprise"))
    @DescriptionsList
    private CbEnterprise cbEnterprise;

Veamos algunas imágenes de CbCustomer:
  • Lista de los clientes, en este caso solo tenemos uno creado:


  • Modo edición del cliente seleccionado, donde puedes ver todas las clases que hemos relacionado: CbEnterprise, CbCurrency, CbLanguage, CbCountry, CbPaymentmethod y CbAddresess:




  • Detalle de las direcciones del cliente, puedes como aparecen representadas las dos clases utilizadas: CbAddresses y CbAddress. Desde aquí podemos añadire nuevas direcciones o cambiar por completo la CbAddresses asociada al cliente (esto no es correcto y veremos como mejorarlo en el siguiente post).



Hasta aquí el segundo post del tutorial de OpenXava, en el siguiente post adaptaremos la presentación utilizando todas las utilidades que nos da OpenXava mediante las anotaciones y otras implementaciones.