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

Allow referencing single complex parameter using actual method argument name when compile with -parameters #3012

Open
OverDrone opened this issue Nov 17, 2023 · 1 comment

Comments

@OverDrone
Copy link

OverDrone commented Nov 17, 2023

MyBatis version

3.5.13

Database vendor and version

PostgreSQL 16.1

Test case or example project

https://github.com/OverDrone/mybatis-param

Steps to reproduce

record MainRecord(String value) {}

@Mapper
interface MainMapper {
  @Select("SELECT #{rec.value}")
  String test(MainRecord rec);
}

public void test() {
  mapper.test(new MainRecord("123"));
}

Expected result

123

Actual result

org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'rec' in 'class mybatis.MainRecord'

As you can see in my test project following code works:

  @Select("SELECT #{val}")
  String test1(String val);

  @Select("SELECT #{rec.value}")
  String test3(MainRecord rec, String val);

There was already a bug reported before #1237
but it mentioned only simple objects, test1 in my example.
Same problem with vanilla classes as well, test4, test5 in my example:

public class MainClass {
  private final String value;

  public MainClass(final String value) {
    super();
    this.value = value;
  }

  public String getValue() {
    return value;
  }
}

  @Select("SELECT #{cl.value}")
  String test4(MainClass cl);

  @Select("SELECT #{cl.value}")
  String test5(MainClass cl, String val);

if it is so important to keep this feature by default (when you specify object fields directly without prefixing with parameter name if this parameter is the only one) then at least give an option to disable it.
useActualParamName enabled by default and doesn't help.
Why is it important? It's very refactor unfriendly. Say I have a query couple of screens with lots of mentions of ${request.field...}, then I decide that I don't need all other method parameters, keep only one parameter, then all of a sudden I need to go through sql and replace ${request.field...} to {field...}. Another day I decide to bring back some parameter and then whole story again replacing back {field...} to ${request.field...}, but in this case I can't even find all parameter names automatically because they don't have a common prefix.
Workaround is to specify @Param("request") MainRecord rec, but this makes code messy, because you need to add comment why in this particular case you use Param annotation.

@harawata
Copy link
Member

Hello @OverDrone ,

Changing the default behavior is not an option because of backward compatibility.
Adding a new configuration option might be possible technically, but I don't think it's worth it.
Parameter referencing rule is already complex enough and adding a new option could make the situation worse.

As you found out, if you prioritize consistency over verbosity, you can add @Param.
There will be no confusion if you always add @Param to all parameters.

I'll keep this issue open in case other committers have a different opinion.

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

2 participants