HHH-9339 - java.lang.Optional support

This commit is contained in:
Steve Ebersole 2016-05-16 11:14:05 -05:00
parent 9dca4b82ae
commit aa9e1f0baf
5 changed files with 79 additions and 0 deletions

View File

@ -7,6 +7,7 @@
package org.hibernate;
import java.io.Serializable;
import java.util.Optional;
/**
* Loads an entity by its primary identifier.
@ -57,4 +58,14 @@ public interface IdentifierLoadAccess<T> {
* @return The persistent instance or {@code null}
*/
T load(Serializable id);
/**
* Same semantic as {@link #load} except that here {@link Optional} is returned to
* handle nullability.
*
* @param id The identifier
*
* @return The persistent instance, if one, wrapped in Optional
*/
Optional<T> loadOptional(Serializable id);
}

View File

@ -26,6 +26,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.persistence.CacheRetrieveMode;
import javax.persistence.CacheStoreMode;
@ -2732,6 +2733,11 @@ public final class SessionImpl
}
}
@Override
public Optional<T> loadOptional(Serializable id) {
return Optional.ofNullable( load( id ) );
}
@SuppressWarnings("unchecked")
protected final T doLoad(Serializable id) {
if ( this.lockOptions != null ) {

View File

@ -12,6 +12,7 @@ import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.Optional;
import java.util.stream.Stream;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
@ -57,6 +58,8 @@ public interface Query<R> extends TypedQuery<R>, org.hibernate.Query<R>, CommonQ
*/
RowSelection getQueryOptions();
Optional<R> uniqueResultOptional();
/**
* Retrieve a Stream over the query results.
* <p/>

View File

@ -21,6 +21,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
@ -1325,6 +1326,11 @@ public abstract class AbstractProducedQuery<R> implements QueryImplementor<R> {
return stream;
}
@Override
public Optional<R> uniqueResultOptional() {
return Optional.ofNullable( uniqueResult() );
}
@Override
public List<R> list() {
beforeQuery();

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.test.ops.genericApi;
import java.util.NoSuchElementException;
import java.util.Optional;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@ -20,6 +22,11 @@ import org.hibernate.boot.MetadataSources;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.fail;
/**
* @author Steve Ebersole
*/
@ -138,4 +145,50 @@ public class BasicGetLoadAccessTest extends BaseNonConfigCoreFunctionalTestCase
s.getTransaction().commit();
s.close();
}
@Test
public void testNullLoadResult() {
Session s = openSession();
s.beginTransaction();
assertNull( s.byId( User.class ).load( -1 ) );
Optional<User> user = s.byId( User.class ).loadOptional( -1 );
assertNotNull( user );
assertFalse( user.isPresent() );
try {
user.get();
fail( "Expecting call to Optional#get to throw NoSuchElementException" );
}
catch (NoSuchElementException expected) {
// the expected result...
}
s.getTransaction().commit();
s.close();
}
@Test
public void testNullQueryResult() {
Session s = openSession();
s.beginTransaction();
assertNull( s.createQuery( "select u from User u where u.id = -1" ).uniqueResult() );
Optional<User> user = s.createQuery( "select u from User u where u.id = -1" ).uniqueResultOptional();
assertNotNull( user );
assertFalse( user.isPresent() );
try {
user.get();
fail( "Expecting call to Optional#get to throw NoSuchElementException" );
}
catch (NoSuchElementException expected) {
// the expected result...
}
s.getTransaction().commit();
s.close();
}
}