我想在JDBI 3 (SQL对象)中执行SQL语句之前拦截和修改它们。其原因是用模式名替换自定义令牌占位符。我发现这个线程,但它是为JDBI 2(使用Dropwizard
public class Product {
private int id = -1;
private String name = "";
public Product() {
}
public Product(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class ProductMapper implements RowMapper<Product> {
@Override
public Product map(ResultSet r, StatementContext ctx) throws SQLException {
Product product = new Product();
product.setId(r.getInt("id"));
product.setName(r.getString("name"));
return product;
}
}
@SchemaRewriterFactory
@UseClasspathSqlLocator
public interface ProductDao {
/**
* The sql query is located in resources ([package]/listProducts.sql)
* listProducts.sql: SELECT PRODUCT_ID ID, NAME FROM :schema.PRODUCTS
* @return
*/
@SqlQuery
@RegisterRowMapper(ProductMapper.class)
List<Product> listProducts();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SqlStatementCustomizingAnnotation(SchemaRewriterFactory.SchemaRewriter.class)
public @interface SchemaRewriterFactory {
public class SchemaRewriter implements SqlStatementCustomizerFactory {
@Override
public SqlStatementCustomizer createForMethod(Annotation annotation, Class<?> sqlObjectType, Method method) {
return null;
}
@Override
public SqlStatementParameterCustomizer createForParameter(Annotation annotation, Class<?> sqlObjectType, Method method, Parameter param, int index, Type paramType) {
return null;
}
@Override
public SqlStatementCustomizer createForType(Annotation annotation, Class<?> sqlObjectType) {
return q -> q.addCustomizer(new StatementCustomizer() {
@Override
public void beforeBinding(PreparedStatement stmt, StatementContext ctx) throws SQLException {}
@Override
public void beforeExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException {
System.out.println(stmt.toString());
//TODO: HOW DO I MODIFY SQL (REPLACE TOKENS - :schema) BEFORE IT GETS EXECUTED?
}
@Override
public void afterExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException { }
});
}
}
}
我还发现了这个线程,它使用@定义(JDBI中的动态顺序SQL对象查询)处理自定义标签替换。如果可能,我想避免每次调用都传递额外的参数。任何帮助都将不胜感激!
我找到了一种方法来截取查询并在执行之前对其进行修改。
您必须使用自定义 StatementBuilder 构建一个 StatementBuilderFactory
实例。方法如下:
private fun getCustomStatementBuilderFactory(): StatementBuilderFactory =
StatementBuilderFactory {
object : DefaultStatementBuilder() {
override fun create(conn: Connection?,
sql: String?,
ctx: StatementContext?): PreparedStatement {
//Perform the modification here
val modifiedSql = "--Sample\n$sql"
return if (ctx!!.isReturningGeneratedKeys) {
val columnNames = ctx.generatedKeysColumnNames
if (columnNames != null && columnNames.size > 0) conn!!.prepareStatement(
modifiedSql,
columnNames) else conn!!.prepareStatement(sql, 1)
} else {
if (ctx.isConcurrentUpdatable) conn!!.prepareStatement(modifiedSql,
1003,
1008) else conn!!.prepareStatement(modifiedSql, 1003, 1007)
}
}
}
}
现在,将此 StatementBuilderFactory
实例设置为用于执行查询的 jdbi 实例。
Jdbi.create(dataSource).setStatementBuilderFactory(getCustomStatementBuilderFactory())
根据上面的例子,每个执行的查询在开始都有一个注释< code> - Sample。
您可以为此使用String模板。
/**
* The sql query is located in resources ([package]/listProducts.sql)
* listProducts.sql: SELECT PRODUCT_ID ID, NAME FROM <schemaName>.PRODUCTS
* @return
*/
@SqlQuery
@RegisterRowMapper(ProductMapper.class)
List<Product> listProducts(@Define("schemaName") String schemaName);
只需小心清理架构名称
参数(可能的SQL注入)
问题内容: 我正在尝试使用HQL(hibernate查询语言)在两个表之间创建一个并集。此SQL脚本可在我的SQL服务器上正常运行: 问题是,当我尝试像这样在grails中运行它时: 我收到此错误: 如何在grails中运行上述SQL语句? 谢谢杰森 问题答案: HQL不支持联合。自2005年以来,Hibernate的JIRA中存在一个问题。
问题内容: 大家好,我想执行我的SQL语句,但是我在synatx上遇到麻烦,有人可以帮助我了解我做错了什么吗? 谢谢,阿什。 问题答案: 您需要解决的最重要的事情是使用查询参数,而不是动态地构建字符串。这将提高性能,维护和安全性。 此外,您想使用较新的强类型ADO.Net对象。确保为添加使用指令。 注意此代码中的语句。完成连接后,他们将 确保 您的连接已关闭。这很重要,因为数据库连接是有限且不受管
问题内容: 是否可以使用T-SQL执行存储在表中的SQL语句? 表中存储的语句是临时语句,可以是 SELECT TOP 100 * FROM ATable 到更复杂的语句: 我想执行从T-SQL声明的 @Query 变量。这可能吗?(我正在运行MSSQL 2005环境) 问题答案: 您可以使用 运行您的T-SQL 这是SQL Server 2005的MS docn的链接 http://msdn.m
问题内容: 我想在 Java中 执行查询。 我创建一个连接。然后,我想执行一条语句,完成后关闭连接,但是我想通过连接执行一些插入语句,并在循环完成后关闭连接。 我能做些什么 ? 我的示例代码是: 当执行select语句()时,循环必须为两次,但是当()执行并完成时,则关闭连接并从类中返回。 问题答案: 以下示例使用&命令同时执行多个SQL命令。 结果: 以上代码示例将产生以下结果。结果可能会有所不
下面给出一个例子来演示一下如何使用JDBC来执行各种SQL语句,其中包括DDL语句(建立数据库和数据表)、INSERT语句和SELECT语句。 1.程序分析说明 本程序首先创建一个mydb数据库(如果存在就不创建),然后创建一个用于保存图书信息的表t_books(如果存在,删除后再创建),最后向表中插入两条记录,并查询和显示其中的第2条记录。 2.代码编写 本程序使用了Statement接口的ex
问题内容: 我正在尝试结合以下注释: 像下面的代码: @Before方法中的代码在@Sql批注中的脚本“ dml-parametro.sql”之后运行。 这样做对吗? 对于此解决方案,我使用@After而不是@Before,但我想在测试执行之前而不是之后cdelete表。 我不想使用@SqlConfig。我没有在测试级别上使用Transacional范围,因此我需要在每种测试方法中清除表。如果每个