Eu tenho um insertOrUpdate
método que insere um Entity
quando não existe ou atualizá-lo, se existir. Para habilitar isso, eu tenho que findByIdAndForeignKey
, se ele retornou null
inserir, se não for, atualizar. O problema é como verifico se ele existe? Então eu tentei getSingleResult
. Mas lança uma exceção se o
public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
Query query = entityManager.createNamedQuery(namedQuery);
query.setParameter("name", userName);
query.setParameter("propName", propertyName);
Object result = query.getSingleResult();
if (result == null) return null;
return (Profile) result;
}
mas getSingleResult
joga um Exception
.
obrigado
getSingleResult()
é usado em situações como: " Estou totalmente certo de que esse registro existe. Atire em mim se não existir ". Não quero testarnull
todas as vezes que uso esse método porque tenho certeza de que ele não será devolvido. Caso contrário, isso causa muitos clichês e programação defensiva. E se o registro realmente não existir (como oposto ao que assumimos), é muito melhorNoResultException
compará-lo comNullPointerException
algumas linhas mais tarde. É claro que ter duas versõesgetSingleResult()
seria fantástico, mas se eu tiver que pegar um ...Encapsulei a lógica no seguinte método auxiliar.
fonte
Tente isso no Java 8:
fonte
.orElse(null)
Aqui está uma boa opção para fazer isso:
fonte
TypedQuery<T>
, nesse caso, ogetResultList()
já está corretamente digitado como aList<T>
.fetch()
a entidade pode não estar completamente preenchida. Veja stackoverflow.com/a/39235828/661414setMaxResults()
possui uma interface fluente para que você possa escreverquery.setMaxResults(1).getResultList().stream().findFirst().orElse(null)
. Esse deve ser o esquema de chamada mais eficiente no Java 8+.O Spring possui um método utilitário para isso:
fonte
Eu fiz (no Java 8):
fonte
No JPA 2.2 , em vez de
.getResultList()
verificar se a lista está vazia ou criando um fluxo, você pode retornar o fluxo e obter o primeiro elemento.fonte
Se você deseja usar o mecanismo try / catch para lidar com esse problema .. ele pode ser usado para agir como se / outro. Usei o try / catch para adicionar um novo registro quando não encontrei um existente.
fonte
Aqui está uma versão digitada / genérica, com base na implementação de Rodrigo IronMan:
fonte
Existe uma alternativa que eu recomendaria:
Isso protege contra a exceção do ponteiro nulo, garante que apenas 1 resultado seja retornado.
fonte
Então não faça isso!
Você tem duas opções:
Execute uma seleção para obter a COUNT do seu conjunto de resultados e somente extraia os dados se essa contagem for diferente de zero; ou
Use o outro tipo de consulta (que obtém um conjunto de resultados) e verifique se possui 0 ou mais resultados. Ele deve ter 1, então retire-o da sua coleção de resultados e pronto.
Eu aceitaria a segunda sugestão, de acordo com Cletus. Oferece melhor desempenho do que (potencialmente) 2 consultas. Também menos trabalho.
fonte
Combinando os bits úteis das respostas existentes (limitando o número de resultados, verificando se o resultado é único) e usando o nome do método estabelecido (Hibernate), obtemos:
fonte
O método não documentado
uniqueResultOptional
em org.hibernate.query.Query deve fazer o truque. Em vez de ter que pegar um,NoResultException
você pode simplesmente ligarquery.uniqueResultOptional().orElse(null)
.fonte
Eu resolvi isso usando
List<?> myList = query.getResultList();
e verificando semyList.size()
é igual a zero.fonte
Aqui está a mesma lógica sugerida por outras pessoas (obtenha o resultadoList, retorne seu único elemento ou nulo), usando o Google Guava e um TypedQuery.
Observe que o Guava retornará a IllegalArgumentException não intuitiva se o conjunto de resultados tiver mais de um resultado. (A exceção faz sentido para os clientes de getOnlyElement (), pois leva a lista de resultados como argumento, mas é menos compreensível para os clientes de getSingleResultOrNull ().)
fonte
Aqui está outra extensão, desta vez em Scala.
Com este cafetão:
fonte
Veja este código:
return query.getResultList().stream().findFirst().orElse(null);
Quando
findFirst()
é chamado, talvez seja possível lançar uma NullPointerException.a melhor abordagem é:
return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);
fonte
Portanto, toda a solução "tentar reescrever sem exceção" nesta página tem um problema menor. Não está lançando a exceção NonUnique, nem em alguns casos errados (veja abaixo).
Penso que a solução adequada é (talvez) esta:
É retornado com null se houver 0 elemento na lista, retornando não exclusivo se houver elementos diferentes na lista, mas não retornando não exclusivo quando um dos seus selecionados não foi projetado corretamente e retorna o mesmo objeto mais de uma vez.
Sinta-se livre para comentar.
fonte
Consegui isso obtendo uma lista de resultados e verificando se ela está vazia
É tão irritante que
getSingleResult()
lança exceçõesLances:
fonte
Isso funciona para mim:
fonte