viernes, noviembre 05, 2004

Una aproximación básica a Hibernate

Las clases persistentes son aquellas que están relacionadas con tablas en una base de datos. Supongamos una versión simplificada de una clase Project:

public class Project {
  private Long id;
  private String name;
  private Company company;
    
  public Long getId() {
    return id;
  }
  public void setId() {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public Company getCompany() {
    return company;
  }
  public void setCompany(Company company) {
    this.company = company;
  }
}


en ella tenemos tres atributos: el identificador, el nombre y una referencia a Company.
El identificador, en este caso un Long, podría haber sido cualquier objeto y nos permitirá acceder a la clave primaria en la base de datos. El resto de los atributos tiene sus respectivos accesores / mutadores como cualquier JavaBean y la clase tiene definida implícitamente el constructor por defecto (sin argumentos) necesario para que Hibernate pueda hacer Constructor.newInstance().
Estas características de nuestras clases persistentes, hacen que se no dependa específicamente de ninguna tecnología de persistencia, clases o interfaces tal y como sucede con EJB y los entity beans. Por lo que podemos instanciar y comprobar el funcionamiento de la clase afuera de cualquier contenedor.
La siguiente clase, Company, la definiremos así:

public class Company {
  private Long id;
  private String name;
    
  public Long getId() {
    return id;
  }
  public void setId() {
    this.id = id;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
}


¿Como hacemos para que Hibernate persista estas clases? Definiendo (manualmente o con ayuda de herramientas) un fichero XML por clase donde especificaremos la información necesaria, y utilizando las interfaces Session y Transaction de Hibernate.
El fichero XML (XML mapping document) define de que manera las propiedades de la clase Project se corresponden con columnas de la tabla projects de la base de datos.
Para Project crearemos Project.hbm.xml en el classpath:
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="com.example.model.Project" table="projects">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<many-to-one name="company" cascade="all" column="company_id"/>
</class>
</hibernate-mapping>
Y para Company crearemos Company.hbm.xml:
<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="com.example.model.Company" table="companies">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>
Asumiendo que existe en nuestro classpath un fichero hibernate.properties con los parámetros de conexión a la base de datos (entre otros posibles), podremos crear un proyecto y persistirlo:

import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

...

Configuration cfg = new Configuration();
cfg.addResource("Project.hbm.xml");
cfg.setPropertiesSystem.getProperties() );
SessionFactory sf = cfg.buildSessionFactory();

Session s = sf.openSession();
Transaction tx = s.beginTransaction();

Company company = new Company();
company.setName("Mi empresa");
Project project = new Project();
project.setName("MwM");
project.setCompany(company);

s.save(project);
tx.commit();
s.close();


con lo cual Hibernate generará las siguientes sentencias SQL:
insert into companies (id, name) values (1, "Mi empresa");

insert into projects (id, name, id_company) values (1, "MwM", 1);
Como se puede ver, simplemente guardando Project Hibernate guarda también, mediante cascade save, los objetos dependientes como Company.
Aunque haya sido una aproximación inicial muy básica al mundo Hibernate, esta punta del iceberg nos deja entrever muchas de las características que ofrece. Queda para otra ocasión, como hacer que Hibernate genere el esquema de base de datos y explorar en profundidad sus opciones de configuración y su idioma de query (HQL).

5 comentarios:

Anónimo dijo...

Todo este perfecto
pero me podrias ayudar sobre como insertar una fecha que no sea la actual a un BD en Oracle no consigo hacerlo esto es lo que intento.
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
session =sessionFactory.openSession();


Transaction tx = session.beginTransaction();



//Create new instance of Contact and set values in it by reading them from form object
System.out.println("Inserting Record");
Usuario usuario = new Usuario();
usuario.setIdusu(20);
usuario.setUsu("SISTEMAS");
usuario.setCve("CHECKBOLT");
usuario.setNom("ALICIA LOPEZ");
usuario.setHpul("5698511256824");
usuario.setHind("98751511129226");
usuario.setHmed("9645123511147283");
usuario.setFecalt(new Date(12-10-1994));
usuario.setFecbaj(new Date(14-12-1994));
usuario.setFeccamcla(new Date(14-12-1994));
usuario.setEsblo("1");
usuario.setIdjer(123459);


session.save(usuario);
tx.commit();
System.out.println("Done");
}catch(Exception e){
System.out.println(e.getMessage());
}finally{
// Actual contact insertion will happen at this step
session.flush();

session.close();

}

attentamente

Anónimo dijo...

soy estudiante de la universidad santiago de cali (colombia) tengo como proyecto de grado llegar a grandes aproximaciones sobre el hibernate,, necesito saber si el hibernate permite mapear grandes cantidades de una BDR,, es decir si existe algunas limitaciones

Anónimo dijo...

disculpa tengo problemas para encontrar una libreria que es: net.sf.hibernate.SessionFactory por favor agradeceria tu ayuda si me dices donde la puedo descargar

Gracias..!

por favor envie la respuesta darwel34@yahoo.es.

Anónimo dijo...

Muy bueno, pero me interesaria algo ya mas avanzado .. claro si es que se puede.

Lau dijo...

Para la inserción esto está muy bien, pero para el borrado, a mí me sucede que con esta configuración al eliminar un registro "hijo" se elimina también el padre.
¿qué otras configuraciones hay a parte de cascade=all?