Hibernate - Chave estrangeira e mapeamento

Gente,

Não entendi alguns conceitos de chave estrangeira no Hibernate. Vejam só minhas tabelas filme, gênero e categoria. Um filme deve conter um gênero e uma categoria. Eu já tinha criado as tabelas no (MySQL5) dessa forma:

code
id : int | auto incr | PK
nome: varchar
genero: int
categoria int

índice fk_filme1 -> campo genero aponta para “id” da tabela genero
índice fk_filme2 -> campo categoria aponta para “id” da tabela categoria

code
id : int | auto incr | PK
nome: varchar[/code]

code
id : int | auto incr | PK
nome: varchar[/code]

Então, minha classe Filme fica assim?:

public class Filme { private String nome; private Genero genero; private Categoria categoria; private int id; // construtor, getters e setters }

E o meu Filme.hbm.xml?
/// cabeçalho

[code]




	<many-to-one
		name="genero"
		column="genero"
		class="pojo.Genero"
		not-null="true"
		foreign-key="FK_filme_1"/>
		
	<many-to-one
		name="categoria"
		column="categoria_filme"
		class="pojo.Categoria"
		not-null="true"
		foreign-key="FK_filme_2"/>			

</class>

[/code]

Outra coisa, costumo em minhas tabelas sempre criar um pk “id” inteiro e auto incrementável. As tabelas geradas da relação n:n também devem ter esse campo como única chave estrangeira?

Mais uma outra coisa, como se chamam as classes que contém apenas os atributos e os getters e os setters? Tipo Filme… parece que pojo, to, vo???

Abraço, pessoal

Sim, essas classes se chamam POJO (Plain Old Java Objects).

Em relacionamentos n:m o comum é ter uma tabela de relacionamento, contendo com chave primária as chaves primárias de cada uma das tabelas do relacionamento.

certo,

e como deve ficar minha pojo Filme? levando em conta a relação do mapeamento do hibernate

Sugiro que você use Annotations ao invés de arquivos de .hbm.xml.

Seu POJO filme deve ser alterar para incluir as chaves estrangeiras de gênero e categoria.

E como devo alterar filme pra incluir as chaves estrangeiras?

Acrescente uma atributo/membro na classe filme para cada chave estrangeira.

e já não fiz isso?

public class Filme { private String nome; private Genero genero; private Categoria categoria; private int id; // construtor, getters e setters }

Inclui objetos de cada

Desculpa, não tinha visto.

Certo, mas não entendi uma coisa.

Um objeto filme, tem um objeto genero.
Quando eu fizer o sessao.save(filme) ele deve incluir o filme e cadastrar o genero?

Genero tem um campo “id” int auto-incr, e um campo “nome” string.
Eu preciso popular apenas o campo “nome” e depois inseri-lo no objeto filme?
é isso?

Veja mais embaixo, que postei o mapeamento de Filme

Quanto a primeira pergunta, depende de como você tiver configurado. Normalmente você tem que registrar o gênero primeiro.

Quanto a chave primária, se o mapeamento estiver correto, é só popular os outros campos.

Geralmente quando você vai incluir um filme… o gênero e a categoria já existem… ou já devam existir

Afinal, no relacionamento, o

“filme é que pertence a um gênero” … e

“um filme pertence a uma categoria”

… ou seja… como se fosse um filho.
No hibernate existe uma forma de mapeamento que, pelo filho cadastra-se um pai… porém não é muito recomendada.

um abraço

Sanderson

Me parece que o mapeamento em filme está correto

está dando algum erro?

Sanderson

Dá erro sim. Tentei de diversas formas… Estou usando Struts2 e Hibernate
No form, quando eu clico em Submit, o Hibernate gera uma exceção:
org.hibernate.PropertyValueException: not-null property references a null or transient value: pojo.Filme.genero

Não entendi bem, sobre como incluir o genero no filme. O objeto Genero tem um String “nome”. Eu devo digitar no form, um nome de genero que já existe no banco? Como isso é feito?

public class FilmeAction extends ActionSupport{
	private static final long serialVersionUID = 1L;
	private Filme filme;
	private FilmeDAO filmeDAO;
	private Genero genero;

	public FilmeAction() {
		this.filmeDAO = new FilmeDAO();
	}
	
	public String execute() throws Exception{
		return SUCCESS;
	}
		
	public String inserir() throws Exception{
		try {
			filme.setGenero(genero);
			filmeDAO.inserir(filme);
		}
		catch(Exception e){
			System.out.println(e);
			System.out.println("ERRO NO INSERT ERRO NO INSERT ERRO NO INSERT");
			System.out.println(genero.getNome());
			System.out.println("A CASA CAIU");
		}
		return "inserirOK";
	}
	
	public Filme getFilme() { return this.filme; }
	public void setFilme(Filme filme) { this.filme = filme; }

	public Genero getGenero() {	return this.genero; }
	public void setGenero(Genero genero) { this.genero = genero; }
	
}[/code]

FilmeForm.jsp
[code]
	<s:form action="filme">
		<s:textfield label="Nome" name="filme.nome"/>
		<s:textfield label="Sinopse" name="filme.sinopse"/>
		<s:textfield label="Genero" name="genero.nome"/>
		<s:submit method="inserir"/>
	</s:form>
[/code]

Genero.java
[code]public class Genero {
	private String nome;
	private int id;
//construtor, getters e setters

[quote=doncopal]
Não entendi bem, sobre como incluir o genero no filme.[/quote]

Genero g = generoDAO.carregarGeneroPorNome("mistério"); filme.setGenero(g); filmeDAO.salvarFilme(filme);

Exceção:
org.hibernate.PropertyValueException: not-null property references a null or transient value: pojo.Filme.genero

parceiro com o seu problema eu resolvi o meu problema… nao conseguir fazer o mapeamento
bom a dica pra vc dar um save eh:

no seu bean(POJO)

vai ter o
private Categoria categoria; certo!!

pra vc salvar é só vc salvar o campo categoria…


Filme filme = new Filme();

Categoria categoria = new Categoria();
categoria.setCodCategoria(1);

filme.setCategoria(categoria);

obs: a cetegoria de codigo um deve estar cadastrada no banco!!!
e coloca o fetch=“nome” no seu mapeamento para nao deleter a categoria!
sessao.save(filme);