Mapeamento no Hibernate

9 respostas
M

Ola a todos. Sou novato em Java e Hibernate. To num projeto que caiu no meu colo, por isso nao tive muito tempo para olhar alguma documentação. Vou tentar ser bem sucinto:

1) As tabelas

CREATE TABLE [dbo].[Pai](
	[Pai_id] [int] IDENTITY(1,1) NOT NULL,
	[Pai_descr] [varchar](20) NULL,
 CONSTRAINT [PK_Pai] PRIMARY KEY CLUSTERED 
(
	[Pai_id] ASC
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[Filho](
	[Filho_id] [int] IDENTITY(1,1) NOT NULL,
	[Pai_Id] [int] NOT NULL,
	[Filho_descr] [varchar](20) NULL,
 CONSTRAINT [PK_Filho] PRIMARY KEY CLUSTERED 
(
	[Filho_id] ASC
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Filho]  WITH CHECK ADD  CONSTRAINT [FK_Filho_Pai] FOREIGN KEY([Pai_Id]) REFERENCES [dbo].[Pai] ([Pai_id])
GO
ALTER TABLE [dbo].[Filho] CHECK CONSTRAINT [FK_Filho_Pai]
GO

O mapeamento no HIbernate (Ainda nao vi como funciona com Annotations)

<hibernate-mapping>
  	<class name="Pai" table="PAI">
		<meta attribute="class-description">
			Table Pai
		</meta>
		<id name="PaiId" type="java.lang.Integer" column="Pai_id">
			<generator class="native"/>
		</id>
		<property name="descr" type="java.lang.String" column="Pai_descr"  length="20" />
                <set name="filhos" table="filhos" cascade="all" inverse="true">
			<key column="Pai_ID" />
			<many-to-many column="Filho_ID" class="Filho" />
		</set>	
	</class>
</hibernate-mapping>
e
<hibernate-mapping>
  <class name="Filho" table="FILHO">
  		<meta attribute="class-description">
			Table Filho
		</meta>
		<id name="FilhoId" type="java.lang.Integer" column="Filho_id">
			<generator class="native"/>
		</id>
  		<property name="descr" type="java.lang.String" column="Filho_descr"  length="20" />
  </class>
</hibernate-mapping>
e o código :
public class Teste {

	public static void main(String[] args) {
		Teste t = new Teste();
		t.saveFamilia();
	}
	
	public void saveFamilia()  {
	        Session session = HibernateUtil.getSessionFactory().openSession();
	        Transaction transaction = null;
	        Integer paiId = null;
	        
	        try {
	            transaction = session.beginTransaction();
	            Pai pai = new Pai();
	            pai.setDescr("Valmir");
	            Filho filho = new Filho();
	            filho.setDescr("Isadora");
	            pai.getFilhos().add(filho);
	            paiId = (Integer) session.save(pai);
	            transaction.commit();
	        } catch (HibernateException e) {
	            transaction.rollback();
	            e.printStackTrace();
	        } finally {
	            session.close();
	        }
    }
}
Ao executar:

Hibernate: insert into PAI (Pai_descr) values (?)
Hibernate: insert into FILHO (Pai_Id, Filho_descr) values (?, ?)
4875 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 515, SQLState: 23000
4875 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Cannot insert the value NULL into column 'Pai_Id', table 'TesteHibernate.dbo.Filho'; column does not allow nulls. INSERT fails.
org.hibernate.exception.ConstraintViolationException: could not insert: [Filho]

Como fica o save() neste caso? O Hibernate não deveria saber que estou inserindo um pai e portanto pegar o Id do Pai e usa-lo para inserir o Filho automaticamente, fazendo todo o insert (do Pai e dos filhos) numa operação só?

Porque devo salvar o Pai, setar o id do Pai na classe Filho e depois fazer um update (como abaixo)?

transaction = session.beginTransaction();
Pai pai = new Pai();
pai.setDescr("Valmir");
paiId = (Integer) session.save(pai);
Filho filho = new Filho();
filho.setDescr("Isadora");
[b]filho.setPaiId(paiId);[/b]
pai.getFilhos().add(filho);
session.update(pai);
transaction.commit();
Estou fazendo algo errado ou o Hibernate trabalha assim mesmo?

Obrigado pela ajuda

9 Respostas

D

Fala meu véio! Você quer trampar com herança certo?
Então, pra isso o hibernate têm três “estratégias”…Joinned subclass, table per class e single tabel…aí vc deve mapear a parada da forma adequada ao modelo…dá uma lida nesse link…

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html

qualquer coisa tamo ai, abraço!!

D

NUOSSA, hhahaha, esquece tudo o q falei, não li o post inteiro, e já fui escrevendo, hahaha

D

Enfim, cria uma property Pai no filho…aí vc seta o pai do filho…nem precisa ser bi-direcional…pai não precisa ter uma lista de filhos.

abraço

N

Você tem alguns problemas…

por exemplo usa tabela FILHO recebe o id do PAI, não há uma tabela intermediária. então a cardinalidade é de um para muitos (FILHO [0,n] ---------<>--------[1,1]PAI).

Logo no mapeamento do PAI a linha

&lt;many-to-many column="Filho_ID" class="Filho" /&gt;

deveria ser algo como

Logo no mapeamento do PAI a linha

&lt;one-to-many column="Filho_ID" class="Filho" /&gt;

e fazer ess tipo de relacionamento define também quem ve quem.

Se você quiser que o filho veja o pai, crie um atributo no seu bean que seja do tipo PAI
e mapeie no filho o relacionamento.

Se for ao contrario crie uma lista de FILHOS(use a interface Collection) no PAI e mapeie no PAI usando a tag

&lt;set ...&gt;
&lt;one-to-many .../&gt;
&lt;/set&gt;

É só dá uma pesquisada melhor… :wink:

espero ter ajudado

M

Mas é justamente isso que eu pensava que o Hibernate faria sozinho.

Uma vez que eu estou salvando o pai, e os filhos são uma propriedade collection do pai, entao eu não precisaria setar nada, concorda? O Hibernate deveria automaticamente pegar o id do Pai que ele acabou de salvar pra setar a propriedade pai dos filhos antes de salvá-los.

dovalegabriel:
Enfim, cria uma property Pai no filho…aí vc seta o pai do filho…nem precisa ser bi-direcional…pai não precisa ter uma lista de filhos.

abraço

M

ncm:
Você tem alguns problemas…

por exemplo usa tabela FILHO recebe o id do PAI, não há uma tabela intermediária. então a cardinalidade é de um para muitos (FILHO [0,n] ---------<>--------[1,1]PAI).

Logo no mapeamento do PAI a linha

&lt;many-to-many column="Filho_ID" class="Filho" /&gt;

deveria ser algo como

&lt;one-to-many column="Filho_ID" class="Filho" /&gt;

Beleza, foi erro meu.

Então, é isso que eu tava perguntando, o Hibernate não deveria fazer isso automaticamente? Se ele não faz, bele, é só uma dúvida minha, mas se ele faz, eu to comendo bola em algum lugar.


Se for ao contrario crie uma lista de FILHOS(use a interface Collection) no PAI e mapeie no PAI usando a tag

&lt;set ...&gt;
&lt;one-to-many .../&gt;
&lt;/set&gt;

É só dá uma pesquisada melhor… :wink:

espero ter ajudado

Então, eu to usando <SET>, só não usei <one-to-many>, mas aqui no trampo to usando e a caracteristica se repete.

BOm, o codigo ta em casa, a noite vout estar e comento aqui.

[]'s a todos

N

Cara eu posso estar errado,
mas tenta isso aqui

&lt;one-to-many column="Pai_ID" class="Filho" /&gt;

dentro do seu <set>

porque o parametro passado no atributo de tag column é a coluna que ele vai usar para criar o relacionamento.
Você está passando certinho o da classe atual (Pai) em :

&lt;key column="Pai_ID" /&gt;

Agora acerta a do filho. Dei uma olhada aqui nos meus projetos e vi que só passo a classe. eu deixo com que o hibernate decida qual coluna usar. e geralmente ele vai usa os id’s, só passe a coluna se o que você utilizar para fazer o relacionamento não for um Primary Key. Ai sim você usa dessa forma.

bem acho que enrolei um pouco. Tenta assim:

&lt;set name="filhos" table="filhos" cascade="all" inverse="true"&gt;  
    &lt;key column="Pai_ID" /&gt;  
    &lt;one-to-many class="Filho" /&gt;  
&lt;/set&gt;

É assim que vi nos projetos daqui.

Abraços…

M

ncm:
Cara eu posso estar errado,
mas tenta isso aqui

&lt;one-to-many column="Pai_ID" class="Filho" /&gt;

dentro do seu <set>

Quando alterei o hbm para isto, ai ele tentou fazer o que eu queria, poerm ele tentou gerar um valor para a PK

&lt;meta attribute="class-description"&gt;
			Table Pai
		&lt;/meta&gt;
		&lt;id name="PaiId" type="java.lang.Integer" column="Pai_id"&gt;
			&lt;generator class="native"/&gt;
		&lt;/id&gt;
		&lt;property name="descr" type="java.lang.String" column="Pai_descr"  length="20" /&gt;
		
		&lt;many-to-one name="PaiFilho" column="Pai_ID" class="Filho"  /&gt;

Erro do banco:
9344 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 544, SQLState: 23000
9344 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Cannot insert explicit value for identity column in table ‘Pai’ when IDENTITY_INSERT is set to OFF.

Também não funfou…

N

cara faz o seguinte:

posta os dois hbm’s completos junto com seus beans, para eu dar uma olhada e ver se posso te ajudar em mais alguma coisa. Pode ser que esteja passando algum detalhe porque não estou vendo o código.

[]'s

Criado 9 de novembro de 2009
Ultima resposta 12 de nov. de 2009
Respostas 9
Participantes 3