Hibernate - Mapeamentos de componentes
UMA Componentmapeamento é um mapeamento para uma classe tendo uma referência a outra classe como uma variável de membro. Vimos esse mapeamento tendo duas tabelas e usando o elemento <set> no arquivo de mapeamento. Agora usaremos o elemento <component> no arquivo de mapeamento e uma única tabela seria usada para manter os atributos contidos na variável de classe.
Definir tabelas RDBMS
Considere uma situação em que precisamos armazenar nossos registros de funcionários na tabela EMPLOYEE que terá a seguinte estrutura -
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
Além disso, suponha que cada funcionário terá um endereço, então vamos adicionar campos específicos de endereço na mesma tabela da seguinte forma -
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
street_name VARCHAR(40) default NULL,
city_name VARCHAR(40) default NULL,
state_name VARCHAR(40) default NULL,
zipcode VARCHAR(10) default NULL,
PRIMARY KEY (id)
);
Definir classes POJO
Vamos implementar nossa classe POJO Employee, que será usado para persistir os objetos relacionados à tabela EMPLOYEE.
import java.util.*;
public class Employee implements java.io.Serializable {
private int id;
private String firstName;
private String lastName;
private int salary;
private Address address;
public Employee() {}
public Employee(String fname, String lname, int salary, Address address ) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
this.address = address;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
public Address getAddress() {
return address;
}
public void setAddress( Address address ) {
this.address = address;
}
}
Precisamos definir outra classe POJO correspondente à entidade ADDRESS com campos relacionados ao endereço.
import java.util.*;
public class Address{
private int id;
private String street;
private String city;
private String state;
private String zipcode;
public Address() {}
public Address(String street, String city, String state, String zipcode) {
this.street = street;
this.city = city;
this.state = state;
this.zipcode = zipcode;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet( String street ) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity( String city ) {
this.city = city;
}
public String getState() {
return state;
}
public void setState( String state ) {
this.state = state;
}
public String getZipcode() {
return zipcode;
}
public void setZipcode( String zipcode ) {
this.zipcode = zipcode;
}
}
Definir arquivo de mapeamento do Hibernate
Vamos desenvolver nosso arquivo de mapeamento, que instrui o Hibernate como mapear as classes definidas para as tabelas do banco de dados. O elemento <component> será usado para definir a regra para todos os campos associados à tabela ADDRESS.
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name = "Employee" table = "EMPLOYEE">
<meta attribute = "class-description">
This class contains the employee detail.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<component name = "address" class="Address">
<property name = "street" column = "street_name" type = "string"/>
<property name = "city" column = "city_name" type = "string"/>
<property name = "state" column = "state_name" type = "string"/>
<property name = "zipcode" column = "zipcode" type = "string"/>
</component>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
</hibernate-mapping>
Você deve salvar o documento de mapeamento em um arquivo com o formato <classname> .hbm.xml. Salvamos nosso documento de mapeamento no arquivo Employee.hbm.xml. Você já está familiarizado com a maioria dos detalhes de mapeamento, mas vamos ver todos os elementos do arquivo de mapeamento mais uma vez -
O documento de mapeamento é um documento XML com <hibernate-mapping> como o elemento raiz que contém dois elementos <class> correspondentes a cada classe.
o <class>elementos são usados para definir mapeamentos específicos de classes Java para as tabelas do banco de dados. O nome da classe Java é especificado usando oname atributo do elemento de classe e o nome da tabela do banco de dados é especificado usando o table atributo.
o <meta> element é um elemento opcional e pode ser usado para criar a descrição da classe.
o <id>elemento mapeia o atributo de ID exclusivo na classe para a chave primária da tabela do banco de dados. oname atributo do elemento id refere-se à propriedade na classe e o columnatributo refere-se à coluna na tabela do banco de dados. otype atributo contém o tipo de mapeamento de hibernação, esses tipos de mapeamento serão convertidos do tipo de dados Java para SQL.
o <generator>O elemento dentro do elemento id é usado para gerar os valores da chave primária automaticamente. oclass atributo do elemento gerador é definido como native para deixar a hibernação pegar também identity, sequence ou hilo algoritmo para criar a chave primária, dependendo dos recursos do banco de dados subjacente.
o <property>elemento é usado para mapear uma propriedade de classe Java para uma coluna na tabela de banco de dados. oname atributo do elemento refere-se à propriedade na classe e o columnatributo refere-se à coluna na tabela do banco de dados. otype atributo contém o tipo de mapeamento de hibernação, esses tipos de mapeamento serão convertidos do tipo de dados Java para SQL.
o <component> O elemento define a existência de diferentes atributos da classe Address dentro das classes Employee.
Criar classe de aplicativo
Por fim, criaremos nossa classe de aplicativo com o método main () para executar o aplicativo. Usaremos este aplicativo para salvar alguns registros de Funcionários junto com seus certificados e, em seguida, aplicaremos as operações CRUD nesses registros.
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try {
factory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* Let us have one address object */
Address address1 = ME.addAddress("Kondapur","Hyderabad","AP","532");
/* Add employee records in the database */
Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address1);
/* Let us have another address object */
Address address2 = ME.addAddress("Saharanpur","Ambehta","UP","111");
/* Add another employee record in the database */
Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address2);
/* List down all the employees */
ME.listEmployees();
/* Update employee's salary records */
ME.updateEmployee(empID1, 5000);
/* List down all the employees */
ME.listEmployees();
}
/* Method to add an address record in the database */
public Address addAddress(String street, String city, String state, String zipcode) {
Session session = factory.openSession();
Transaction tx = null;
Integer addressID = null;
Address address = null;
try {
tx = session.beginTransaction();
address = new Address(street, city, state, zipcode);
addressID = (Integer) session.save(address);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return address;
}
/* Method to add an employee record in the database */
public Integer addEmployee(String fname, String lname, int salary, Address address){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try {
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary, address);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to list all the employees detail */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator = employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
Address add = employee.getAddress();
System.out.println("Address ");
System.out.println("\tStreet: " + add.getStreet());
System.out.println("\tCity: " + add.getCity());
System.out.println("\tState: " + add.getState());
System.out.println("\tZipcode: " + add.getZipcode());
}
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
/* Method to update salary for an employee */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
Employee employee = (Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
}
}
Compilação e execução
Aqui estão as etapas para compilar e executar o aplicativo mencionado acima. Certifique-se de ter definido PATH e CLASSPATH apropriadamente antes de prosseguir para a compilação e execução.
Crie o arquivo de configuração hibernate.cfg.xml conforme explicado no capítulo de configuração.
Crie o arquivo de mapeamento Employee.hbm.xml conforme mostrado acima.
Crie o arquivo de origem Employee.java conforme mostrado acima e compile-o.
Crie o arquivo de origem ManageEmployee.java conforme mostrado acima e compile-o.
Execute o binário ManageEmployee para executar o programa.
Você obteria o seguinte resultado na tela, e os mesmos registros de tempos seriam criados na tabela EMPLOYEE.
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Manoj Last Name: Kumar Salary: 4000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
First Name: Manoj Last Name: Kumar Salary: 5000
Address
Street: Kondapur
City: Hyderabad
State: AP
Zipcode: 532
First Name: Dilip Last Name: Kumar Salary: 3000
Address
Street: Saharanpur
City: Ambehta
State: UP
Zipcode: 111
Se você verificar sua tabela de FUNCIONÁRIOS, ela deve ter os seguintes registros -
mysql> select id, first_name,salary, street_name, state_name from EMPLOYEE;
+----+------------+--------+-------------+------------+
| id | first_name | salary | street_name | state_name |
+----+------------+--------+-------------+------------+
| 1 | Manoj | 5000 | Kondapur | AP |
| 2 | Dilip | 3000 | Saharanpur | UP |
+----+------------+--------+-------------+------------+
2 rows in set (0.00 sec)
mysql>