下面列出了怎么用org.hibernate.param.ParameterSpecification的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Interprets the {@code WHERE} clause from the user-defined update/delete query
*
* @param whereClause The user-defined {@code WHERE} clause
*
* @return The bulk-id-ready {@code WHERE} clause representation
*/
@SuppressWarnings("unchecked")
protected ProcessedWhereClause processWhereClause(AST whereClause) {
if ( whereClause.getNumberOfChildren() != 0 ) {
// If a where clause was specified in the update/delete query, use it to limit the
// ids that will be returned and inserted into the id table...
try {
SqlGenerator sqlGenerator = new SqlGenerator( sessionFactory );
sqlGenerator.whereClause( whereClause );
String userWhereClause = sqlGenerator.getSQL().substring( 7 ); // strip the " where "
List<ParameterSpecification> idSelectParameterSpecifications = sqlGenerator.getCollectedParameters();
return new ProcessedWhereClause( userWhereClause, idSelectParameterSpecifications );
}
catch ( RecognitionException e ) {
throw new HibernateException( "Unable to generate id select for DML operation", e );
}
}
else {
return ProcessedWhereClause.NO_WHERE_CLAUSE;
}
}
@Override
protected void out(AST n) {
if ( n instanceof Node ) {
out( ( (Node) n ).getRenderText( sessionFactory ) );
}
else {
super.out( n );
}
if ( n instanceof ParameterNode ) {
collectedParameters.add( ( (ParameterNode) n ).getHqlParameterSpecification() );
}
else if ( n instanceof ParameterContainer ) {
if ( ( (ParameterContainer) n ).hasEmbeddedParameters() ) {
ParameterSpecification[] specifications = ( (ParameterContainer) n ).getEmbeddedParameters();
if ( specifications != null ) {
collectedParameters.addAll( Arrays.asList( specifications ) );
}
}
}
}
private List<ParameterSpecification> getCollectedParameterSpecifications(ReactiveSession session) {
// Currently, ORM returns null for getCollectedParameterSpecifications() a StatementExecute
List<ParameterSpecification> parameterSpecifications = getCollectedParameterSpecifications();
if ( parameterSpecifications == null ) {
final SqlGenerator gen = new SqlGenerator( session.getFactory() );
try {
gen.statement( (AST) getSqlAST() );
parameterSpecifications = gen.getCollectedParameters();
} catch (RecognitionException e) {
throw QuerySyntaxException.convert(e);
}
}
return parameterSpecifications;
}
public static Object[] toParameterArray(
QueryParameters queryParameters,
List<ParameterSpecification> parameterSpecifications,
SharedSessionContractImplementor session) {
return PreparedStatementAdaptor.bind( adaptor -> {
int pos = 1;
for (ParameterSpecification parameterSpecification: parameterSpecifications) {
pos += parameterSpecification.bind(adaptor, queryParameters, session, pos);
}
} );
}
public CteValuesListUpdateHandlerImpl(
SessionFactoryImplementor factory,
HqlSqlWalker walker,
String catalog,
String schema) {
super( factory, walker, catalog, schema );
String[] tableNames = getTargetedQueryable().getConstraintOrderedTableNameClosure();
String[][] columnNames = getTargetedQueryable().getContraintOrderedTableKeyColumnClosure();
String idSubselect = generateIdSubselect( getTargetedQueryable() );
updates = new String[tableNames.length];
assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][];
for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) {
boolean affected = false;
final List<ParameterSpecification> parameterList = new ArrayList<>();
final Update update = new Update( factory.getServiceRegistry().getService( JdbcServices.class ).getDialect() )
.setTableName( tableNames[tableIndex] )
.setWhere( "(" + String.join( ", ", (CharSequence[]) columnNames[tableIndex] ) + ") in (" + idSubselect + ")" );
if ( factory().getSessionFactoryOptions().isCommentsEnabled() ) {
update.setComment( "bulk update" );
}
final List<AssignmentSpecification> assignmentSpecifications = walker.getAssignmentSpecifications();
for ( AssignmentSpecification assignmentSpecification : assignmentSpecifications ) {
if ( assignmentSpecification.affectsTable( tableNames[tableIndex] ) ) {
affected = true;
update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() );
if ( assignmentSpecification.getParameters() != null ) {
Collections.addAll( parameterList, assignmentSpecification.getParameters() );
}
}
}
if ( affected ) {
updates[tableIndex] = update.toStatementString();
assignmentParameterSpecifications[tableIndex] = parameterList.toArray( new ParameterSpecification[parameterList.size()] );
}
}
}
protected List<Object[]> selectIds(
SharedSessionContractImplementor session,
QueryParameters queryParameters) {
List<Object[]> ids = new ArrayList<>();
try {
try (PreparedStatement ps = session.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( idSelect, false )) {
int position = 1;
for ( ParameterSpecification parameterSpecification : idSelectParameterSpecifications ) {
position += parameterSpecification.bind( ps, queryParameters, session, position );
}
Dialect dialect = session.getFactory().getServiceRegistry().getService( JdbcServices.class ).getDialect();
ResultSet rs = session
.getJdbcCoordinator()
.getResultSetReturn()
.extract( ps );
while ( rs.next() ) {
Object[] result = new Object[targetedPersister.getIdentifierColumnNames().length];
for ( String columnName : targetedPersister.getIdentifierColumnNames() ) {
int columnIndex = rs.findColumn( StringHelper.unquote( columnName, dialect ) );
Object column = rs.getObject(columnIndex);
result[columnIndex - 1] = column;
}
ids.add( result );
}
}
}
catch ( SQLException e ) {
throw convert( e, "could not select ids for bulk operation", idSelect );
}
return ids;
}
@Override
public int bind(PreparedStatement statement, QueryParameters qp, SharedSessionContractImplementor session, int position)
throws SQLException {
int bindCount = 0;
for ( ParameterSpecification paramSpec : paramSpecs ) {
bindCount += paramSpec.bind( statement, qp, session, position + bindCount );
}
return bindCount;
}
private String collectDisplayInfo() {
StringBuilder buffer = new StringBuilder();
for ( ParameterSpecification paramSpec : paramSpecs ) {
buffer.append( ( paramSpec ).renderDisplayInfo() );
}
return buffer.toString();
}
private List<ParameterSpecification> getParameterSpecification() {
List<ParameterSpecification> parameterSpecifications =
embeddedParameters.stream()
.filter( o -> o instanceof DynamicFilterParameterSpecification )
.collect( Collectors.toList() );
parameterSpecifications.addAll(
embeddedParameters.stream()
.filter( o -> ! (o instanceof DynamicFilterParameterSpecification ) )
.collect( Collectors.toList() ) );
return parameterSpecifications;
}
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) {
if ( indexCollectionSelectorParamSpec == null ) {
if ( elementType.getIndexCollectionSelectorParamSpec() != null ) {
embeddedParameters.remove( elementType.getIndexCollectionSelectorParamSpec() );
elementType.setIndexCollectionSelectorParamSpec( null );
}
}
else {
elementType.setIndexCollectionSelectorParamSpec( indexCollectionSelectorParamSpec );
addEmbeddedParameter( indexCollectionSelectorParamSpec );
}
}
private void applyParameterSpecifications(ParameterContainer parameterContainer) {
if ( parameterContainer.hasEmbeddedParameters() ) {
ParameterSpecification[] specs = parameterContainer.getEmbeddedParameters();
for ( ParameterSpecification spec : specs ) {
applyParameterSpecification( spec );
}
}
}
/**
* We specifically override this method here, because in general we know much more
* about the parameters and their appropriate bind positions here then we do in
* our super because we track them explciitly here through the ParameterSpecification
* interface.
*
* @param queryParameters The encapsulation of the parameter values to be bound.
* @param startIndex The position from which to start binding parameter values.
* @param session The originating session.
* @return The number of JDBC bind positions actually bound during this method execution.
* @throws SQLException Indicates problems performing the binding.
*/
protected int bindParameterValues(
final PreparedStatement statement,
final QueryParameters queryParameters,
final int startIndex,
final SessionImplementor session) throws SQLException {
int position = bindFilterParameterValues( statement, queryParameters, startIndex, session );
List parameterSpecs = queryTranslator.getSqlAST().getWalker().getParameters();
Iterator itr = parameterSpecs.iterator();
while ( itr.hasNext() ) {
ParameterSpecification spec = ( ParameterSpecification ) itr.next();
position += spec.bind( statement, queryParameters, session, position );
}
return position - startIndex;
}
public int execute(QueryParameters parameters, SessionImplementor session) throws HibernateException {
coordinateSharedCacheCleanup( session );
PreparedStatement st = null;
RowSelection selection = parameters.getRowSelection();
try {
try {
st = session.getBatcher().prepareStatement( sql );
Iterator paramSpecifications = getWalker().getParameters().iterator();
int pos = 1;
while ( paramSpecifications.hasNext() ) {
final ParameterSpecification paramSpec = ( ParameterSpecification ) paramSpecifications.next();
pos += paramSpec.bind( st, parameters, session, pos );
}
if ( selection != null ) {
if ( selection.getTimeout() != null ) {
st.setQueryTimeout( selection.getTimeout().intValue() );
}
}
return st.executeUpdate();
}
finally {
if ( st != null ) {
session.getBatcher().closeStatement( st );
}
}
}
catch( SQLException sqle ) {
throw JDBCExceptionHelper.convert(
getFactory().getSQLExceptionConverter(),
sqle,
"could not execute update query",
sql
);
}
}
@SuppressWarnings("unchecked")
public TableBasedUpdateHandlerImpl(
SessionFactoryImplementor factory,
HqlSqlWalker walker,
IdTableInfo idTableInfo) {
super( factory, walker );
final Dialect dialect = factory.getJdbcServices().getJdbcEnvironment().getDialect();
final UpdateStatement updateStatement = (UpdateStatement) walker.getAST();
final FromElement fromElement = updateStatement.getFromClause().getFromElement();
this.targetedPersister = fromElement.getQueryable();
final String bulkTargetAlias = fromElement.getTableAlias();
final ProcessedWhereClause processedWhereClause = processWhereClause( updateStatement.getWhereClause() );
this.idSelectParameterSpecifications = processedWhereClause.getIdSelectParameterSpecifications();
this.idInsertSelect = generateIdInsertSelect( bulkTargetAlias, idTableInfo, processedWhereClause );
log.tracev( "Generated ID-INSERT-SELECT SQL (multi-table update) : {0}", idInsertSelect );
String[] tableNames = targetedPersister.getConstraintOrderedTableNameClosure();
String[][] columnNames = targetedPersister.getContraintOrderedTableKeyColumnClosure();
String idSubselect = generateIdSubselect( targetedPersister, idTableInfo );
updates = new String[tableNames.length];
assignmentParameterSpecifications = new ParameterSpecification[tableNames.length][];
for ( int tableIndex = 0; tableIndex < tableNames.length; tableIndex++ ) {
boolean affected = false;
final List<ParameterSpecification> parameterList = new ArrayList<>();
final Update update = new Update( dialect )
.setTableName( tableNames[tableIndex] )
.setWhere( "(" + String.join( ", ", columnNames[tableIndex] ) + ") IN (" + idSubselect + ")" );
if ( factory().getSessionFactoryOptions().isCommentsEnabled() ) {
update.setComment( "bulk update" );
}
final List<AssignmentSpecification> assignmentSpecifications = walker.getAssignmentSpecifications();
for ( AssignmentSpecification assignmentSpecification : assignmentSpecifications ) {
if ( assignmentSpecification.affectsTable( tableNames[tableIndex] ) ) {
affected = true;
update.appendAssignmentFragment( assignmentSpecification.getSqlAssignmentFragment() );
if ( assignmentSpecification.getParameters() != null ) {
Collections.addAll( parameterList, assignmentSpecification.getParameters() );
}
}
}
if ( affected ) {
updates[tableIndex] = update.toStatementString();
assignmentParameterSpecifications[tableIndex] = parameterList.toArray( new ParameterSpecification[parameterList.size()] );
}
}
}
public ProcessedWhereClause(String userWhereClauseFragment, List<ParameterSpecification> idSelectParameterSpecifications) {
this.userWhereClauseFragment = userWhereClauseFragment;
this.idSelectParameterSpecifications = idSelectParameterSpecifications;
}
public List<ParameterSpecification> getIdSelectParameterSpecifications() {
return idSelectParameterSpecifications;
}
public void addEmbeddedParameter(ParameterSpecification specification) {
if ( embeddedParameters == null ) {
embeddedParameters = new ArrayList<ParameterSpecification>();
}
embeddedParameters.add( specification );
}
public ParameterSpecification[] getEmbeddedParameters() {
return embeddedParameters.toArray( new ParameterSpecification[ embeddedParameters.size() ] );
}
public ParameterSpecification getHqlParameterSpecification() {
return parameterSpecification;
}
public void setHqlParameterSpecification(ParameterSpecification parameterSpecification) {
this.parameterSpecification = parameterSpecification;
}
@Override
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate)
throws SemanticException {
if ( isResolved() ) {
return;
}
FromReferenceNode collectionNode = (FromReferenceNode) getFirstChild();
SessionFactoryHelper sessionFactoryHelper = getSessionFactoryHelper();
collectionNode.resolveIndex( this ); // Fully resolve the map reference, create implicit joins.
Type type = collectionNode.getDataType();
if ( !type.isCollectionType() ) {
throw new SemanticException( "The [] operator cannot be applied to type " + type.toString() );
}
String collectionRole = ( (CollectionType) type ).getRole();
QueryableCollection queryableCollection = sessionFactoryHelper.requireQueryableCollection( collectionRole );
if ( !queryableCollection.hasIndex() ) {
throw new QueryException( "unindexed fromElement before []: " + collectionNode.getPath() );
}
// Generate the inner join -- The elements need to be joined to the collection they are in.
FromElement fromElement = collectionNode.getFromElement();
String elementTable = fromElement.getTableAlias();
FromClause fromClause = fromElement.getFromClause();
String path = collectionNode.getPath();
FromElement elem = fromClause.findCollectionJoin( path );
if ( elem == null ) {
FromElementFactory factory = new FromElementFactory( fromClause, fromElement, path );
elem = factory.createCollectionElementsJoin( queryableCollection, elementTable );
LOG.debugf( "No FROM element found for the elements of collection join path %s, created %s", path, elem );
}
else {
LOG.debugf( "FROM element found for collection join path %s", path );
}
// The 'from element' that represents the elements of the collection.
setFromElement( fromElement );
// Add the condition to the join sequence that qualifies the indexed element.
AST selector = collectionNode.getNextSibling();
if ( selector == null ) {
throw new QueryException( "No index value!" );
}
// Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
String collectionTableAlias = elementTable;
if ( elem.getCollectionTableAlias() != null ) {
collectionTableAlias = elem.getCollectionTableAlias();
}
// TODO: get SQL rendering out of here, create an AST for the join expressions.
// Use the SQL generator grammar to generate the SQL text for the index expression.
JoinSequence joinSequence = fromElement.getJoinSequence();
String[] indexCols = queryableCollection.getIndexColumnNames();
if ( indexCols.length != 1 ) {
throw new QueryException( "composite-index appears in []: " + collectionNode.getPath() );
}
SqlGenerator gen = new SqlGenerator( getSessionFactoryHelper().getFactory() );
try {
gen.simpleExpr( selector ); //TODO: used to be exprNoParens! was this needed?
}
catch (RecognitionException e) {
throw new QueryException( e.getMessage(), e );
}
String selectorExpression = gen.getSQL();
joinSequence.addCondition( collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression );
List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
if ( paramSpecs != null ) {
switch ( paramSpecs.size() ) {
case 0:
// nothing to do
break;
case 1:
ParameterSpecification paramSpec = paramSpecs.get( 0 );
paramSpec.setExpectedType( queryableCollection.getIndexType() );
fromElement.setIndexCollectionSelectorParamSpec( paramSpec );
break;
default:
fromElement.setIndexCollectionSelectorParamSpec(
new AggregatedIndexCollectionSelectorParameterSpecifications( paramSpecs )
);
break;
}
}
// Now, set the text for this node. It should be the element columns.
String[] elementColumns = queryableCollection.getElementColumnNames( elementTable );
setText( elementColumns[0] );
setResolved();
}
public AggregatedIndexCollectionSelectorParameterSpecifications(List<ParameterSpecification> paramSpecs) {
this.paramSpecs = paramSpecs;
}
/**
* Mutate the subtree relating to a row-value-constructor to instead use
* a series of ANDed predicates. This allows multi-column type comparisons
* and explicit row-value-constructor syntax even on databases which do
* not support row-value-constructor.
* <p/>
* For example, here we'd mutate "... where (col1, col2) = ('val1', 'val2) ..." to
* "... where col1 = 'val1' and col2 = 'val2' ..."
*
* @param valueElements The number of elements in the row value constructor list.
*/
private void mutateRowValueConstructorSyntax(int valueElements) {
// mutation depends on the types of nodes involved...
int comparisonType = getType();
String comparisonText = getText();
switch ( comparisonType ) {
case HqlSqlTokenTypes.EQ:
setType( HqlSqlTokenTypes.AND );
setText( "AND" );
break;
case HqlSqlTokenTypes.NE:
setType( HqlSqlTokenTypes.OR );
setText( "OR" );
break;
default:
throw new QuerySyntaxException( comparisonText + " operator not supported on composite types." );
}
String[] lhsElementTexts = extractMutationTexts( getLeftHandOperand(), valueElements );
String[] rhsElementTexts = extractMutationTexts( getRightHandOperand(), valueElements );
ParameterSpecification lhsEmbeddedCompositeParameterSpecification =
getLeftHandOperand() == null || ( !ParameterNode.class.isInstance( getLeftHandOperand() ) )
? null
: ( (ParameterNode) getLeftHandOperand() ).getHqlParameterSpecification();
ParameterSpecification rhsEmbeddedCompositeParameterSpecification =
getRightHandOperand() == null || ( !ParameterNode.class.isInstance( getRightHandOperand() ) )
? null
: ( (ParameterNode) getRightHandOperand() ).getHqlParameterSpecification();
translate(
valueElements,
comparisonType,
comparisonText,
lhsElementTexts,
rhsElementTexts,
lhsEmbeddedCompositeParameterSpecification,
rhsEmbeddedCompositeParameterSpecification,
this
);
}
protected void translate(
int valueElements, int comparisonType,
String comparisonText, String[] lhsElementTexts,
String[] rhsElementTexts,
ParameterSpecification lhsEmbeddedCompositeParameterSpecification,
ParameterSpecification rhsEmbeddedCompositeParameterSpecification,
AST container) {
for ( int i = valueElements - 1; i > 0; i-- ) {
if ( i == 1 ) {
AST op1 = getASTFactory().create( comparisonType, comparisonText );
AST lhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[0] );
AST rhs1 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[0] );
op1.setFirstChild( lhs1 );
lhs1.setNextSibling( rhs1 );
container.setFirstChild( op1 );
AST op2 = getASTFactory().create( comparisonType, comparisonText );
AST lhs2 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[1] );
AST rhs2 = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[1] );
op2.setFirstChild( lhs2 );
lhs2.setNextSibling( rhs2 );
op1.setNextSibling( op2 );
// "pass along" our initial embedded parameter node(s) to the first generated
// sql fragment so that it can be handled later for parameter binding...
SqlFragment fragment = (SqlFragment) lhs1;
if ( lhsEmbeddedCompositeParameterSpecification != null ) {
fragment.addEmbeddedParameter( lhsEmbeddedCompositeParameterSpecification );
}
if ( rhsEmbeddedCompositeParameterSpecification != null ) {
fragment.addEmbeddedParameter( rhsEmbeddedCompositeParameterSpecification );
}
}
else {
AST op = getASTFactory().create( comparisonType, comparisonText );
AST lhs = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, lhsElementTexts[i] );
AST rhs = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, rhsElementTexts[i] );
op.setFirstChild( lhs );
lhs.setNextSibling( rhs );
AST newContainer = getASTFactory().create( container.getType(), container.getText() );
container.setFirstChild( newContainer );
newContainer.setNextSibling( op );
container = newContainer;
}
}
}
@Override
public void addEmbeddedParameter(ParameterSpecification specification) {
embeddedParameters.add( specification );
}
@Override
public ParameterSpecification[] getEmbeddedParameters() {
final List<ParameterSpecification> parameterSpecification = getParameterSpecification();
return parameterSpecification.toArray( new ParameterSpecification[ parameterSpecification.size() ] );
}
public ParameterSpecification getIndexCollectionSelectorParamSpec() {
return elementType.getIndexCollectionSelectorParamSpec();
}
public ParameterSpecification getIndexCollectionSelectorParamSpec() {
return indexCollectionSelectorParamSpec;
}
public void setIndexCollectionSelectorParamSpec(ParameterSpecification indexCollectionSelectorParamSpec) {
this.indexCollectionSelectorParamSpec = indexCollectionSelectorParamSpec;
}
public AssignmentSpecification(AST eq, Queryable persister) {
if ( eq.getType() != HqlSqlTokenTypes.EQ ) {
throw new QueryException( "assignment in set-clause not associated with equals" );
}
this.eq = eq;
this.factory = persister.getFactory();
// Needed to bump this up to DotNode, because that is the only thing which currently
// knows about the property-ref path in the correct format; it is either this, or
// recurse over the DotNodes constructing the property path just like DotNode does
// internally
final DotNode lhs = (DotNode) eq.getFirstChild();
final SqlNode rhs = (SqlNode) lhs.getNextSibling();
validateLhs( lhs );
final String propertyPath = lhs.getPropertyPath();
Set<String> temp = new HashSet<String>();
// yuck!
if ( persister instanceof UnionSubclassEntityPersister ) {
final String[] tables = persister.getConstraintOrderedTableNameClosure();
Collections.addAll( temp, tables );
}
else {
temp.add(
persister.getSubclassTableName( persister.getSubclassPropertyTableNumber( propertyPath ) )
);
}
this.tableNames = Collections.unmodifiableSet( temp );
if ( rhs == null ) {
hqlParameters = new ParameterSpecification[0];
}
else if ( isParam( rhs ) ) {
hqlParameters = new ParameterSpecification[] {( (ParameterNode) rhs ).getHqlParameterSpecification()};
}
else {
List parameterList = ASTUtil.collectChildren(
rhs,
new ASTUtil.IncludePredicate() {
public boolean include(AST node) {
return isParam( node );
}
}
);
hqlParameters = new ParameterSpecification[parameterList.size()];
Iterator itr = parameterList.iterator();
int i = 0;
while ( itr.hasNext() ) {
hqlParameters[i++] = ( (ParameterNode) itr.next() ).getHqlParameterSpecification();
}
}
}