NumericBooleanType hibernate type cannot bind value in StoredProcedureQuery


#1

Hi all,

I tried to call a procedure with Hibernate ORM 5.3.0.Final, then I got an IllegalArgumentException.
Example code:

inTransaction(
				session -> {
					final StoredProcedureQuery procedureQuery = session.createStoredProcedureQuery( "test" );

					procedureQuery.registerStoredProcedureParameter(1, NumericBooleanType.class, ParameterMode.IN);
					procedureQuery.setParameter( 1, false );
				}
		);

Exception:

**java.lang.IllegalArgumentException: Bind value [false] was not of specified type [class org.hibernate.type.NumericBooleanType**
	at org.hibernate.procedure.internal.ParameterBindImpl.internalSetValue(ParameterBindImpl.java:83)
	at org.hibernate.procedure.internal.ParameterBindImpl.setBindValue(ParameterBindImpl.java:64)
	at org.hibernate.procedure.internal.ProcedureCallImpl.setParameter(ProcedureCallImpl.java:818)
	at org.hibernate.procedure.internal.ProcedureCallImpl.setParameter(ProcedureCallImpl.java:70)

Could you help me for this issue?

Best Regards
Roland


#2

Change this:

procedureQuery.registerStoredProcedureParameter(1, NumericBooleanType.class, ParameterMode.IN);

to this:

procedureQuery.registerStoredProcedureParameter(1, Boolean.class, ParameterMode.IN);

The type parameter is the Java Type of the parameter and has nothing to do with Hibernate Types.


#3

This NumericBooleanType works in the previous Hibernate version 5.2.
What about the YesNoType? The result of it is the same exception.
How can I use my own implementations of UserType?


#4

This is how the type is passed on:

public <T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode) {
	final ProcedureParameterImpl procedureParameter = new ProcedureParameterImpl(
			this,
			position,
			mode,
			type,
			getSession().getFactory().getTypeResolver().heuristicType( type.getName() ),
			globalParameterPassNullsSetting
	);

	registerParameter( procedureParameter );
	return procedureParameter;
}

Notice that you have both the type and the hibernateType. Theoretically, you could use a custom Type as well. Just try it and see where it breaks.

Better build up a test case as it’s going to be easier to implement a fix if it turns out to be an issue in hibernate-core.


#5

In my opinion, the backward compatibility is most important.
Please give me a solution, how can I use the YesNoType in a StoredProcedureQuery.

I have debugged the codes in hibernate-core. The implementation of ParameterRegistration was changed.
The implementations of ParameterRegistration in Hibenate 5.2:
NamedParameterRegistration:

	@Override
	@SuppressWarnings("unchecked")
	public <T> ParameterRegistration<T> registerParameter(String name, Class<T> type, ParameterMode mode) {
		final NamedParameterRegistration parameterRegistration = new NamedParameterRegistration( this, name, mode, type, globalParameterPassNullsSetting );
		registerParameter( parameterRegistration );
		return parameterRegistration;
	}

PositionalParameterRegistration:

	@Override
	@SuppressWarnings("unchecked")
	public <T> ParameterRegistration<T> registerParameter(int position, Class<T> type, ParameterMode mode) {

		final PositionalParameterRegistration parameterRegistration =
				new PositionalParameterRegistration( this, position, mode, type, globalParameterPassNullsSetting );
		registerParameter( parameterRegistration );
		return parameterRegistration;
	}

The implementation was changed at this commit: https://github.com/hibernate/hibernate-orm/commit/6ba328e7a03d2faaf648e85310e903f11211cbd8


#6

Better build up a test case as it’s going to be easier to implement a fix if it turns out to be an issue in hibernate-core.


#7

Please perform these tests with Hibernate 5.2 and 5.3.

package com.example;

import org.hibernate.Session;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.type.NumericBooleanType;
import org.hibernate.type.YesNoType;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import javax.persistence.ParameterMode;

@RequiresDialect(H2Dialect.class)
public class StoredProcedureApiTest extends BaseNonConfigCoreFunctionalTestCase {

    private Session session;

    @Before
    public void setUp() {
        session = openSession();
    }

    @After
    public void tearDown() {
        session.close();
    }


    @Test
    public void testNumericBooleanTypeInParameter() {
        session.createStoredProcedureQuery("test")
                .registerStoredProcedureParameter(1, NumericBooleanType.class, ParameterMode.IN)
                .registerStoredProcedureParameter(2, String.class, ParameterMode.OUT)
                .setParameter(1, false);
    }

    @Test
    public void testYesNoTypeInParameter() {
        session.createStoredProcedureQuery("test")
                .registerStoredProcedureParameter(1, YesNoType.class, ParameterMode.IN)
                .registerStoredProcedureParameter(2, String.class, ParameterMode.OUT)
                .setParameter(1, false);
    }

}


#8

Great. Please send it as a Pull Request as explained in this article.


#9

Thanks the information.

I have created an issue about this problem in the Hibernate Issue System

https://hibernate.atlassian.net/browse/HHH-12661

The test cases are coming soon.


#10

Thanks. I can do the test as I wanted to have one for Oracle which does not support a true boolean type anyway.


#11

I submitted a Pull Request. If it’s approved, we can have it in the next 5.3.x release.


#12

Thank you very much.

I have added a Pull Request with some tests: https://github.com/hibernate/hibernate-orm/pull/2327

I hope It is not problem.


#13

Thanks. I’ll review it tomorrow.