0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

动态生成带@ 和返回值的mapper方法

Posted at

好的,下面是一个示例的完整代码:

@Repository
public class DynamicMapperCreator {

  private final SqlSessionFactory sqlSessionFactory;

  @Autowired
  public DynamicMapperCreator(SqlSessionFactory sqlSessionFactory) {
    this.sqlSessionFactory = sqlSessionFactory;
  }

  public <T> void createSelectMethod(Class<T> type, String columnName) throws Exception {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
      Configuration configuration = sqlSession.getConfiguration();
      // 创建动态 MapperBuilderAssistant
      MapperBuilderAssistant assistant = new MapperBuilderAssistant(configuration, "");
      // 构建 @Select 注解
      SelectProviderAnnotationBuilder annotationBuilder =
          new SelectProviderAnnotationBuilder(assistant, type);
      // 生成 Mapper 方法名
      String methodName = "selectBy" + StringUtils.capitalize(columnName);
      // 创建 Mapper 方法
      Method method = type.getDeclaredMethod(methodName, String.class);
      // 生成 Mapper 接口
      Class<?> mapperInterface = createMapperInterface(type, methodName, method.getReturnType());
      // 注册 Mapper 接口
      configuration.addMapper(mapperInterface);
      // 输出 Mapper 接口代码
      System.out.println("Dynamic Mapper Interface: ");
      System.out.println(ReflectUtils.getFullClassName(mapperInterface));
      System.out.println(ReflectUtils.getCode(mapperInterface));
    } finally {
      sqlSession.close();
    }
  }

  /**
   * 动态创建 Mapper 接口
   *
   * @param type 实体类类型
   * @param methodName 方法名
   * @param returnType 返回值类型
   * @return Mapper 接口类型
   */
  private <T> Class<?> createMapperInterface(Class<T> type, String methodName,
      Class<?> returnType) {
    MapperBuilder mapperBuilder = new MapperBuilder(type);
    return mapperBuilder.addStatement(
            "org.apache.ibatis.annotations.SelectProvider(type = "
                + SelectProviderAnnotationBuilder.class.getName()
                + ".class, method = \"buildSql\")")
        .addMethod(
            new MethodBuilder(returnType, methodName)
                .addParameter(String.class, "value")
                .toMethod())
        .toMapper();
  }
}

class MapperBuilder {

  private final Class<?> type;
  private final List<String> methods = new ArrayList<>();

  public MapperBuilder(Class<?> type) {
    this.type = type;
  }

  public MapperBuilder addStatement(String statement) {
    methods.add(statement);
    return this;
  }

  public MapperBuilder addMethod(Method method) {
    methods.add(method.toString());
    return this;
  }

  public Class<?> toMapper() {
    StringBuilder sb = new StringBuilder();
    sb.append("package ").append(type.getPackage().getName()).append(";\n\n");
    sb.append("public interface ").append(type.getSimpleName()).append("Mapper {\n\n");
    for (String method : methods) {
      sb.append("  ").append(method).append(";\n\n");
    }
    sb.append("}\n");
    return ReflectUtils.compile(type.getSimpleName() + "Mapper", sb.toString());
  }
}

class MethodBuilder {

  private final Class<?> returnType;
  private final String methodName;
  private final List<String> parameters = new ArrayList<>();

  public MethodBuilder(Class<?> returnType, String methodName) {
    this.returnType = returnType;
    this.methodName = methodName;
  }

  public MethodBuilder addParameter(Class<?> type, String name) {
    parameters.add(type.getSimpleName() + " " + name);
    return this;
  }

  public Method toMethod() {
    StringBuilder sb = new StringBuilder();
    sb.append("@SuppressWarnings(\"all\")\n");
    sb.append("public ").append(ReflectUtils.getTypeName(returnType
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?