📄 loader.java
字号:
* limit parameters. */ protected final PreparedStatement prepareQueryStatement( String sql, final QueryParameters queryParameters, final boolean scroll, final SessionImplementor session) throws SQLException, HibernateException { Dialect dialect = session.getFactory().getDialect(); RowSelection selection = queryParameters.getRowSelection(); boolean useLimit = useLimit(selection, dialect); boolean hasFirstRow = getFirstRow(selection)>0; boolean useOffset = hasFirstRow && useLimit && dialect.supportsLimitOffset(); boolean scrollable = session.getFactory().isScrollableResultSetsEnabled() && ( scroll || //ie. a query called using scroll() ( hasFirstRow && !useOffset ) //we want to skip some rows at the start ); if (useLimit) sql = dialect.getLimitString( sql, useOffset, getMaxOrLimit(selection, dialect) ); PreparedStatement st = session.getBatcher().prepareQueryStatement(sql, scrollable); try { int col=1; if ( useLimit && dialect.bindLimitParametersFirst() ) { col += bindLimitParameters(st, col, selection, session); } col += bindPositionalParameters(st, queryParameters, col, session); col += bindNamedParameters(st, queryParameters.getNamedParameters(), col, session); if ( useLimit && !dialect.bindLimitParametersFirst() ) { col += bindLimitParameters(st, col, selection, session); } if (!useLimit) setMaxRows(st, selection); if (selection!=null && selection.getTimeout()!=null) { st.setQueryTimeout( selection.getTimeout().intValue() ); } } catch (SQLException sqle) { JDBCExceptionReporter.logExceptions(sqle); session.getBatcher().closeQueryStatement(st, null); throw sqle; } catch (HibernateException he) { session.getBatcher().closeQueryStatement(st, null); throw he; } return st; } /** * Some dialect-specific LIMIT clauses require the maximium last row number, * others require the maximum returned row count. */ private static int getMaxOrLimit(final RowSelection selection, final Dialect dialect) { int firstRow = getFirstRow(selection); int lastRow = selection.getMaxRows().intValue(); if ( dialect.useMaxForLimit() ) { return lastRow + firstRow; } else { return lastRow; } } /** * Bind parameters needed by the dialect-specific LIMIT clause */ private int bindLimitParameters( final PreparedStatement st, final int index, final RowSelection selection, final SessionImplementor session) throws SQLException { Dialect dialect = session.getFactory().getDialect(); if ( !dialect.supportsVariableLimit() ) return 0; if ( !hasMaxRows(selection) ) throw new AssertionFailure("Bug binding LIMIT parameters"); int firstRow = getFirstRow(selection); int lastRow = getMaxOrLimit(selection, dialect); boolean hasFirstRow = firstRow>0 && dialect.supportsLimitOffset(); boolean reverse = dialect.bindLimitParametersInReverseOrder(); if (hasFirstRow) st.setInt( index + (reverse ? 1 : 0 ), firstRow ); st.setInt( index + ( reverse || !hasFirstRow ? 0 : 1 ), lastRow ); return hasFirstRow?2:1; } /** * Use JDBC API to limit the number of rows returned by the SQL query if necessary */ private void setMaxRows(final PreparedStatement st, final RowSelection selection) throws SQLException { if ( hasMaxRows(selection) ) { st.setMaxRows( selection.getMaxRows().intValue() + getFirstRow(selection) ); } } /** * Fetch a <tt>PreparedStatement</tt>, call <tt>setMaxRows</tt> and then execute it, * advance to the first result and return an SQL <tt>ResultSet</tt> */ protected final ResultSet getResultSet( final PreparedStatement st, final RowSelection selection, final SessionImplementor session) throws SQLException, HibernateException { ResultSet rs = null; try { rs = session.getBatcher().getResultSet(st); Dialect dialect = session.getFactory().getDialect(); if ( !dialect.supportsLimitOffset() || !useLimit(selection, dialect) ) { advance(rs, selection, session); } return rs; } catch (SQLException sqle) { JDBCExceptionReporter.logExceptions(sqle); session.getBatcher().closeQueryStatement(st, rs); throw sqle; } } /** * Bind named parameters to the <tt>PreparedStatement</tt>. This has an empty * implementation on this superclass and should be implemented by subclasses * (queries) which allow named parameters. */ protected int bindNamedParameters( PreparedStatement st, Map namedParams, int start, SessionImplementor session) throws SQLException, HibernateException { return 0; } private List loadEntity( final SessionImplementor session, final Object[] values, final Type[] types, final Object optionalObject, final Serializable optionalId ) throws SQLException, HibernateException { return doQueryAndInitializeNonLazyCollections( session, new QueryParameters(types, values), optionalObject, optionalId, null, false ); } /** * Called by subclasses that load entities */ protected final List loadEntity( final SessionImplementor session, final Serializable id, final Type identifierType, final Object optionalObject, final Serializable optionalIdentifier ) throws SQLException, HibernateException { return loadEntity( session, new Object[] {id}, new Type[] {identifierType}, optionalObject, optionalIdentifier ); } /** * Called by subclasses that batch load entities */ protected final List loadEntityBatch( final SessionImplementor session, final Serializable[] ids, final Type idType, final Object optionalObject, final Serializable optionalID ) throws SQLException, HibernateException { Type[] types = new Type[ids.length]; Arrays.fill(types, idType); return loadEntity(session, ids, types, optionalObject, optionalID); } /** * Called by subclasses that load collections */ protected final void loadCollection( final SessionImplementor session, final Serializable id, final Type type) throws SQLException, HibernateException { loadCollection( session, new Serializable[] {id}, new Type[] {type} ); } /** * Called by subclasses that batch initialize collections */ protected final void loadCollectionBatch( final SessionImplementor session, final Serializable[] ids, final Type type) throws SQLException, HibernateException { Type[] idTypes = new Type[ids.length]; Arrays.fill(idTypes, type); loadCollection(session, ids, idTypes); } /** * Called by subclasses that initialize collections */ private void loadCollection( final SessionImplementor session, final Serializable[] ids, final Type[] types) throws SQLException, HibernateException { doQueryAndInitializeNonLazyCollections( session, new QueryParameters(types, ids), null, null, ids, true ); } /** * Return the query results, using the query cache, called * by subclasses that implement cacheable queries */ protected List list( final SessionImplementor session, final QueryParameters queryParameters, final Set querySpaces, final Type[] resultTypes) throws SQLException, HibernateException { final SessionFactoryImplementor factory = session.getFactory(); final boolean cacheable = factory.isQueryCacheEnabled() && queryParameters.isCacheable(); if (cacheable) { QueryCache queryCache = factory.getQueryCache( queryParameters.getCacheRegion() ); QueryKey key = new QueryKey( getSQLString(), queryParameters ); List result = queryCache.get(key, resultTypes, querySpaces, session); if (result==null) { result = doList(session, queryParameters); if (cacheable) queryCache.put(key, resultTypes, result, session); } return getResultList(result); } else { return getResultList( doList(session, queryParameters) ); } } /** * Actually execute a query, ignoring the query cache */ protected final List doList(final SessionImplementor session, final QueryParameters queryParameters) throws SQLException, HibernateException { return doQueryAndInitializeNonLazyCollections( session, queryParameters, null, null, null, true ); } private String[][] suffixedKeyColumns; private String[][] suffixedVersionColumNames; private String[][][] suffixedPropertyColumns; private String[] suffixedDiscriminatorColumn; protected static final String[] NO_SUFFIX = { StringHelper.EMPTY_STRING }; /** * Calculate and cache select-clause suffixes. Must be * called by subclasses after instantiation. */ protected void postInstantiate() { Loadable[] persisters = getPersisters(); String[] suffixes = getSuffixes(); suffixedKeyColumns = new String[persisters.length][]; suffixedPropertyColumns = new String[persisters.length][][]; suffixedVersionColumNames = new String[persisters.length][]; suffixedDiscriminatorColumn = new String[persisters.length]; for ( int i=0; i<persisters.length; i++ ) { suffixedKeyColumns[i] = persisters[i].getIdentifierAliases( suffixes[i] ); suffixedPropertyColumns[i] = getSuffixedPropertyAliases( persisters[i], suffixes[i] ); suffixedDiscriminatorColumn[i] = persisters[i].getDiscriminatorAlias( suffixes[i] ); if ( persisters[i].isVersioned() ) { suffixedVersionColumNames[i] = suffixedPropertyColumns[i][ persisters[i].getVersionProperty() ]; } } } private static String[][] getSuffixedPropertyAliases(Loadable persister, String suffix) { int size = persister.getPropertyNames().length; String[][] suffixedPropertyAliases = new String[size][]; for ( int j=0; j<size; j++ ) { suffixedPropertyAliases[j] = persister.getPropertyAliases( suffix, j ); } return suffixedPropertyAliases; } /** * Utility method that generate 0_, 1_ suffixes. Subclasses don't * necessarily need to use this algorithm, but it is intended that * they will in most cases. */ protected static String[] generateSuffixes(int length) { if (length==0) return NO_SUFFIX; String[] suffixes = new String[length]; for ( int i=0; i<length; i++ ) { suffixes[i] = Integer.toString(i) + StringHelper.UNDERSCORE; } return suffixes; } /** * Generate a nice alias for the given class name or collection role * name and unique integer. Subclasses do <em>not</em> have to use * aliases of this form. * @return an alias of the form <tt>foo1_</tt> */ protected static String generateAlias(String description, int unique) { return StringHelper.truncate( StringHelper.unqualify(description), 10 ) .toLowerCase() .replace('$','_') + Integer.toString(unique) + StringHelper.UNDERSCORE; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -