Java JPA getSingleResult() 或 null
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2002993/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA getSingleResult() or null
提问by Eugene Ramirez
I have an insertOrUpdate
method which inserts an Entity
when it doesn't exist or update it if it does. To enable this, I have to findByIdAndForeignKey
, if it returned null
insert if not then update. The problem is how do I check if it exists? So I tried getSingleResult
. But it throws an exception if the
我有一个insertOrUpdate
方法,Entity
当它不存在时插入,如果存在则更新它。为了实现这一点,我必须findByIdAndForeignKey
,如果它返回null
插入,如果没有,则更新。问题是我如何检查它是否存在?所以我试过了getSingleResult
。但是如果
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;
}
but getSingleResult
throws an Exception
.
但getSingleResult
抛出一个Exception
.
Thanks
谢谢
采纳答案by cletus
Throwing an exception is how getSingleResult()
indicates it can't be found. Personally I can't stand this kind of API. It forces spurious exception handling for no real benefit. You just have to wrap the code in a try-catch block.
抛出异常是如何getSingleResult()
表明它无法找到。我个人无法忍受这种 API。它强制进行虚假异常处理而没有真正的好处。您只需要将代码包装在 try-catch 块中。
Alternatively you can query for a list and see if its empty. That doesn't throw an exception. Actually since you're not doing a primary key lookup technically there could be multiple results (even if one, both or the combination of your foreign keys or constraints makes this impossible in practice) so this is probably the more appropriate solution.
或者,您可以查询列表并查看其是否为空。那不会抛出异常。实际上,由于您在技术上没有进行主键查找,因此可能会有多个结果(即使一个、两个或外键或约束的组合在实践中都无法实现),因此这可能是更合适的解决方案。
回答by Carl Smotricz
So don't do that!
所以不要那样做!
You have two options:
您有两个选择:
Run a selection to obtain the COUNT of your result set, and only pull in the data if this count is non-zero; or
Use the other kind of query (that gets a result set) and check if it has 0 or more results. It should have 1, so pull that out of your result collection and you're done.
运行选择以获取结果集的 COUNT,并且仅在此计数非零时才拉入数据;或者
使用另一种查询(获取结果集)并检查它是否有 0 个或多个结果。它应该有 1,所以把它从你的结果集合中拉出来,你就完成了。
I'd go with the second suggestion, in agreement with Cletus. It gives better performance than (potentially) 2 queries. Also less work.
我同意第二个建议,同意 Cletus。它提供比(可能)2 个查询更好的性能。工作也少。
回答by Eugene Katz
I encapsulated the logic in the following helper method.
我将逻辑封装在以下辅助方法中。
public class JpaResultHelper {
public static Object getSingleResultOrNull(Query query){
List results = query.getResultList();
if (results.isEmpty()) return null;
else if (results.size() == 1) return results.get(0);
throw new NonUniqueResultException();
}
}
回答by tpdi
Here's the same logic as others suggested (get the resultList, return its only element or null), using Google Guava and a TypedQuery.
这里的逻辑与其他人建议的逻辑相同(获取 resultList,返回其唯一元素或 null),使用 Google Guava 和 TypedQuery。
public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
return Iterables.getOnlyElement(query.getResultList(), null);
}
Note that Guava will return the unintuitive IllegalArgumentException if the result set has more than one result. (The exception makes sense to clients of getOnlyElement(), as it takes the result list as its argument, but is less understandable to clients of getSingleResultOrNull().)
请注意,如果结果集有多个结果,Guava 将返回不直观的 IllegalArgumentException。(该异常对 getOnlyElement() 的客户端有意义,因为它将结果列表作为其参数,但对 getSingleResultOrNull() 的客户端来说不太容易理解。)
回答by Rodrigo IronMan
Here's a good option for doing this:
这是一个很好的选择:
public static <T> T getSingleResult(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list == null || list.isEmpty()) {
return null;
}
return list.get(0);
}
回答by aces.
There is an alternative which I would recommend:
有一个我会推荐的替代方案:
Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);
This safeguards against Null Pointer Exception, guarantees only 1 result is returned.
这可以防止空指针异常,保证只返回 1 个结果。
回答by Pete Montgomery
Here's another extension, this time in Scala.
这是另一个扩展,这次是在 Scala 中。
customerQuery.getSingleOrNone match {
case Some(c) => // ...
case None => // ...
}
With this pimp:
有了这个皮条客:
import javax.persistence.{NonUniqueResultException, TypedQuery}
import scala.collection.JavaConversions._
object Implicits {
class RichTypedQuery[T](q: TypedQuery[T]) {
def getSingleOrNone : Option[T] = {
val results = q.setMaxResults(2).getResultList
if (results.isEmpty)
None
else if (results.size == 1)
Some(results.head)
else
throw new NonUniqueResultException()
}
}
implicit def query2RichQuery[T](q: TypedQuery[T]) = new RichTypedQuery[T](q)
}
回答by Sorter
If you wish to use the try/catch mechanism to handle this problem.. then it can be used to act like if/else. I used the try/catch to add a new record when I didn't find an existing one.
如果您希望使用 try/catch 机制来处理此问题.. 那么它可以用于像 if/else 一样。当我找不到现有记录时,我使用 try/catch 添加新记录。
try { //if part
record = query.getSingleResult();
//use the record from the fetched result.
}
catch(NoResultException e){ //else part
//create a new record.
record = new Record();
//.........
entityManager.persist(record);
}
回答by Emmanuel Touzery
Here's a typed/generics version, based on Rodrigo IronMan's implementation:
这是一个类型化/泛型版本,基于 Rodrigo IronMan 的实现:
public static <T> T getSingleResultOrNull(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
回答by heenenee
Spring has a utility methodfor this:
Spring 有一个实用方法:
TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());