Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EclipseLink assumes that Query.setParameter(Parameter<T> param, T value)'s param object is an EclipseLink type #1990

Open
gregturn opened this issue Nov 6, 2023 · 0 comments

Comments

@gregturn
Copy link

gregturn commented Nov 6, 2023

Spring Data JPA creates a JPA-compliant Parameter instance and supplies it through Query.setParameter(Parameter<T> param, T value). This ends up inside EJBQueryImpl, where it breaks.

    @Override
    public <T> TypedQuery setParameter(Parameter<T> param, T value) {
        if (param == null) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NULL_PARAMETER_PASSED_TO_SET_PARAMETER"));
        }
        //bug 402686: type validation
        String position = getParameterId(param);  // <----- this is where it fails
        ParameterExpressionImpl parameter = (ParameterExpressionImpl) this.getInternalParameters().get(position);
        if (parameter == null ) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("NO_PARAMETER_WITH_NAME", new Object[] { param.toString(), this.databaseQuery }));
        }
        if (!parameter.getParameterType().equals(param.getParameterType())) {
            throw new IllegalArgumentException(ExceptionLocalization.buildMessage("INCORRECT_PARAMETER_TYPE", new Object[] { position, param.getParameterType() }));
        }
        return this.setParameter(position, value);
    }

When it invokes getParameterId against the Parameter<T>, EL is assuming that this is an internal type instead of a JPA type, and attempts a cast operation, which in our situation fails.

   public static String getParameterId(Parameter param){
        Integer id= param.getPosition();
        if (id == null ){
            return String.valueOf(((ParameterExpressionImpl)param).getInternalName()); // <--- perhaps param.getName() instead?
        }
        return String.valueOf(id);
    }

Because we are supplying a name-based parameter, a JPA Parameter.getName() operation, which would have worked, is traded for a downcast and then an invocation for an internal name operation.

Perhaps consider FIRST checking if there is a param.getName() result and deferring to that?

You're clearly using the getPosition() call, so why not stick to the interface operations?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant