如何添加包含queryname,statement的Map
的内容到Handle
的语句缓存,以便在SQL对象中使用,而不使用繁琐的模板组文件,也不影响在对象注释中使用原始SQL的能力,同时还保留@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
似乎只在用@UseStringTemplate3StatementLocator
注释SQL对象接口时起作用;然而,CCD_ 6似乎没有提供一种明显的方法来添加动态生成的查询。
如果您考虑将Byte Buddy用于运行时(字节码)代码生成,以下是我的机器上经过单元测试的代码。这显示了一个before/after示例。我希望它能有所帮助。
原始来源:
@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;
}
}