use of org.hibernate.type.ProcedureParameterExtractionAware in project hibernate-orm by hibernate.
the class AbstractParameterRegistrationImpl method prepare.
@Override
public void prepare(CallableStatement statement, int startIndex) throws SQLException {
// initially set up the Type we will use for binding as the explicit type.
Type typeToUse = hibernateType;
int[] sqlTypesToUse = sqlTypes;
// however, for Calendar binding with an explicit TemporalType we may need to adjust this...
if (bind != null && bind.getExplicitTemporalType() != null) {
if (Calendar.class.isInstance(bind.getValue())) {
switch(bind.getExplicitTemporalType()) {
case TIMESTAMP:
{
typeToUse = CalendarType.INSTANCE;
sqlTypesToUse = typeToUse.sqlTypes(session().getFactory());
break;
}
case DATE:
{
typeToUse = CalendarDateType.INSTANCE;
sqlTypesToUse = typeToUse.sqlTypes(session().getFactory());
break;
}
case TIME:
{
typeToUse = CalendarTimeType.INSTANCE;
sqlTypesToUse = typeToUse.sqlTypes(session().getFactory());
break;
}
}
}
}
this.startIndex = startIndex;
if (mode == ParameterMode.IN || mode == ParameterMode.INOUT || mode == ParameterMode.OUT) {
if (mode == ParameterMode.INOUT || mode == ParameterMode.OUT) {
if (sqlTypesToUse.length > 1) {
// there is more than one column involved; see if the Hibernate Type can handle
// multi-param extraction...
final boolean canHandleMultiParamExtraction = ProcedureParameterExtractionAware.class.isInstance(hibernateType) && ((ProcedureParameterExtractionAware) hibernateType).canDoExtraction();
if (!canHandleMultiParamExtraction) {
// it cannot...
throw new UnsupportedOperationException("Type [" + hibernateType + "] does support multi-parameter value extraction");
}
}
// e.g., Oracle.
if (sqlTypesToUse.length == 1 && procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding()) {
statement.registerOutParameter(getName(), sqlTypesToUse[0]);
} else {
for (int i = 0; i < sqlTypesToUse.length; i++) {
statement.registerOutParameter(startIndex + i, sqlTypesToUse[i]);
}
}
}
if (mode == ParameterMode.INOUT || mode == ParameterMode.IN) {
if (bind == null || bind.getValue() == null) {
// parameter defines a default value. Deferring to that information would be the best option
if (passNulls) {
log.debugf("Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to true; binding NULL", procedureCall.getProcedureName(), this);
if (this.procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding()) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(statement, null, this.getName(), session());
} else {
typeToUse.nullSafeSet(statement, null, startIndex, session());
}
} else {
log.debugf("Stored procedure [%s] IN/INOUT parameter [%s] not bound and `passNulls` was set to false; assuming procedure defines default value", procedureCall.getProcedureName(), this);
}
} else {
if (this.procedureCall.getParameterStrategy() == ParameterStrategy.NAMED && canDoNameParameterBinding()) {
((ProcedureParameterNamedBinder) typeToUse).nullSafeSet(statement, bind.getValue(), this.getName(), session());
} else {
typeToUse.nullSafeSet(statement, bind.getValue(), startIndex, session());
}
}
}
} else {
// we have a REF_CURSOR type param
if (procedureCall.getParameterStrategy() == ParameterStrategy.NAMED) {
session().getFactory().getServiceRegistry().getService(RefCursorSupport.class).registerRefCursorParameter(statement, getName());
} else {
session().getFactory().getServiceRegistry().getService(RefCursorSupport.class).registerRefCursorParameter(statement, startIndex);
}
}
}
Aggregations