好的,下面是一个示例的完整代码:
@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