Como mapear classes no hibernate através de arquivos.xml

8 respostas
M

Estou com dúvida sobre mapeamentos!

Os dois trechos são de associações one to many, o primeiro exemplo é tirado deste link
http://www.xylax.net/hibernate/onetomany.html e representa o seguinte mapeamento:

[img][/img]

Este é o código:
<class name="Foo" table="foo">
    ...
    <set role="bars" table="bar">
        <key column="foo_id"/>
        <one-to-many class="Bar"/>
    </set>
</class>
Já este outro exemplo faz a mesma coisa só que com tabelas diferentes, porém o mapeamento é de one-to-many: Tabela cliente:
<class name='br.com.integrator.model.Cliente' table='clientes'>
...
<set  inverse='true' name='pedido'>
         <key column='clienteid_id' foreign-key='fk_pedidos_clienteid_key'/>
         <one-to-many class='br.com.integrator.model.Pedido' />
</set>
Tabela pedido:
<class name='br.com.integrator.model.Pedido' table='pedidos'>
      <id name='pedidoid' type='integer' column='pedidoid'>
         <generator class='native' />
      </id>
      <set  inverse='true' name='detalhesPedido'>
         <key column='pedidoid_id' foreign-key='fk_detalhes_pedido_pedidoid_key'/>
         <one-to-many class='br.com.integrator.model.DetalhesPedido' />
      </set>
      <many-to-one  foreign-key='fk_pedidos_clienteid_id' column='clienteid' class='br.com.integrator.model.Cliente' name='cliente' />
      <property  column='datapedido' type='date' name='datapedido'>
      </property>
   </class>

O 2º exemplo foi feito no netbeans, exemplo do livro do edson gonçalves.

Não entendo porque os comandos são diferentes.
Qual a necessidade do exemplo 2 especificar essa foreign-key? O primeiro exemplo não especificou pq?

O primeiro exemplo faz o mapeamento tão simples, já no segundo se torna um tanto quanto complicado, por exemplo: esse trecho:
foreign-key='fk_pedidos_clienteid_key'
essa fk... eu escrevo o que quiser? pois na no sql nao existe nenhuma chave com esse nome, fk_pedidos_cli...
CREATE TABLE `clientes` (
  `ClienteID` char(5) NOT NULL,
  `nome` varchar(30) default NULL,
  `cargo` varchar(30) default NULL,
  `endereco` varchar(60) default NULL,
  `cidade` varchar(15) default NULL,
  `cep` varchar(10) default NULL,
  `pais` varchar(15) default NULL,
  `telefone` varchar(24) default NULL,
  `Fax` varchar(24) default NULL,
  PRIMARY KEY  (`ClienteID`),
  KEY `cidade` (`cidade`),
  KEY `cep` (`cep`)
)
CREATE TABLE `pedidos` (
  `PedidoID` int(11) NOT NULL auto_increment,
  `ClienteID` char(5) default NULL,
  `dataPedido` datetime default NULL,
  PRIMARY KEY  (`PedidoID`),
  KEY `CustomerID` (`ClienteID`),
  CONSTRAINT `fk_clientes` FOREIGN KEY (`ClienteID`) REFERENCES `clientes` (`ClienteID`)
)

8 Respostas

M

up

M

Olá. Por que você não utiliza Annotations? Dê uma olhada na apostila FJ-28 da caelum. Abraços…

M
Usando o Annotations eu vou precisar desses dois arquivos?
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://192.168.0.2:3306/paroquia</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">123</property>
    <mapping class="minha classe" package="minha classe.hbm.xml" resource="minha classe.hbm.xml"/>
  </session-factory>
</hibernate-configuration>
e deste:
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;


public class IniciaHibernate {
    
    private static final ThreadLocal<Session> tl = new ThreadLocal<Session>();
    private static SessionFactory sf;

    static {
        try {
            sf = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Erro na classe IniciaHibernate.\n" + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() {
        Session sessao = (Session)tl.get();
        sessao = sf.openSession();
        tl.set(sessao);
        return sessao;
    }
}
E

moacirjava:
Estou com dúvida sobre mapeamentos!

<class name="Foo" table="foo">
    ...
    <set role="bars" table="bar">
        <key column="foo_id"/>
        <one-to-many class="Bar"/>
    </set>
</class>

Ele estah fazendo um mapeamento onde ele referencia a tabela foo com a tabela Bar, e do qual ele estah criado uma lista da classe bar do qual eh chama de bars dentro da classe foo. E se ele nao colocou o package antes da classe eh pq as classes estah no mesmo package, entao nao ah necessidade de colocar todo o caminha da classe para referenciá-la. logo sua classe Bar ficaria algo assim:

Public classe Bar{
private Set<Bar> bars;

//metodos encapsuladores(gets e sets)

}
  1. Sim vc estah correto faz a mesma coisa, mas de uma maneira mais complexa e estranha. no caso uma outra maneira de mapear a lista ao meu ver seria assim:
//hbm
 <class name='br.com.integrator.model.Cliente' table='clientes'>  
 ... 
 <bag name="listPedido" table="TABELA_PEDIDO" inverse="true">
	<key>
		<column name="ID_CLIENTE" />
	</key>
	<one-to-many class="br.com.integrator.model.Pedido" />
 </bag>

//classe
Public classe Bar{
 private List<Pedido>listPedido;
  
 //metodos encapsuladores(gets e sets)
}
  1. Ele quis mostrar uma outra forma de mapear uma lista de Pedidos na classe Cliente usando foreign-key(do qual serah necessario nesse caso).

  2. Idem resposta 2

  1. Não vc nao escre oq quiser vc apenas vai referenciar a chave estrangeira com a chave primaria. Olha exemplo que te passei acima acho q estah mais claro.

  2. Sim existe, toda vez que vc cria uma chave estrangeira para referenciar uma tabela com a outra elA irá criar uma constraint foreign key na sua tabela com as iniciais FK+NOME_DA_TABELA_DESTINO+NOME_DA_TABELA_ORIGEM.

E
moacirjava:
Usando o Annotations eu vou precisar desses dois arquivos?
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.url">jdbc:mysql://192.168.0.2:3306/paroquia</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">123</property>
    <mapping class="minha classe" package="minha classe.hbm.xml" resource="minha classe.hbm.xml"/>
  </session-factory>
</hibernate-configuration>

O arquivo hibernate.cfg.xml vc sempre vai ter independente de estar usando annotations ou não, pois eh nela que vc vai dizer no caso das anotações quais sao classes e serem mapeadas, se for o hbm vai dizer quais sao os arquivo .hbm.xml a serem mapeados. Esse arquivo por default fica na raiz da sua pasta src ou JavaSource.

moacirjava:
e deste:
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;


public class IniciaHibernate {
    
    private static final ThreadLocal<Session> tl = new ThreadLocal<Session>();
    private static SessionFactory sf;

    static {
        try {
            sf = new AnnotationConfiguration().configure("hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Erro na classe IniciaHibernate.\n" + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static Session getSession() {
        Session sessao = (Session)tl.get();
        sessao = sf.openSession();
        tl.set(sessao);
        return sessao;
    }
}

Classe responsável pela configuração do Hibernate Annotations. Tbm eh necessário usá-lo pois eh melhor vc declarar a classe uma unica vez na qual vc sempre vai utilizar na sua aplicação. vc nao vai ficar criando o código acima toda vez q precisar nao eh?

Melhorando o código acima:

import org.hibernate.*;
import org.hibernate.cfg.*;

public class HibernateUtil {

	private static SessionFactory sessionFactory;

	static {
		try {
			sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
		} catch (Throwable ex) {		
			System.err.println("Initial SessionFactory creation failed." + ex);
			throw new ExceptionInInitializerError(ex);
		}
	}

	public static SessionFactory getSessionFactory() {
		if(sessionFactory == null){
			try {
				sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
			} catch (Throwable ex) {	
				System.err.println("Initial SessionFactory creation failed." + ex);
				throw new ExceptionInInitializerError(ex);
			}
		}
		return sessionFactory;
	}
}
M

Usando annotations dá pra utilizar a Criteria pra construir consultas personalizadas? Li na net o pessoal dizendo que é ruim.

E

Sim da para usar normalmente vc pode criar sua classes DAO >> BO >> Proxy >> Interface e fazer os metodos de persitencia ao banco de dados, mas eu prefiro usar HQL.
De uma olhada aqui talvez te ajude a entender melhor sobre Criteria, HQL e Querie Nativa. Boa sorte!

M

ebarros:

Sim da para usar normalmente vc pode criar sua classes DAO >> BO >> Proxy >> Interface e fazer os metodos de persitencia ao banco de dados, mas eu prefiro usar HQL.
De uma olhada http://javafree.uol.com.br/topic-871797-Dicas-e-Discussoes-sobre-HQL-Criteria-e-Query-Nativa.html]aqui talvez te ajude a entender melhor sobre Criteria, HQL e Querie Nativa. Boa sorte!

Realmente, to lendo aqui, parece ser mais fácil mesmo…

Criado 18 de fevereiro de 2009
Ultima resposta 18 de fev. de 2009
Respostas 8
Participantes 3