Duplicação de Primary Key
Fala galera, estava procurando um tópico sobre este problema, achei, mais o cara conseguiu resolver, mais não postou a resolução, o meu eh bem parecido com o dele.. estou fazendo uma aplicação em java, e estou com problemas em chave duplicada, ou seja, esse erro --> Duplicate entry '18' for key 'PRIMARY' 18, eh a id que está tentando inserir dois tipos de produtos ao mesmo tempo, fala que a venda foi cadastrada com sucesso, mais gera essa exceção..
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '18' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
O meu código da minha classe Vendas:
public class VendasControl {
PreparedStatement pst;
ResultSet rs;
String cadastraVenda = "INSERT INTO VENDAS (ID_VENDAS, ID_PRODUTOS, ID_ALUNOS, DATA_VENDAS, QUANTIDADE) "
+ " VALUES (?,?,?,?,?)";
String buscaUltimoCodigo = "SELECT MAX(ID_VENDAS) AS ID_VENDAS FROM VENDAS";
public VendasControl(){
}
public int buscarCodigoUltimaVenda(){
try{
ConexaoBD bd = new ConexaoBD();
pst = (PreparedStatement) bd.conectar().prepareStatement(buscaUltimoCodigo);
rs = pst.executeQuery();
if (rs.last()){
return rs.getInt("id_vendas");
}
bd.desconectar();
} catch (SQLException ex){
ex.printStackTrace();
}
return 0;
}
public void CadastrarVenda(VendasBean venda){
try{
ConexaoBD bd = new ConexaoBD();
pst = (PreparedStatement) bd.conectar().prepareStatement(cadastraVenda);
pst.setInt(1, venda.getId());
pst.setInt(2, venda.getIdProduto());
pst.setInt(3, venda.getIdAluno());
pst.setDate(4, venda.getDataVenda());
pst.setInt(5, venda.getQuantidade());
pst.executeUpdate();
bd.desconectar();
}catch (SQLException ex){
ex.printStackTrace();
}
}
}
Código que cadastra a venda:
private void cadastrarVenda(){
if(venda.size() == 0){
JOptionPane.showMessageDialog(this, "Inclua pelo menos um produto!");
}else{
try{
VendasControl vc = new VendasControl();
SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd"); //formata o campo para datas
java.util.Date d = new java.util.Date();
Date data = Date.valueOf(formato.format(d)); //data da venda
int codigo = vc.buscarCodigoUltimaVenda() + 1;
for (int i = 0; i < venda.size(); i++){
venda.get(i).setIdAluno(alunos.get(cbAlunos.getSelectedIndex()).getId());
venda.get(i).setDataVenda(data);
venda.get(i).setId(codigo);
vc.CadastrarVenda(venda.get(i));
}
JOptionPane.showMessageDialog(this, "Venda cadastrada com sucesso!");
}catch (Exception ex){
JOptionPane.showMessageDialog(this, "Erro ao cadastrar Venda!");
}
}
}
Aqui a imagem do que eu to falando !
[url]http://img171.imageshack.us/img171/913/print6lu.png[/url]
Quando eu clico em finalizar, é quando gera esse erro que eu falei acima !
Obs: Não importa o produto, pode ser de nome diferente, id diferente, se eh dois ou mais, da esse erro, agora se for um produto, nem gera erro e vai de booa !
Agradeço desde já quem puder me ajudar ! Obrigado e até mais :)
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '18' for key 'PRIMARY'
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
O meu código da minha classe Vendas:
public class VendasControl {
PreparedStatement pst;
ResultSet rs;
String cadastraVenda = "INSERT INTO VENDAS (ID_VENDAS, ID_PRODUTOS, ID_ALUNOS, DATA_VENDAS, QUANTIDADE) "
+ " VALUES (?,?,?,?,?)";
String buscaUltimoCodigo = "SELECT MAX(ID_VENDAS) AS ID_VENDAS FROM VENDAS";
public VendasControl(){
}
public int buscarCodigoUltimaVenda(){
try{
ConexaoBD bd = new ConexaoBD();
pst = (PreparedStatement) bd.conectar().prepareStatement(buscaUltimoCodigo);
rs = pst.executeQuery();
if (rs.last()){
return rs.getInt("id_vendas");
}
bd.desconectar();
} catch (SQLException ex){
ex.printStackTrace();
}
return 0;
}
public void CadastrarVenda(VendasBean venda){
try{
ConexaoBD bd = new ConexaoBD();
pst = (PreparedStatement) bd.conectar().prepareStatement(cadastraVenda);
pst.setInt(1, venda.getId());
pst.setInt(2, venda.getIdProduto());
pst.setInt(3, venda.getIdAluno());
pst.setDate(4, venda.getDataVenda());
pst.setInt(5, venda.getQuantidade());
pst.executeUpdate();
bd.desconectar();
}catch (SQLException ex){
ex.printStackTrace();
}
}
}
Código que cadastra a venda:
private void cadastrarVenda(){
if(venda.size() == 0){
JOptionPane.showMessageDialog(this, "Inclua pelo menos um produto!");
}else{
try{
VendasControl vc = new VendasControl();
SimpleDateFormat formato = new SimpleDateFormat("yyyy-MM-dd"); //formata o campo para datas
java.util.Date d = new java.util.Date();
Date data = Date.valueOf(formato.format(d)); //data da venda
int codigo = vc.buscarCodigoUltimaVenda() + 1;
for (int i = 0; i < venda.size(); i++){
venda.get(i).setIdAluno(alunos.get(cbAlunos.getSelectedIndex()).getId());
venda.get(i).setDataVenda(data);
venda.get(i).setId(codigo);
vc.CadastrarVenda(venda.get(i));
}
JOptionPane.showMessageDialog(this, "Venda cadastrada com sucesso!");
}catch (Exception ex){
JOptionPane.showMessageDialog(this, "Erro ao cadastrar Venda!");
}
}
}
Aqui a imagem do que eu to falando !
[url]http://img171.imageshack.us/img171/913/print6lu.png[/url]
Quando eu clico em finalizar, é quando gera esse erro que eu falei acima !
Obs: Não importa o produto, pode ser de nome diferente, id diferente, se eh dois ou mais, da esse erro, agora se for um produto, nem gera erro e vai de booa !
Agradeço desde já quem puder me ajudar ! Obrigado e até mais :)
Vinicius Gomes
Curtidas 0
Respostas
Danilo Gomes
27/02/2013
Cara, é possível usar um campo auto increment no ID_VENDAS?
GOSTEI 0
Danilo Gomes
27/02/2013
Outra coisa, já tentou debugar e ver se os valores das variáveis estão de acordo com o esperado?
GOSTEI 0
Danilo Gomes
27/02/2013
Cara, abstraindo as perguntas acima, existe um erro de lógica mesmo.
Veja que está utilizando o mesmo ID dentro do FOR, teria que repetir essa chamada no FOR também.
int codigo = vc.buscarCodigoUltimaVenda() + 1; // O MESMO ID SERÁ UTILIZADO NO FOR ABAIXO for (int i = 0; i < venda.size(); i++){ venda.get(i).setIdAluno(alunos.get(cbAlunos.getSelectedIndex()).getId()); venda.get(i).setDataVenda(data); venda.get(i).setId(codigo); vc.CadastrarVenda(venda.get(i)); }
Veja que está utilizando o mesmo ID dentro do FOR, teria que repetir essa chamada no FOR também.
GOSTEI 0
Vinicius Gomes
27/02/2013
como assim repetir essa chamada no for !? não entendi !
GOSTEI 0
Danilo Gomes
27/02/2013
Não faria muito sentido né? rs
Então, qual a chave primária desta sua tabela? É o ID_VENDAS? Apenas ele?
Então, qual a chave primária desta sua tabela? É o ID_VENDAS? Apenas ele?
GOSTEI 0
Danilo Gomes
27/02/2013
Minhas sugestões iniciais foram equivocadas porque, pelo que entendi, esta tabela é um relacionamento.
O que está acontecendo, imagino eu, é que a chave primária refere-se apenas ao ID_VENDAS.
Quando vai alocar um segundo produto utiliza (logicamente) o mesmo ID_VENDAS, violando a constraint.
Nesse caso, pode modificar a chave primária para que seja composta por outros IDS.
A chave pode ser {ID_VENDAS E ID_PRODUTOS}.
Dessa forma pode cadastrar mais de um produto para uma mesma venda.
O que está acontecendo, imagino eu, é que a chave primária refere-se apenas ao ID_VENDAS.
Quando vai alocar um segundo produto utiliza (logicamente) o mesmo ID_VENDAS, violando a constraint.
Nesse caso, pode modificar a chave primária para que seja composta por outros IDS.
A chave pode ser {ID_VENDAS E ID_PRODUTOS}.
Dessa forma pode cadastrar mais de um produto para uma mesma venda.
GOSTEI 0
Vinicius Gomes
27/02/2013
Então me ajuda aqe, isso qe vce falou por ultimo fez sentido, mais é qe minha lógica não está muito boa..
essa é minha tabela vendas
create table vendas(
id_vendas int default null,
id_produtos int (50) default null,
id_alunos int (25) default null,
Data_vendas DATE default null,
quantidade int (10) default null,
primary key (id_vendas)
);
ALTER TABLE `vendas` ADD CONSTRAINT `fk_id_produtos`
FOREIGN KEY ( `id_produtos` )
REFERENCES `produtos` (`id_produto`) ;
ALTER TABLE `vendas` ADD CONSTRAINT `fk_id_alunos`
FOREIGN KEY ( `id_alunos` )
REFERENCES `alunos` (`id`) ;
ALTER TABLE vendas MODIFY id_vendas int NULL AUTO_INCREMENT;
essa é minha tabela vendas
create table vendas(
id_vendas int default null,
id_produtos int (50) default null,
id_alunos int (25) default null,
Data_vendas DATE default null,
quantidade int (10) default null,
primary key (id_vendas)
);
ALTER TABLE `vendas` ADD CONSTRAINT `fk_id_produtos`
FOREIGN KEY ( `id_produtos` )
REFERENCES `produtos` (`id_produto`) ;
ALTER TABLE `vendas` ADD CONSTRAINT `fk_id_alunos`
FOREIGN KEY ( `id_alunos` )
REFERENCES `alunos` (`id`) ;
ALTER TABLE vendas MODIFY id_vendas int NULL AUTO_INCREMENT;
GOSTEI 0
Vinicius Gomes
27/02/2013
E como eu modificaria a chave primária para que seja composta por outros IDS ?
GOSTEI 0
Danilo Gomes
27/02/2013
Primeiro tem que remover o status de primary key de ID_VENDAS
Para remover a chave primária existe, não tenho certeza, mas acredito que seja:
Depois deve-se fazer algo do gênero:
Para remover a chave primária existe, não tenho certeza, mas acredito que seja:
ALTER TABLE tabela DROP PRIMARY KEY;
Depois deve-se fazer algo do gênero:
ALTER TABLE nomedatabela ADD CONSTRAINT PRIMARY KEY (campo1, campo2, ... campo N);
GOSTEI 0
Danilo Gomes
27/02/2013
Se puder recriar a tabela é ainda mais fácil:
create table vendas( id_vendas int default null, id_produtos int (50) default null, id_alunos int (25) default null, Data_vendas DATE default null, quantidade int (10) default null, primary key (id_vendas, id_produtos) );
GOSTEI 0
Vinicius Gomes
27/02/2013
Me passa seu email pra gente conversar melhor, se você puder, é claro !
Desde já agradeço a sua ajuda, e mais tarde eu testo o que vcê falou !
Abraçoo, té mais !
Desde já agradeço a sua ajuda, e mais tarde eu testo o que vcê falou !
Abraçoo, té mais !
GOSTEI 0
Vinicius Gomes
27/02/2013
Minha ultima duvida !
Eu vou deixar o id_produtos como chave estrangeira tbm ? ou isso não é possivel ?
abrass
Eu vou deixar o id_produtos como chave estrangeira tbm ? ou isso não é possivel ?
abrass
GOSTEI 0
Danilo Gomes
27/02/2013
Você DEVE deixar como chave estrangeira também para manter a integridade.
Qualquer coisa pode postar aí no fórum que a gente ajuda.
Qualquer coisa pode postar aí no fórum que a gente ajuda.
GOSTEI 0
Danilo Gomes
27/02/2013
Olhando agora como o tópico desenvolveu-se, faria mais sentido ficar lá no MySQL né? rs
GOSTEI 0
Vinicius Gomes
27/02/2013
A id_vendas não tinha que ser auto increment ? e a id_produtos ?
Pode colocar la no forum de MySQL sim, mais nem sei como qe coloca ! hsuahsua
Pode colocar la no forum de MySQL sim, mais nem sei como qe coloca ! hsuahsua
GOSTEI 0
Danilo Gomes
27/02/2013
Nesse teu caso id_vendas não poderá ser auto increment, não para este caso, esta estrutura.
Se for autoincrement nunca vai conseguir associar dois produtos a uma mesma venda, seria necessária outra tabela (que não faria muito sentido aqui).
Conseguiu definir a chave composta? Creio que apenas isto resolverá seu problema.
Se for autoincrement nunca vai conseguir associar dois produtos a uma mesma venda, seria necessária outra tabela (que não faria muito sentido aqui).
Conseguiu definir a chave composta? Creio que apenas isto resolverá seu problema.
GOSTEI 0
Vinicius Gomes
27/02/2013
Resolveu sim meu amigo ! Mais tem um porém, se eu colocar mais de um produto com mesmo id, da erro, ai gera erro na id_produtos.. olha >> Duplicate entry '13-30' for key 'PRIMARY'
O que eu tava pensando, é não deixar o cliente inserir mais de um produto com o mesmo nome, ou seja, com a mesma id..
entendeu !?
O que eu tava pensando, é não deixar o cliente inserir mais de um produto com o mesmo nome, ou seja, com a mesma id..
entendeu !?
GOSTEI 0
Vinicius Gomes
27/02/2013
o código que inclui o produto é esse:
private void incluirProduto(){ if (verificarQuantidade()){ VendasBean vb = new VendasBean(); vb.setIdProduto(produtos.get(cbProdutos.getSelectedIndex()).getId()); vb.setQuantidade(Integer.parseInt(String.valueOf(ftfQuantidade.getValue()))); venda.add(vb); String produto = produtos.get(cbProdutos.getSelectedIndex()).getNome(); String quantidade = String.valueOf(ftfQuantidade.getValue()); String valor = String.valueOf(produtos.get(cbProdutos.getSelectedIndex()).getValor() * Integer.parseInt(quantidade)); String [] campos = new String [] {produto, quantidade, valor}; tmVendas.addRow(campos); total += Double.parseDouble(valor); ftfTotal.setValue(total); }else{ JOptionPane.showMessageDialog(this, "Quantidade inválida!"); ftfQuantidade.requestFocus(); } }
porém não to sabendo definir uma lógica, que pra quando eu inserir um produto, ex: Whey, ai eu vou tentar inserir outro, de mesmo nome Whey, ele da uma msg, dizendo que não é possivel adc 2 ou mais produtos de mesmo nome pra um mesmo aluno, o produto tem que ser distinto !
Obrigado pela ajuda ai até agora ! Agradeço desde já ! Boa Tarde !
GOSTEI 0
Danilo Gomes
27/02/2013
Vinicius, imaginei que isso poderia acontecer em um caso remoto.
Como vi um campo de "quantidade" na venda, achei que nunca incluiria um mesmo produto, para um mesmo aluno em uma mesma venda, estou certo?
Não seria mais coerente inserir uma quantidade de produtos para uma venda?
Como vi um campo de "quantidade" na venda, achei que nunca incluiria um mesmo produto, para um mesmo aluno em uma mesma venda, estou certo?
Não seria mais coerente inserir uma quantidade de produtos para uma venda?
GOSTEI 0
Vinicius Gomes
27/02/2013
como assim uma quantidade de produtos para uma venda?
quando vou faze a venda eu ja coloco a quantidade, por exemplo: incluo whey e na quantidade eu coloco qnts eu quiser e finalizo a venda da certo.. se eu colocar varios produtos distintos com quantas quantidades eu quiser, vai dar certo !
O que eu qeria, é que quando o cliente incluísse um produto, ai se por ventura ele ia e incluísse o mesmo produto, desse a mensagem pra ele falando que só pode o produto, se elee quiser mais, coloca na quantidade ! entende !?
quando vou faze a venda eu ja coloco a quantidade, por exemplo: incluo whey e na quantidade eu coloco qnts eu quiser e finalizo a venda da certo.. se eu colocar varios produtos distintos com quantas quantidades eu quiser, vai dar certo !
O que eu qeria, é que quando o cliente incluísse um produto, ai se por ventura ele ia e incluísse o mesmo produto, desse a mensagem pra ele falando que só pode o produto, se elee quiser mais, coloca na quantidade ! entende !?
GOSTEI 0
Vinicius Gomes
27/02/2013
tipo comparar um comboBox com um item da tabela entendeu !?
if (cbProdutos.getSelectedItem().toString() .....
if (cbProdutos.getSelectedItem().toString() .....
GOSTEI 0
Danilo Gomes
27/02/2013
Entendi. Então fechamos o assunto banco de dados, correto?
//
Nessa parte de desktop não poderei ajudá-lo muito.
Mas acredito que conseguirá ver, simplesmente e sem dificuldades, se existe algum item duplicado na coleção enviada, basta implementar o equals do objeto.
Você pode, por exemplo, para saber se existem ítens duplicados, utilizar uma implementação de Set, como HashSet.
Se não me engano ele aceita uma collection como argumento de construção.
Dessa forma, passando sua collection para ele e comparando o size da coleção original com a do HashSet, saberá se existem ítens duplicados de modo simples e direto.
//
Nessa parte de desktop não poderei ajudá-lo muito.
Mas acredito que conseguirá ver, simplesmente e sem dificuldades, se existe algum item duplicado na coleção enviada, basta implementar o equals do objeto.
Você pode, por exemplo, para saber se existem ítens duplicados, utilizar uma implementação de Set, como HashSet.
Se não me engano ele aceita uma collection como argumento de construção.
Dessa forma, passando sua collection para ele e comparando o size da coleção original com a do HashSet, saberá se existem ítens duplicados de modo simples e direto.
GOSTEI 0
Danilo Gomes
27/02/2013
Se for necessário, pode fazer uso do Collections.frequency para saber o número de vezes em que aparece um elemento em uma coleção.
int occurrences = Collections.frequency(animals, "bat");
GOSTEI 0
Vinicius Gomes
27/02/2013
De banco de dados ta fechado. foi resolvido o problema, muuuito obrigado pela sua ajuda !
Essa parte ai, mais tarde eu tento, e depois posto e resultado aqui !
Muito obrigado, abraços !
Essa parte ai, mais tarde eu tento, e depois posto e resultado aqui !
Muito obrigado, abraços !
GOSTEI 0
Danilo Gomes
27/02/2013
Creio que não terá muitos problemas com o uso das collections.
Qualquer coisa posta aí.
[]'s
Qualquer coisa posta aí.
[]'s
GOSTEI 0
José
27/02/2013
Como a dúvida aparentemente foi sanada, estou dando o tópico por concluído.
obrigado pela participação de todos !!!
obrigado pela participação de todos !!!
GOSTEI 0