Pergunta

Esta é uma versão específica do esta questão .
Quero verificar se eu estou inserindo uma linha duplicada. Devo verificá-lo por meio de programação na minha camada de aplicação:

if (exists(obj))
{
    throw new DuplicateObjectException();
}
HibernateSessionFactory.getSession().save(obj);

ou devo pegar a exceção lançada pela camada de banco de dados e acionado quando eu violar o contraint?

try
{
    HibernateSessionFactory.getSession().save(obj);
}
catch(ConstraintViolationException e)
{
    throw new DuplicateObjectException();
}

EDIT: Em outras palavras: embora a restrição está lá para permanecer (é bom design de banco de dados de qualquer maneira, e eu não posso ter certeza meu aplicativo será o único acesso à tabela) deve I contar com a restrição e tratar a exceção sua violação irá aumentar, ou melhor eu verificar afinal?

EDIT2: Claro que sim verificação + inserção dentro de uma transação, o bloqueio de tabela para garantir que nenhum outro processo está escrevendo outro recorde, entretanto

Foi útil?

Solução

Primeiro, você deve tem uma chave primária ou restrição exclusiva no banco de dados para fazer cumprir esta singularidade corretamente -. Nenhuma pergunta

Tendo em conta que existe a restrição, o caminho que você deve código no aplicativo? Minha preferência seria tentar a inserção e capturar as exceções. Porque, presumivelmente, a maioria das inserções será bem sucedida, apenas alguns vontade falhar como duplicatas (que é o "exceção" implica!): É ineficiente para realizar uma existe verificação antes de cada inserção, quando o banco de dados vai estar realizando sua própria verificação de restrição de qualquer maneira.

Além disso, é teoricamente possível para o check existe para ser assim mesmo errado - se alguém consegue cometer um registro com o mesmo valor de chave na pequena intervalo entre o seu existe cheque e sua inserção. Então, se você não interceptar a exceção de banco de dados, você vai acreditar a inserção sucedeu quando na verdade isso não aconteceu.

Outras dicas

Você verifica que o objeto existe unicamente no código do aplicativo, em seguida, uma vez convencido de que isso não aconteça, alegremente salvar o objeto. Mas outro cliente concorrente pode inserir seu próprio objeto no momento entre as duas linhas de código. Então você deseja obter uma exceção Duplicate qualquer maneira, só que desta vez você não pegá-lo.

Você deve fazer o save () e capturar a exceção. Caso contrário, você tem uma condição de corrida com outros clientes simultâneos que trabalham no mesmo banco de dados.

Você precisa capturar a exceção de banco de dados a menos que você pode garantir que a sua candidatura é a única que nunca insere linhas (e nunca vai inserir linhas) em seu banco de dados.

EDIT: eu possa ter mal a pergunta, mas eu ainda diria que a opção B (HibernateSessionFactory lança a ConstraintException do banco de dados) é a melhor opção. Sempre há uma pequena chance de que outro aplicativo pode inserir algo na lasca de tempo entre o cheque ea chamada função real. Além disso, a única maneira de verificar a existência de um ingênuo é a realização de uma consulta adicional que é apenas um dreno desnecessário no desempenho.

O meu entendimento original da questão era que, na opção A verificação dupe seria realizada internamente (ou seja, usando apenas as estruturas de dados que o programa já havia criado, e sem consulta até o INSERT). Minha resposta inicial foi em resposta a este método.

Em geral, eu tento evitar codificação que depende de erros que estão sendo jogados porque eu fiz algo errado. Às vezes, porém, isso é tudo que você pode fazer. Em sua situação, eu acho que você deve verificar primeiro.

Isso vai quebrar (permitindo entradas duplicadas) se a restrição é derrubada por alguma razão (normalmente o trabalho de manutenção onde as negligências DBA para reativá-lo). Você deve verificar esta situação dentro do aplicativo.

No entanto, é bom design de banco de dados para que o banco de dados de impor a restrição (como você salientou muito bem) como outros também podem estar usando o banco de dados. Como uma generalização que é melhor assumir que os aplicativos e bancos de dados de viver em um M: relacionamento M - este será o caso quase todo o tempo

.

As exceções lançadas pelo Hibernate (ou qualquer componente ORM) tendem a ser difíceis de interpretar.

Se a exceção tem informações o suficiente para que você pode produzir uma mensagem de erro que realmente ajuda o usuário, em seguida, apenas capturar a exceção, analisá-lo e seguir em frente.

Se a exceção não tem informação suficiente, então você tem que verificar a condição de erro, e produzir uma mensagem de erro útil para o usuário que está fazendo algo errado.

A questão é um dos "como opaca é a exceção"? Alguns são bastante opaca. Outros têm o suficiente para que você pode analisar a cadeia de mensagem e descobrir o que dizer para o usuário.

Uma vez que o Hibernate gera uma exceção a partir da sessão que você deve descartar sessão (ver secção 11.2.3). Então, se você precisa verificar se há dups e continuar usando a mesma sessão, então você não tem escolha, mas para verificar em primeiro lugar no aplicativo.

Também existe a possibilidade com o código no primeiro trecho que outro processo poderia inserir um registro que faria com que a exceção duplicado para ser jogado entre o momento em que você verificar o registro duplicado eo tempo que realmente é inserido.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top