I have the following method in my Java app:
public List<UUID> recursiveMethod(UUID productUuid) {
Set<UUID> productUuidSet = new HashSet<>();
productUuidSet.add(productUuid);
List<Product> subProducts = productRepo.getSubProducts(productUuid);
for (Product subProduct : subProducts) {
final UUID subProductUuid = subProduct.getProductUuid();
productUuidSet.add(subProductUuid);
productUuidSet.addAll(recursiveMethod(subProductUuid));
}
return new ArrayList<>(productUuidSet);
}
As far as I know, recursive method keep each call result recursively. And, when calling the recursive method via productUuidSet.addAll(recursiveMethod(subProductUuid));, it creates a new HashSet, but as it returns the value inside the HashSet, I would be able to keep it in productUuidSet after recursive call.
So, what is wrong with this method? If there is a problem, how can I retain productUuidSet value by adding result after each recursive call?
If I understand your question, you want to keep the set rather than creating new set each time?
This should work:
public List<UUID> recursiveMethod(UUID productUuid) {
Set<UUID> productUuidSet = new HashSet<>(); // or LinkedHashSet if order matters
recursiveMethod0(productUuidSet, productUuid);
return new ArrayList<>(productUuidSet);
}
private void recursiveMethod0(Set<UUID> productUuidSet, UUID productUuid) {
productUuidSet.add(productUuid);
List<Product> subProducts = productRepo.getSubProducts(productUuid);
for (Product subProduct : subProducts) {
recursiveMethod0(productUuidSet, subProduct.getProductUuid());
}
}
TL;DR: simply pass the set instead of recreating it each time.
I simplified your insertion code: productUuidSet.add(subProductUuid); is already done by the recursive function.
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
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.
Thanks
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.
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.
Try this in Java 8:
Optional first = query.getResultList().stream().findFirst();
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();
}
}
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);
}
I've done (in Java 8):
query.getResultList().stream().findFirst().orElse(null);
From JPA 2.2, instead of .getResultList() and checking if list is empty or creating a stream you can return stream and take first element.
.getResultStream()
.findFirst()
.orElse(null);
Spring has a utility method for this:
TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
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 { //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);
}
Here's a typed/generics version, based on Rodrigo IronMan's implementation:
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);
}
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.
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.
I'd go with the second suggestion, in agreement with Cletus. It gives better performance than (potentially) 2 queries. Also less work.
Combining the useful bits of the existing answers (limiting the number of results, checking that the result is unique) and using the estabilshed method name (Hibernate), we get:
/**
* Return a single instance that matches the query, or null if the query returns no results.
*
* #param query query (required)
* #param <T> result record type
* #return record or null
*/
public static <T> T uniqueResult(#NotNull TypedQuery<T> query) {
List<T> results = query.setMaxResults(2).getResultList();
if (results.size() > 1) throw new NonUniqueResultException();
return results.isEmpty() ? null : results.get(0);
}
The undocumented method uniqueResultOptional in org.hibernate.query.Query should do the trick. Instead of having to catch a NoResultException you can just call query.uniqueResultOptional().orElse(null).
I solved this by using List<?> myList = query.getResultList(); and checking if myList.size() equals to zero.
Look this code :
return query.getResultList().stream().findFirst().orElse(null);
When findFirst() is called maybe can be throwed a NullPointerException.
the best aproach is:
return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);
Here's the same logic as others suggested (get the resultList, return its only element or null), using Google Guava and a 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().)
Here's another extension, this time in 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)
}
So all of the "try to rewrite without an exception" solution in this page has a minor problem. Either its not throwing NonUnique exception, nor throw it in some wrong cases too (see below).
I think the proper solution is (maybe) this:
public static <L> L getSingleResultOrNull(TypedQuery<L> query) {
List<L> results = query.getResultList();
L foundEntity = null;
if(!results.isEmpty()) {
foundEntity = results.get(0);
}
if(results.size() > 1) {
for(L result : results) {
if(result != foundEntity) {
throw new NonUniqueResultException();
}
}
}
return foundEntity;
}
Its returning with null if there is 0 element in the list, returning nonunique if there are different elements in the list, but not returning nonunique when one of your select is not properly designed and returns the same object more then one times.
Feel free to comment.
I achieved this by getting a result list then checking if it is empty
public boolean exist(String value) {
List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
return !options.isEmpty();
}
It is so annoying that getSingleResult() throws exceptions
Throws:
NoResultException - if there is no result
NonUniqueResultException - if more than one result
and some other exception that you can get more info on from their documentation
I prefer #Serafins answer if you can use the new JPA features, but this is one fairly straight forward way to do it which I'm surprised hasn't been mentioned here before:
try {
return (Profile) query.getSingleResult();
} catch (NoResultException ignore) {
return null;
}
`public Example validate(String param1) {
// TODO Auto-generated method stub
Example example = new Example();
Query query =null;
Object[] myResult =null;
try {
query = sessionFactory.getCurrentSession()
.createQuery("select column from table where
column=:p_param1");
query.setParameter("p_param1",param1);
}
myResult = (Object[])query.getSingleResult();//As your problem occurs here where the query has no records it is throwing an exception
String obj1 = (String) myResult[0];
String obj2 = (String) myResult[1];
example.setobj1(ISSUtil.convertNullToSpace(obj1))
example.setobj2(ISSUtil.convertNullToSpace(obj2));
return example;
}catch(Exception e) {
e.printStackTrace();
example.setobj1(ISSUtil.convertNullToSpace(""));//setting
objects to "" in exception block
example.setobj1(ISSUtil.convertNullToSpace(""));
}
return example;
}`
Answer : Obviously when there is no records getsingleresult will throw an exception i have handled it by setting the objects to "" in the exception block even though it enter the exception you JSON object will set to ""/empty
Hope this is not a perfect answer but it might help
If some needs to modify my code more precisely and correct me always welcome.
Thats works to me:
Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
return opt.isPresent() ? opt.get() : null;
I have one code snippet, which is calling 2 different services based on some a if condition. And both the services return CompletableFuture<Optional<SomeObject>>. Following is the code logic looks like
if(someCondition){
CompletableFuture<Optional<SomeObjectType1>> = service1.call();
}else{
CompletableFuture<Optional<SomeObjectType2>> = service2.call();
}
And both SomeObjectType1 and SomeObjectType2 have a String inside it, which is of my interest. My current code looks like this:
private ContentWrapper getContentWrapper(input1, input2, ....) {
String content = null;
if (some_condition is true) {
List<Object_Type_1> list = service1.fetchTheCompletableFuture(..... inputs...)
.join()
.map(ListOutput::getList)
.orElse(null);
if (CollectionUtils.isNotEmpty(list)) {
content = list.get(0).getContent();
}
} else {
content = service2
.fetchTheCompletableFuture(..... inputs...)
.join()
.map(RenderedContent::getContent)
.orElse(null);
}
return content != null ? new ContentWrapper(content) : null;
}
Now my question is, can this if-else clause be removed or make it more clear by using lambdas. I am new in lambdas and does not have very good idea on this.
I am not sure whether the code below even compiles due to the vagueness.
private ContentWrapper getContentWrapper(input1, input2, ....) {
Optional<RenderedContent> content = some_condition
? service1
.fetchTheCompletableFuture(..... inputs...)
.join()
.map(ListOutput::getList)
.stream()
.findFirst()
: service2
.fetchTheCompletableFuture(..... inputs...)
.join();
}
return content
.map(RenderedContent::getContent)
.map(ContentWrapper::new).orElse(null);
}
The first service seems to yield a list of RenderedContent of which to take the first if there is one.
The second service may yield a Rendered content immediately.
So you can join the if-else to an Optional<RenderedContent>.
The map(RenderedContent::getContent) will yield Optional.empty() if it was empty to begin with. Otherwise getContent is called and wrapped in an Optional.
If present new ContentWrapper(...) might be called.
Notice much may fail, like getContent returning null (though there is an Optional.ofNullable.
Nevertheless Streams may be very expressive.
I would avoid using null in favor of Optional as that plays better together.
I have a test where an Optional was used. In the method, its stating no value was present. Here is the code, I have. How can I make this pass without NoSuchElementException.
public jobs theID(Integer id) {
if( id == null) {
throw new IllegalArgumentException("Its missing.");
}
return jobTitleMapper.entityToModel(this.jobTitleRepository.findById(id).get());
}
It is fussing about the get() from Java 8.
How do I use an Optional with isPresent correctly in this sense?
The test is:
public void findIdTest() {
Jobs jt = this.Service.theID(Entities.thisID);
Assert.assertNotNull(jt);
Assert.assertEquals(Entities.thisID, .getId());
}
Thanks for the help.
That happens because the Optional returned by:
this.jobTitleRepository.findById(id) can return an empty, so if you call get() on it it will throw a java.util.NoSuchElementException.
You can fix that with something like:
this.jobTitleRepository.findById(id).orElseGet(null)
or
this.jobTitleRepository.findById(id).orElseGet(new Jobs())
or fix the return Optional type in the original method: jobTitleRepository.findById(id)
Can you post this method jobTitleRepository.findById(id) on your post aswell?
Must check Option YourObject.findById(id).isPresent()
exemple:
public YourObject getYourObject(Long id) {
if (id == null) {
return null;
}
return objectRepository.findById(id).isPresent() ?
objectRepository.findById(id).get(): null;
}
jobTitleRepository.findById(id) it always returns an optional class so you don't need check if it is null, also before you call assertEquals() you can check if object with passed id exists by calling someOptional.isPresent() and if it's true you can make assert. But you should project your test cases to avoid mixing codintional statmens with asserations.
I'm looking for a Google Collections method that returns the first result of a sequence of Suppliers that doesn't return null.
I was looking at using Iterables.find() but in my Predicate I would have to call my supplier to compare the result against null, and then have to call it again once the find method returned the supplier.
Given your comment to Calm Storm's answer (the desire not to call Supplier.get() twice), then what about:
private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
public X apply(Supplier<X> in) {
// If you will never have a null Supplier, you can skip the test;
// otherwise, null Supplier will be treated same as one that returns null
// from get(), i.e. skipped
return (in == null) ? null : in.get();
}
}
then
Iterable<Supplier<X>> suppliers = ... wherever this comes from ...
Iterable<X> supplied = Iterables.transform(suppliers, SUPPLY);
X first = Iterables.find(supplied, Predicates.notNull());
note that the Iterable that comes out of Iterables.transform() is lazily-evaluated, therefore as Iterables.find() loops over it, you only evaluate as far as the first non-null-returning one, and that only once.
You asked for how to do this using Google Collections, but here's how you would do it without using Google Collections. Compare it to Cowan's answer (which is a good answer) -- which is easier to understand?
private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
for (Supplier<Thing> supplier : thingSuppliers) {
Thing thing = supplier.get();
if (thing != null) {
return thing;
}
}
// throw exception or return null
}
In place of the comment -- if this was the fault of the caller of your class, throw IllegalArgumentException or IllegalStateException as appropriate; if this shouldn't have ever happened, use AssertionError; if it's a normal occurrence your code that invokes this expects to have to check for, you might return null.
What is wrong with this?
List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
boolean apply(Supplier supplier) {
return supplier.isSomeMethodCall() == null;
}
boolean equals(Object o) {
return false;
}
});
Are you trying to save some lines? The only optimisation I can think is to static import the find so you can get rid of "Iterables". Also the predicate is an anonymous inner class, if you need it in more than one place you can create a class and it would look as,
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
Where SupplierPredicateFinder is another class.
UPDATE : In that case find is the wrong method. You actually need a custom function like this which can return two values. If you are using commons-collections then you can use a DefaultMapEntry or you can simply return an Object[2] or a Map.Entry.
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
Replace the DefaultMapEntry with a List of size 2 or a hashmap of size 1 or an array of length 2 :)