When calling {{StatelessSession.get(Class, Serializable, LockMode)}} with a {{null}} {{LockMode}} argument, a {{NullPointerException}} is thrown from the following code path: {code} java.lang.NullPointerException at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4004) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3989) at org.hibernate.internal.StatelessSessionImpl.get(StatelessSessionImpl.java:182) at org.hibernate.internal.StatelessSessionImpl.get(StatelessSessionImpl.java:170) {code}
A self-contained demo is available in [^HHH-10905.zip], it's runnable with {{mvn clean test}}.
When the counterpart {{Session.get(Class<T>, Serializable, LockMode)}} is called with a {{null}} {{LockMode}}, it doesn't throw an exception (and works just fine).
It seems like the {{LockOptions}} instance in {{AbstractEntityPersister.getAppropriateLoader(LockOptions, SharedSessionContractImplementor)}} has different values for its {{lockMode}} field : {{LockMode.NONE}} in case of a stateful {{Session}}, and {{null}} in case of a {{StatelessSession}}. So {{getLoaders().get(null)}} returns a {{null}} {{UniqueEntityLoader}}, and attempting to call {{UniqueEntityLoader.load(Serializable, Object, SharedSessionContractImplementor, LockOptions)}} will throw the {{NullPointerException}}.
In case of a stateful {{Session}}, the {{LoadEvent(Serializable, String, Object, LockOptions, boolean, EventSource)}} constructor has the following code: {code:java} if ( lockOptions.getLockMode() == null ) { lockOptions.setLockMode(DEFAULT_LOCK_MODE); } {code} There is no similar default value check for the {{StatelessSession}} code path.
Maybe the {{StatelessSession}} should set the default {{LockMode.NONE}} lock mode when a {{null}} argument is passed? It would be more in line with the stateful {{Session}}, and would not throw {{NullPointerException}}. |
|