1

如何在不使用繁琐的模板组文件或损害在对象注解中使用原始 SQL 的能力的情况下将Map包含查询名称、语句的内容添加 到SQL 对象的语句缓存中,同时保留功能?Handle@Define

Map<String,String> querySource = new HashMap<>();
querySource.put("sql/BasicDao/simpleSelect","Select * FROM <schemaName>.table_of_vast_importance")

handle.somehowAddToStatementCache(querySource)

...

public interface BasicDao {

    @SqlQuery("sql/BasicDao/simpleSelect")
    BasicBean selectFromTable(@Define("schemaName") String);

    @SqlQuery("SELECT ... FROM ...")
    BasicBean moreComplicatedSelect(@Define("schemaName) String)

    ...


}

我希望以编程方式为 SQL 对象的应用程序加载生成基本的 CRUD 操作,以消除为数据库中每个表的每个单个操作编写样板 SQL 的需要。问题是,这@Define似乎只在使用 ; 注释 SQL 对象接口时起作用@UseStringTemplate3StatementLocator。但是StringTemplate3StatementLocator似乎没有提供一种明显的方法来添加动态生成的查询。

4

1 回答 1

0

如果您考虑使用Byte Buddy生成运行时(字节码)代码,以下是我机器上的单元测试代码。这显示了一个之前/之后的示例。我希望它有所帮助。

原始来源:

@RegisterMapper(TimezoneJDBIMapper.class)
public abstract class TimezoneJDBI {

    @SqlUpdate("INSERT INTO timezone (timez_name, version) VALUES (:timezName, :version)")
    @GetGeneratedKeys
    public abstract long insert(@BindBean Timezone timezone);

}

没有注释的新源:

public abstract class TimezoneJDBI {
    @GetGeneratedKeys
    public abstract long insert(Timezone timezone);
}

使用onDemand现在是完全动态的:

Class<? extends TimezoneJDBI> clazz = new ByteBuddy()
        .withModifiers(TypeManifestation.ABSTRACT)
        .subclass(TimezoneJDBI.class)
        .method(ElementMatchers.named("insert"))
        .withoutCode()
        .annotateMethod(new SqlUpdateImpl("INSERT INTO timezone (timez_name, version) VALUES (:timezName, :version)"))
        .annotateParameter(0, new BindBeanImpl())
        .annotateType(new RegisterMapperImpl(new Class[]{TimezoneJDBIMapper.class}))
        .make().load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER).getLoaded();

TimezoneJDBI dao = jdbi.onDemand(clazz);

对于注释,需要一些帮助器类(每个使用的注释一个,如 Byte Buddy 文档中所述):

class SqlUpdateImpl implements SqlUpdate {

    private String value;

    public SqlUpdateImpl(String value) {
        this.value = value;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return SqlUpdate.class;
    }

    @Override
    public String value() {
        return value;
    }
}

class RegisterMapperImpl implements RegisterMapper {

    private Class<? extends ResultSetMapper<?>>[] value;

    public RegisterMapperImpl(Class<? extends ResultSetMapper<?>>[] value) {
        this.value = value;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return RegisterMapper.class;
    }

    @Override
    public Class<? extends ResultSetMapper<?>>[] value() {
        return value;
    }
}

class BindBeanImpl implements BindBean {

    @Override
    public Class<? extends Annotation> annotationType() {
        return BindBean.class;
    }

    @Override
    public String value() {
        return BindBeanImpl.BARE_BINDING;
    }
}
于 2015-12-02T21:14:40.393 回答