We're updating the issue view to help you get more done. 

NPE when using Criteria+Projection+LockMode


I have a problem to lock some row when I use a projection to get entity count ,and occur nullPointerException ! I stepped through the hibernate code in the debugger. This is a BUG!! This is a long time ago BUG!!

Hibernate version:5.1.0.Final

Code between sessionFactory.openSession() and session.close():

1 2 3 Criteria criteria = getSession().createCriteria(TbGenerateRecord.class); criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); criteria.setProjection(Projections.rowCount()).uniqueResult();

soon after,I stepped through the hibernate code in the debugger.
The NullPointerException in CriteriaLoader.applyLocks happens because its local "entityAliases" array is null; that array is null because the "aliases" field (defined in OuterJoinLoader) is null. So the question is, where did (or should) OuterJoinLoader.aliases come from? Well, it comes from a method called initFromWalker(JoinWalker walker), which calls walker.getAliases().

So now the question is, what's up with this JoinWalker? In this case, it is a CriteriaJoinWalker, which extends AbstractEntityJoinWalker.

Where, then, does (or should) JoinWalker.aliases get initalized? It happens in a method called initPersisters. This method, in turn, is called by the AbstractEntityJoinWalker.initAll method.

Why isn't CriteriaJoinWalker calling that initAll method? Here's the relevant code in the CriteriaJoinWalker constructor:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 if ( translator.hasProjection() ) { initProjection( translator.getSelect(), translator.getWhereCondition(), translator.getOrderBy(), translator.getGroupBy(), LockOptions.NONE ); resultTypes = translator.getProjectedTypes(); userAliases = translator.getProjectedAliases(); includeInResultRow = new boolean[resultTypes.length]; Arrays.fill( includeInResultRow, true ); } else { initAll( translator.getWhereCondition(), translator.getOrderBy(), LockOptions.NONE ); // root entity comes last userAliasList.add( criteria.getAlias() ); //root entity comes *last* resultTypeList.add( translator.getResultType( criteria ) ); includeInResultRowList.add( true ); userAliases = ArrayHelper.toStringArray( userAliasList ); resultTypes = ArrayHelper.toTypeArray( resultTypeList ); includeInResultRow = ArrayHelper.toBooleanArray( includeInResultRowList ); }

So, when there's a projection, we don't call the initAll method, and so the aliases field is never initialized. NPE is not a helpful error message.

I can't distinguish between the following possibilities:

1. It's not legal to use setLockMode and projections together.
2. It is legal, and the lack of initialization in this case is a bug.
3. It is legal, but we're doing it all wrong; a more experienced user would do [some clever thing].

If there are solutions, please contact me:2245089166@qq.com

Full stack trace of any exception that occurs:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 java.lang.NullPointerException at org.hibernate.loader.criteria.CriteriaLoader.applyLocks(CriteriaLoader.java:237) at org.hibernate.loader.Loader.preprocessSQL(Loader.java:234) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1894) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1874) at org.hibernate.loader.Loader.doQuery(Loader.java:919) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336) at org.hibernate.loader.Loader.doList(Loader.java:2610) at org.hibernate.loader.Loader.listUsingQueryCache(Loader.java:2452) at org.hibernate.loader.Loader.list(Loader.java:2414) at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:109) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1787) at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:363) at org.hibernate.internal.CriteriaImpl.uniqueResult(CriteriaImpl.java:385) at net.yasion.common.utils.HibernateUtils.countByCriteria(HibernateUtils.java:274) at net.yasion.common.dao.impl.BaseDAOImpl.sourceListByCriteria(BaseDAOImpl.java:574) at net.yasion.common.dao.impl.BaseDAOImpl.listByCriteria(BaseDAOImpl.java:484) at net.yasion.shortlink.service.impl.LinkServiceImpl.shortLink(LinkServiceImpl.java:126)


Hibernate 5.1.0 Final,Spring 4.2.5.RELEASE






Fix versions





Suitable for new contributors


Requires Release Note


Pull Request





Affects versions