====== Tipos básicos ======
Al mapear una propiedad de una clase Java a una columna de base de datos podemos especificar el tipo. Ésto es posible ya que algunos tipos de Java pueden mapearse de distintas formas en la base de datos. Por ello Hibernate permite especificar un tipo más concreto para cada propiedad Java.
===== Tipos en Hibernate =====
La lista de los tipos más usados en Hibernate es la siguiente(( En el apartado de referencias podremos encontrar el listado completo de tipos de Hibernate. )):
^ Tipo Hibernate ^ Tipo Java ^ Tipo base de datos (MySQL) ^
| integer | int , java.lang.Integer | INTEGER |
| long | long, java.lang.Long | BIGINT |
| short | short , java.lang.Short | SMALLINT |
| float | float , java.lang.Float | FLOAT |
| double | double , java.lang.Double | DOUBLE |
| character | char , java.lang.Character | CHAR |
| byte | byte , java.lang.Byte | TINYINT |
| boolean | boolean , java.lang.Boolean | TINYINT. Guarda el ''true'' como "''1''" y el ''false'' como "''0''" |
| yes_no | boolean , java.lang.Boolean | CHAR(1). Guarda el ''true'' como "''Y''" y el ''false'' como "''N''" |
| true_false | boolean , java.lang.Boolean | CHAR(1). Guarda el ''true'' como "''T''" y el ''false'' como "''F''" |
| string | java.lang.String | VARCHAR |
| date | java.util.Date | DATE. Solo se guarda solo la información de la fecha (año, mes y día) |
| time | java.util.Date | TIME. Solo se guarda solo la información de la hora (horas, minutos y segundos) |
| timestamp | java.util.Date | DATETIME. Se guarda la información de la fecha y la hora (año, mes , día, horas, minutos y segundos) |
| text | java.lang.String | LONGTEXT |
| binary | byte[] | TINYBLOB |
| big_decimal | java.math.BigDecimal | DECIMAL |
| big_integer | java.math.BigInteger | DECIMAL |
Como podemos ver , los tipos Java java.util.Date,java.lang.Boolean y java.lang.String pueden ser guardados en la base de datos en más de una forma.Pasemos ahora a ver cada una de dichas formas.
==== Fecha y hora ====
En java se suele cometer el error de pensar que la clase java.util.Date guarda únicamente los datos de año, mes y día. Desgraciadamente se guardan también los datos de horas, minutos y segundos.Así que ¿qué hacemos para guardar únicamente la fecha o únicamente la hora en la base de datos?.
La forma entonces de guardar únicamente la fecha o únicamente la hora o ambas cosas usando hibernate es especificar los tipos ''date '', ''time'' o ''timestamp''. Si no especificamos el tipo a Hibernate para un java.util.Date por defecto se usará el tipo ''timestamp'' con lo que se guardará la información de la fecha y la hora.
* **''date''** : Con este tipo de Hibernate se almacenará un java.util.Date en la base de datos guardando únicamente la fecha (año, mes y día).
* **''time''** : Con este tipo de Hibernate se almacenará un java.util.Date en la base de datos guardando únicamente la hora (horas, minutos y segundos).
* **''timestamp''** : Con este tipo de Hibernate se almacenará un java.util.Date en la base de datos guardando la fecha y la hora (año, mes, día, horas, minutos y segundos). Este tipo no es necesario usarlo ya que es el tipo por defecto para las propiedades de tipo java.util.Date.
Actualmente en Java no hay forma estándar de guardar en un objeto únicamente la fecha (año, mes y día) o únicamente la hora (horas, minutos y segundos). Bueno, están las clases java.sql.Date y java.sql.Time pero esas clases se han creado para tratar directamente con JDBC y no es recomendable usarlas fuera del contexto del acceso a la base de datos mediante JDBC. Es decir, que las clases del paquete ''java.sql'' nunca se deberían usar en el código de nuestras clases de negocio o de entidad. En Java 8 se piensan definir nuevas clases relativas a la fecha y la hora, de forma que estén separadas la fecha y la hora. El trabajo está siendo desarrollado por el [[wpes>Java_Community_Process|JCP]] en el [[http://jcp.org/en/jsr/detail?id=310|JSR-310: Date and Time API]].
==== Boolean ====
Hibernate permite 3 formas distintas de almacenar un booleano de Java en la base de datos. Para ello existen 3 tipos de datos en hibernate.
* **''boolean''**: Es la forma estándar de guardar un booleano en la base de datos.
* **''yes_no''**: El valor se guardará como un CHAR(1) con los valores de ''Y'' y ''N'' para ''true'' y ''false'' respectivamente.
* **''true_false''**: El valor se guardará como un CHAR(1) con los valores de ''T'' y ''F'' para ''true'' y ''false'' respectivamente.
==== Texto ====
Hibernate permite 2 formas distintas de almacenar un java.lang.String de Java en la base de datos. Para ello existen 2 tipos de datos en hibernate.
* **''string''**: Se guardará el java.lang.String como un ''VARCHAR'' en la base de datos.
* **''text''**: Se guardará el java.lang.String como un ''CLOB'' o ''TEXT'' ,etc. en la base de datos.
===== Clases Java =====
Ahora que tenemos claro qué tipo de dato de Hibernate debemos usar para cada propiedad de Java, pasemos a explicar cómo se debe indicar dicho tipo de datos.
Para explicarlo usaremos el siguiente código Java.
public class TiposBasicos implements Serializable {
private int inte;
private long long1;
private short short1;
private float float1;
private double double1;
private char character1;
private byte byte1;
private boolean boolean1;
private boolean yesno1;
private boolean truefalse1;
private String stri;
private Date dateDate;
private Date dateTime;
private Date dateTimestamp;
private String texto;
private byte[] binario;
private BigDecimal bigDecimal;
private BigInteger bigInteger;
public TiposBasicos() {
}
}
En la clase Java TiposBasicos no se han incluido los métodos get/set de cada propiedad para facilitar la lectura pero deben estar en la clase Java.
El siguiente diagrama UML muestra la clase TiposBasicos:
class TiposBasicos
TiposBasicos : int inte
TiposBasicos : long long1
TiposBasicos : short short1
TiposBasicos : float float1
TiposBasicos : double double1
TiposBasicos : char character1
TiposBasicos : byte byte1
TiposBasicos : boolean boolean1
TiposBasicos : boolean yesno1
TiposBasicos : boolean truefalse1
TiposBasicos : String stri
TiposBasicos : Date dateDate
TiposBasicos : Date dateTime
TiposBasicos : Date dateTimestamp
TiposBasicos : String texto
TiposBasicos : byte[] binario
TiposBasicos : BigDecimal bigDecimal
TiposBasicos : BigInteger bigInteger
Para las propiedades Java que tienen más de una forma de guardarse en la base de datos vamos a indicar el tipo concreto de hibernate que se va a usar:
^ Propiedad Java ^ Tipo Hibernate ^
| dateDate | date |
| dateTime | time |
| dateDateTime | timestamp |
| booleanSimple | boolean |
| booleanYesno | yes_no |
| booleanTruefalse | true_false |
| stri | string |
| stringClob | text |
===== Tablas =====
La tabla de base de datos quedarían de la siguiente forma:
class TiposBasicos <>
TiposBasicos : INTEGER inte
TiposBasicos : BIGINT long1
TiposBasicos : SMALLINT short1
TiposBasicos : FLOAT float1
TiposBasicos : DOUBLE double1
TiposBasicos : CHAR[1] character1
TiposBasicos : TINYINT byte1
TiposBasicos : TINYINT boolean1
TiposBasicos : CHAR[1] yesno1
TiposBasicos : CHAR[1] truefalse1
TiposBasicos : VARCHAR[255] stri
TiposBasicos : DATE dateDate
TiposBasicos : TIME dateTime
TiposBasicos : DATETIME dateTimestamp
TiposBasicos : LONGTEXT texto
TiposBasicos : TINYBLOB binario
TiposBasicos : DECIMAL bigDecimal
TiposBasicos : DECIMAL bigInteger
===== Fichero de mapeo ''.hbm.xml'' =====
Para persistir la clase es necesario el fichero de persistencia:
* TiposBasicos.hbm.xml
Podemos ver cómo cada propiedad Java se almacenará en la base de datos según el tipo de Hibernate que le hemos definido.
El atributo ''type'' de cada tag '''' se usa para especificar el tipo hibernate de cada propiedad Java.El atributo ''name'' se usa para indicar el nombre de la propiedad Java.
Al definir que una propiedad Java es la clave primaria mediante el tag '''' también se usa el atributo ''type'' para indicar el tipo de Hibernate.
No es necesario indicar el tipo de las propiedades Java que tienen una única correspondencia con los tipos de hibernate o si él ya elige la correcta por defecto. Es decir no hace falta indicar el tipo para las propiedaes ''int'', ''float'' , etc. Sin embargo hibernate recomienda ponerlas ya que se mejora el rendimiento al arrancar la aplicación puesto que así Hibernate se evita tener que ir clase por clase para averiguar su tipo. El tiempo de arranque de una aplicación puede ser muy crítico en entornos como [[https://developers.google.com/appengine/?hl=es|Google App Engine]].
===== Anotaciones =====
Como ya hemos visto es posible prescindir del fichero ''.hbm.xml'' anotando el código directamente.
El código fuente de la clase ''TiposBasicos'' queda de la siguiente forma:
@Entity
@Table(name="TiposBasicos")
public class TiposBasicos implements Serializable {
@Id
@Type(type="integer")
private int inte;
@Type(type="long")
private long long1;
@Type(type="short")
private short short1;
@Type(type="float")
private float float1;
@Type(type="double")
private double double1;
@Type(type="character")
private char character1;
@Type(type="byte")
private byte byte1;
@Type(type="boolean")
private boolean boolean1;
@Type(type="yes_no")
private boolean yesno1;
@Type(type="true_false")
private boolean truefalse1;
@Type(type="string")
private String stri;
@Temporal(TemporalType.DATE)
private Date dateDate;
@Temporal(TemporalType.TIME)
private Date dateTime;
@Temporal(TemporalType.TIMESTAMP)
private Date dateTimestamp;
@Lob
private String texto;
@Type(type="binary")
private byte[] binario;
@Type(type="big_decimal")
private BigDecimal bigDecimal;
@Type(type="big_integer")
private BigInteger bigInteger;
public TiposBasicos() {
}
}
Vemos como sobre cada una de las propiedades Java añadimos las anotaciones para indicar su tipo. Indicar que se han usado notaciones estándar de JPA y propietarias de Hibernate.
Veamos ahora el significado de cada una de las anotaciones:
* **''@Temporal(TemporalType.DATE)''** : Indica el tipo de datos de hibernate de ''date''. Es una anotación estándar de JPA.
* **''@Temporal(TemporalType.TIME)''** : Indica el tipo de datos de hibernate de ''time''. Es una anotación estándar de JPA.
* **''@Temporal(TemporalType.TIMESTAMP)''** : Indica el tipo de datos de hibernate de ''timestamp''. Es una anotación estándar de JPA.
* **''@Lob''** : Indica el tipo de datos de hibernate de ''text''. Es una anotación estándar de JPA.
* **''@Type''** : Esta anotación indica el tipo de datos de hibernate.Esta notación es específica de Hibernate
* **type**: Este atributo contiene el tipo concreto de Hibernate. Sus posibles valores se han indicado en la tabla del principio de este tema.
Como podemos ver el estándar de JPA no soporta los tipos de hibernate ''yes_no'' y ''true_false'', la cual cosa no debería extrañarnos ya que no es muy ortodoxa. Pero , ¿porqué no hay una anotación éstandar en JPA para los tipos ''integer'', ''double'', etc.? La respuesta es simple. Porque no es necesario ya que el estándar de JPA indica que se usará el propio tipo de la propiedad Java, así que no es necesario indicárselo. Es decir, si el tipo Java es ''float'', ¿para qué crear una anotación para indicar que su tipo de Hibernate es ''float''?.
Como en el caso de del fichero de mapeo ''.hbm.xml'' no es necesario indicar todos los tipos.
===== Código Java =====
Ahora que ya tenemos preparada la clase Java para que pueda persistirse veamos el código necesario para persistirla.
Date date=new Date();
byte array[]={(byte)0x45,(byte)0xF5,(byte)0x3A,(byte)0x67,(byte)0xFF};
TiposBasicos tiposBasicos1=new TiposBasicos();
tiposBasicos1.setInte(1);
tiposBasicos1.setLong1(12);
tiposBasicos1.setShort1((short)13);
tiposBasicos1.setFloat1(14.1F);
tiposBasicos1.setDouble1(15.2);
tiposBasicos1.setCharacter1('W');
tiposBasicos1.setByte1((byte)16);
tiposBasicos1.setBoolean1(true);
tiposBasicos1.setYesno1(true);
tiposBasicos1.setTruefalse1(true);
tiposBasicos1.setStri("Hola mundo");
tiposBasicos1.setDateDate(date);
tiposBasicos1.setDateTime(date);
tiposBasicos1.setDateTimestamp(date);
tiposBasicos1.setTexto("texto muyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy largo");
tiposBasicos1.setBinario(array);
tiposBasicos1.setBigDecimal(new BigDecimal("0.3"));
tiposBasicos1.setBigInteger(new BigInteger("5345345324532"));
TiposBasicos tiposBasicos2=new TiposBasicos();
tiposBasicos2.setInte(2);
tiposBasicos2.setLong1(12);
tiposBasicos2.setShort1((short)13);
tiposBasicos2.setFloat1(14.1F);
tiposBasicos2.setDouble1(15.2);
tiposBasicos2.setCharacter1('W');
tiposBasicos2.setByte1((byte)16);
tiposBasicos2.setBoolean1(false); //<<--- Cambiado a false
tiposBasicos2.setYesno1(false); //<<--- Cambiado a false
tiposBasicos2.setTruefalse1(false); //<<--- Cambiado a false
tiposBasicos2.setStri("Hola mundo");
tiposBasicos2.setDateDate(date);
tiposBasicos2.setDateTime(date);
tiposBasicos2.setDateTimestamp(date);
tiposBasicos2.setTexto("texto muyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy largo");
tiposBasicos2.setBinario(array);
tiposBasicos2.setBigDecimal(new BigDecimal("0.3"));
tiposBasicos2.setBigInteger(new BigInteger("5345345324532"));
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(tiposBasicos1);
session.save(tiposBasicos2);
session.getTransaction().commit();
session.close();
En las líneas de 12 a 14 y 32 a 34 se guardan booleanos pero al tener distinto tipo de hibernate en la base de datos se guardará distinta información para cada uno de los 3 tipos. Por ello se guardan también 2 objetos ''TiposBasicos'' para ver las diferencias al guardar un ''true'' o un ''false''.
En las líneas de 16 a 18 y 36 a 38 se guarda el mismo objeto ''date'' pero al tener distinto tipo de hibernate en la base de datos se guardará distinta información para cada uno de los 3 tipos.
===== Referencias =====
* [[http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch05.html#mapping-types-basictypes|Hibernate Basic value types]]: Listado completo de los tipos que soporta Hibernate.
* [[http://dev.mysql.com/doc/refman/5.6/en/datetime.html|MySQL 5.6 Reference Manual.The DATE, DATETIME, and TIMESTAMP Types]]: Información de referencia de MySQL sobre los tipos de datos de hora y fecha.
* [[http://jcp.org/en/jsr/detail?id=310|JSR-310: Date and Time API]]: JSR-310 sobre las nuevas clases de fecha y hora en Java 8.
* [[http://javarevisited.blogspot.com.es/2012/04/difference-between-javautildate-and.html|Difference between java.util.Date and java.sql.Date in Java - JDBC Question]]: Diferencias entre java.util.Date y java.sql.Date.
* [[https://developers.google.com/appengine/?hl=es|Google App Engine]]