Erro ao tentar inserir chave estrangeira

Seguinte amigos, estou tentando fazer um mapeamento mas so consigo adicionar sem a chave estrangeira e quando mapeio de outro jeito pra colocar a chave estrangeira manualmente da erro.

Eu tenho as classes Produto e Fornecedor. Quando eu mapeio a classe da seguinte forma, ele da erro pq tento colocar a FK manualmente:

Produto

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn (name="idfornecedor") private int idfornecedor;

Fornecedor

@OneToMany (mappedBy= "idfornecedor") private List<Produto> produto;

Erro ao rodar

E se eu tentar fazer o mapeamento da forma abaixo, ele insere na tabela, mas sem a FK, pq fornecedor não é um tipo de valor, entao como vou add um fornecedor colocando um int?

Produto

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn (name="idfornecedor") private Fornecedor fornecedor;

Fornecedor

@OneToMany (mappedBy= "fornecedor") private List<Produto> produto;

Adicionando no banco

Produto p = new Produto(); p.setNome ("Pen driver 1GB"); p.setDescricao("branco"); p.setPreco(12.99);

Para acrescentar o id do fornecedor nao tem como pq so daria pra acrescentar a seguinte linha:

mas o 1 eh do tipo int e nao do tipo fornecedor.

Como eu consigo adicionar o id do fornecedor na minha tabela Produto?

Agradeço pela ajuda!!!
[]'s

Alguem pode ajudar aew? ;/

Cara, arruma seu código pq vc deveria mapear um objeto e não um int :slight_smile:

Fornecedor

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn (name="idfornecedor")
private Produto produto;

Produto

@OneToMany (mappedBy= "produto")
private List<Fornecedor> fornecedores;

Assim fica melhor de vc trabalhar. Agora para vc setar seu id do fornecedor, vc faz o seguinte:

Produto p = new Produto();
p.setFornecedores(new ArrayList());
p.getFornecedores().add(new Fornecedor());
p.getFornecedores().get(0).setId(1);

Flw

ate da certo quando coloco o codigo, não cheguei a adicionar a FK mas o eclipse nao mostrou erro. Só que mapeado dessa forma eu não consigo adicionar um fornecedor porque ocorre esse erro:

Ele mapeado dessa forma duplica a coluna com a PK do proprio fornecedor. Veja a classe Fornecedor:

[code]@Entity
public class Fornecedor {

@Id @GeneratedValue
private long idfornecedor;

private String nome;
private int cnpj;

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)  
@JoinColumn (name="idfornecedor")
private Produto produto;

public long getIdfornecedor() {
	return idfornecedor;
}
public void setIdfornecedor(long idfornecedor) {
	this.idfornecedor = idfornecedor;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public int getCnpj() {
	return cnpj;
}
public void setCnpj(int cnpj) {
	this.cnpj = cnpj;
}
public Produto getProduto() {
	return produto;
}
public void setProduto(Produto produto) {
	this.produto = produto;
}

}[/code]

viu? ele diz q private long idfornecedor; e @JoinColumn (name=“idfornecedor”) são duas colunas iguais. E agora? =/

Vc não precisa necessariamente de uma fk…vc precisa de uma coluna q receba, um inteiro por exemplo ( nao precisa ter o papel de fk )

Isso ai vc vai salvar na tabela Produto, certo? Na tabela produto, tem um id_fornecedor lá, não é? Vc não pode usar a mesma referencia para as columns e os ids, experimenta mudar o nome da coluna do seu relacionamento…coloca:

     @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)    
     @JoinColumn (name="banana_fornecedor")  

Vichh cara, eu não entendi muito bem mas eu fiz o que vc falou e deu esse erro.

Caused by: java.sql.BatchUpdateException: Batch entry 0 insert into Fornecedor (cnpj, nome, banana_fornecedor, idfornecedor) values (68468422, XXX, NULL, 5) was aborted. Call getNextException to see the cause.

ia ocorrer erro mesmo?

Não…me manda o código q vc ta fazendo pra salvar e ta gerando esse erro!

[code]public class AdicionarFornecedor {

public static void main(String[] args) {
	Session session = new HibernateFactory().getSession();
	
	Fornecedor f = new Fornecedor();
	f.setNome ("XXX");
	f.setCnpj(68468422);
	
	FornecedorDAO fornecedorDAO = new FornecedorDAO(session);
	fornecedorDAO.salvar(f);
	//session.beginTransaction();
	//session.save(p);
	//session.getTransaction().commit();
	
			
	System.out.println("ID do fornecedor:" + f.getIdfornecedor());
	
	session.close();
}[/code]

Adiciona isso na anotação @JoinColumn

updatable=false, insertable=false

Daeh padcoe, blz?
Eu fiz o que vc falou no fornecedor e estou conseguindo adicionar fornecedor de boa.

Mas voltando agora aquele exemplo que você me deu pra adicionar idfornecedor em produto, ele não coloca a FK.
O código que você me passou foi o seguinte:

Produto p = new Produto(); p.setFornecedores(new ArrayList()); p.getFornecedores().add(new Fornecedor()); p.getFornecedores().get(0).setId(1);

eu tentei colocar o id do fornecedor no lugar do 1 no setId mas nao deu certo pq ele adicionou 0 na tabela. E quando tentei colocar o id do fornecedor em get, ele deu o seguinte erro:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 6, Size: 1 at java.util.ArrayList.RangeCheck(ArrayList.java:547) at java.util.ArrayList.get(ArrayList.java:322) at br.com.caelum.hibernate.AdicionaProduto.main(AdicionaProduto.java:23)

Por que isso? O que estou fazendo de errado? =/

abraço e obrigado pela ajuda!!!

Vc está tentando pegar algum objeto na posição que não existe e por isso está lançando a exceção.

Cola o código que vc ta usando ae :smiley:

Esse ai é o codigo que eu estou usando pra tentar adicionar o produto com a FK:

[code]public class AdicionaProduto {

public static void main(String[] args) {
	Session session = new HibernateFactory().getSession();
	
	Produto p = new Produto();
	p.setNome ("Pen driver 10GB");
	p.setDescricao("branco");
	p.setPreco(69.99);
	p.setFornecedores(new ArrayList());
	p.getFornecedores().add(new Fornecedor());  
	p.getFornecedores().get(6).setIdfornecedor(6);
	
	
	ProdutoDAO produtoDAO = new ProdutoDAO(session);
	produtoDAO.salva(p);
	//session.beginTransaction();
	//session.save(p);
	//session.getTransaction().commit();
	
			
	System.out.println("ID do produto:" + p.getId());
	
	session.close();
}

}[/code]

se eu deixar o get com 0 do jeito que você me disse ate vai, mas grava a FK como 0, tendeu? Eu deixo 0 no get e no setIdfornecedor eu coloco 6 que é o id e grava 0.

;/

não cara…

aquele get(int) é a posição de uma lista…sua lista soh tem um objeto e como vc qr pegar o objeto da posicao 7 ( 0 é a posicao 1 )?

esse id = 6 existe?

Sim sim, eu registrei o fornecedor. A id dele é 6, está no banco gravado .

então é get(0).setId(6);

Foi isso que eu fiz de primeiro, mas ele não adiciona 6 na tabela. Ele adiciona 0 =/

Olha

id | descricao | idfornecedor | nome | preco ----+-----------+--------------+-----------------+------- 1 | branco | | Pen driver 2GB | 19.99 2 | branco | | Pen driver 1GB | 12.99 7 | branco | 0 | Pen driver 8GB | 49.99 8 | branco | 0 | Pen driver 10GB | 69.99 9 | branco | 0 | Pen driver 10GB | 69.99
os 3 ultimos que tentei dessa forma e todos adicionaram 0 ;(

me manda o mapeamento q vc colocou nas anotaçoes nos campos One-to-Many e Many-To-One…manda com o objeto mapeado tb!

vou te mandar tudo pra ficar + facil ^^

Produto

[code]@Entity
public class Produto {
@Id @GeneratedValue
private long id;

private String nome;

@Column(name = "descricao", nullable = true, length = 50)
private String descricao;
private Double preco;


private int idfornecedor;

@OneToMany (mappedBy= "produto")  
private List<Fornecedor> fornecedores;

	
public List<Fornecedor> getFornecedores() {
	return fornecedores;
}
public void setFornecedores(List<Fornecedor> fornecedores) {
	this.fornecedores = fornecedores;
}
public long getIdfornecedor() {
	return idfornecedor;
}
public void setIdfornecedor(int idfornecedor) {
	this.idfornecedor = idfornecedor;
}
public long getId() {
	return id;
}
public void setId(long id) {
	this.id = id;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public String getDescricao() {
	return descricao;
}
public void setDescricao(String descricao) {
	this.descricao = descricao;
}
public Double getPreco() {
	return preco;
}
public void setPreco(Double preco) {
	this.preco = preco;
}

}[/code]

Fornecedor

[code]@Entity
public class Fornecedor {

@Id @GeneratedValue
private long idfornecedor;

private String nome;
private int cnpj;

@ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)  
@JoinColumn (name="banana_fornecedor", updatable=false, insertable=false)
private Produto produto;

public long getIdfornecedor() {
	return idfornecedor;
}
public void setIdfornecedor(long idfornecedor) {
	this.idfornecedor = idfornecedor;
}
public String getNome() {
	return nome;
}
public void setNome(String nome) {
	this.nome = nome;
}
public int getCnpj() {
	return cnpj;
}
public void setCnpj(int cnpj) {
	this.cnpj = cnpj;
}
public Produto getProduto() {
	return produto;
}
public void setProduto(Produto produto) {
	this.produto = produto;
}

}[/code]

Produto

	@OneToMany(mappedBy="produto", fetch = FetchType.LAZY)
	@Cascade(CascadeType.ALL)
	private List<Fornecedor> fornecedores;

Fornecedor

       @ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name="banana_fornecedor", insertable=true, updatable=true)
	@Fetch(FetchMode.JOIN)
	@Cascade(CascadeType.SAVE_UPDATE)
	private Produto produto;

Teste ae…o código de teste é o mesmo esquema q vc tava usando…acho q estava faltando essas anotacoes :smiley: