Skip to content

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

@OverDrone

Description

@OverDrone

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions