[hibernate-dev] Stored procedure improvement
Vlad Mihalcea
mihalcea.vlad at gmail.com
Tue Feb 16 01:32:24 EST 2016
+1. I added a JIRA issue for this:
https://hibernate.atlassian.net/browse/HHH-10530
On Mon, Feb 15, 2016 at 10:49 PM, Steve Ebersole <steve at hibernate.org>
wrote:
> I think too that we need to keep the native/JPA split in mind. We are
> much more limited in how we might support this in JPA due to not being able
> to change those contracts. So in JPA that means either hints or an
> extension contract.
>
> Let's model the native API first since there we have the most
> flexibility. Again, it really comes down to whether it makes sense to
> model the distinction between "call return" and "call arguments" (arguments
> might also retrieve values back). Technically the existing
> registerParameter/ParameterRegistration infrastructure could handle
> modeling the idea of a "call return" assuming that:
>
> 1. The parameters are always registered by position, not name
> 2. The first parameter is the "call return"
> 3. We are given some indication (hint, etc) that we need to be dealing
> with the `{?=call(...)}` syntax
>
> Or we could instead model the "call return" as separate from "call
> arguments", whether directly on ProcedureCall or on a separate contract
> FunctionCall. And in fact if we go the route of modeling this "call
> return" separately, we can have a single-point trigger for the type of
> executable call to make:
>
> ProcedureCall call = session.createStoredProcedureCall( ... );
> call.registerCallReturn( Integer.class );
> call.registerParameter( ... );
>
> In fact if we end up going this route, I'd suggest deprecating
> `#registerParameter` in favor of `#registerCallArgument`. Anyway, above
> the call to `#registerCallReturn` tells us completely everything we need
> to make a `{?=call(...)}` call instead of the `{call(...)}` form.
>
> For JPA the only options really are a hint or an extension. With the hint
> approach, we pretty much have to follow the 3-point assumptions I set above
> in terms of the JPA object.
>
>
> On Mon, Feb 15, 2016 at 2:21 PM Steve Ebersole <steve at hibernate.org>
> wrote:
>
>> It is undefined in JDBC spec - not that JDBC covers function call in any
>> kind of depth to begin with ;)
>>
>> However, that does not mean that it won't ever be supported. So its
>> really a question of do we complicate future support for that just because
>> support for it is not defined at the moment?
>>
>> Like I think its clear that referring to function/procedure args by a mix
>> of name and position is bad form : both at the JPA/Hibernate and JDBC
>> levels. But a function return is special. And lumping that in with
>> argument handling and inheriting the same limitations I am not so sure
>> makes sense.
>>
>>
>> On Mon, Feb 15, 2016 at 2:12 PM Vlad Mihalcea <mihalcea.vlad at gmail.com>
>> wrote:
>>
>>> I tried out with MySQL and PostgreSQL and I cannot call a function by
>>> name.
>>> It works with positional parameters.
>>>
>>> So, I'm not even sure it's possible to use named parameters with
>>> functions that return a value.
>>> Have you ever seen such a function call working with named parameters?
>>>
>>> Vlad
>>>
>>> On Mon, Feb 15, 2016 at 7:43 PM, Steve Ebersole <steve at hibernate.org>
>>> wrote:
>>>
>>>> On Mon, Feb 15, 2016 at 10:16 AM Vlad Mihalcea <mihalcea.vlad at gmail.com>
>>>> wrote:
>>>>
>>>>> The problem with naming the method as
>>>>> "ProcedureCall#setTreatAsFunction(boolean isFunction)" is that the term
>>>>> "function" is very leaky.
>>>>>
>>>>
>>>> The distinction being made is whether we need to use the JDBC function
>>>> escape syntax. How one database implements that or misnames a procedure a
>>>> function is not really pertinent IMO. The bottom line is that JDBC defines
>>>> 2 distinct syntaxes here and we need to know which to use, either:
>>>>
>>>> 1. {call it(...)}
>>>> 2. {?=call it(...)}
>>>>
>>>> The only important distinction here is that in one case we need to put
>>>> one of the parameters at the start. And I do not find it "leaky" to call
>>>> that second form "function syntax". IMO the pgsql name is just a
>>>> misnomer. Again the important piece of information is the template, the
>>>> syntax. Even though on pgsql it would be a function in their vocab, it is
>>>> really the first (proc) syntax.
>>>>
>>>>
>>>> To summarize, we can have the discriminator method for knowing we
>>>>> should handle a return-like SQL function:
>>>>>
>>>>> 1. ProcedureCall#returnResultSet(boolean isReturn)
>>>>>
>>>>> Now, considering the options that you proposed, I'd go for the 2nd one:
>>>>>
>>>>> "2. use the existing ProcedureCall param methods and just assume that
>>>>> in the case of a function that the first parameter represents the function
>>>>> return"
>>>>>
>>>>
>>>>
>>>>>
>>>>> This is actually very close to JDBC too, so it would be easier for a
>>>>> developer to recall the syntax because in JDBC the syntax is:
>>>>>
>>>>> try (CallableStatement function = connection.prepareCall(
>>>>> "{ ? = call fn_count_comments(?) }" )) {
>>>>> function.registerOutParameter( 1, Types.INTEGER );
>>>>> function.setInt( 2, 1 );
>>>>> function.execute();
>>>>> int result = function.getInt( 1 );
>>>>> }
>>>>>
>>>>> But then, it means that we register the return type and the fact that
>>>>> we use the first index like with a stored procedure:
>>>>>
>>>>> query.registerStoredProcedureParameter(1, Integer.class,
>>>>> ParameterMode.OUT);
>>>>>
>>>>> This way we have only a new methods being added (e.g. returnResultSet)
>>>>> and we alter the callable statement syntax based on it.
>>>>> When it comes to fetching the result set, we need to do it just like
>>>>> in the JDBC example.
>>>>>
>>>>
>>>> Which effectively means you'd never be able to use named parameters
>>>> with functions since you cannot mix named and positional parameters.
>>>>
>>>>
>>>
More information about the hibernate-dev
mailing list