无SQL内容的Java create PreparedStatement
是否可以在java中创建无SQL内容的Java create PreparedStatement,java,jdbc,prepared-statement,Java,Jdbc,Prepared Statement,是否可以在java中创建PreparedStatement,而不设置初始SQL查询 示例代码: @Override public List<AccountBean> search(AccountConstraint... c) { if (c.length == 0) { throw new IllegalArgumentException("dao.AccountDAO.search: c.length == 0"); } try {
PreparedStatement
,而不设置初始SQL查询
示例代码:
@Override
public List<AccountBean> search(AccountConstraint... c) {
if (c.length == 0) {
throw new IllegalArgumentException("dao.AccountDAO.search: c.length == 0");
}
try {
List<AccountBean> beans = new ArrayList<>();
for (AccountConstraint ac : c) {
PreparedStatement ps = connection.prepareStatement(null);
QueryBuilder queryBuilder = new QueryBuilder(ps, "SELECT * FROM accounts");
queryBuilder.add(ac.getAccountIdConstraint());
queryBuilder.add(ac.getUsernameConstraint());
queryBuilder.add(ac.getPasswordConstraint());
queryBuilder.add(ac.getEmailConstraint());
//INSERT QUERY INTO PS
ResultSet rs = ps.executeQuery();
while (rs.next()) {
beans.add(new AccountBean(rs));
}
}
return beans;
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
另外,我在一个
try{}
中得到了两条语句,因为使用了资源进行了尝试。在包装好准备好的语句后,您不能通过API修改它。没有SQL语句也无法创建它
为什么不单独创建查询,然后绑定参数?您可以使用映射来保存参数占位符及其值,以便将它们设置为准备好的语句
尽管我只是使用Spring的JDBC模板来更快地完成同样的事情。准备一个语句意味着编译它,以便可以使用不同的参数高效地执行多次。因此,不,在定义查询之前编译查询是没有意义的 据我所知,您希望使用Java编译器来帮助您动态定义查询。为什么不在
compile()
方法中创建准备好的语句,作为构建器的结果呢。此外,如果使用生成器模式,使对add()
的每次调用都返回this
,则代码的可读性会更高,更类似于声明性查询。然后您可以这样编写查询:
PreparedStatement ps = new QueryBuilder()
.select("*")
.from("accounts")
.where()
.add(yourConstraint())
...
.compile();
但是,必须在循环之前创建准备好的语句。否则,如果在循环中保留对构建器的引用并调用compile()
,则每次调用都会得到一条新的准备语句。因此,重用预编译查询不会带来好处。在循环中,您只为准备好的语句中的变量赋值。如何改进SQL查询生成器
如果你看看如何做,你的想法是你更彻底地分离你的关注点。你应该:
- SQL语句的表达式树表示(理想情况下不直接对字符串进行操作)
- 方便地构造该表达式树的方法,例如通过使用DSL
- 某种执行生命周期管理,生成SQL字符串、准备语句、绑定变量等
结果=
//这将通过jOOQ DSL构建表达式树
ctx.selectFrom(帐户)
.where(ac.getAccountIdConstraint())
.和(ac.getUsernameConstraint())
.和(ac.getPasswordConstraint())
.和(ac.getEmailConstraint())
//这将在内部创建PreparedStatement,绑定变量,执行它,并映射结果
.fetch();
当然,您的AccountConstraint.getXYZConstraint()
方法不会返回SQL字符串片段,而是返回表达式树元素。在jOOQ的情况下,这将是一个
(免责声明:我为jOOQ的供应商工作)
如何提高SQL性能
我注意到,您对N
AccountConstraint
值运行N个查询,并以一种方式混合结果,使哪个AccountConstraint
值产生哪个AccountBean
无关紧要。我强烈建议您将该循环移动到生成的SQL查询中,因为您将在几乎所有数据库上获得更快的结果 使用“assist”我的意思是,如果您有拼写错误,而不是只会在运行时导致异常的纯SQL,您将得到编译器错误。但是,在您构建如此广泛的API之前,请快速搜索一下它是否已经存在:-)
PreparedStatement ps = new QueryBuilder()
.select("*")
.from("accounts")
.where()
.add(yourConstraint())
...
.compile();
Result<?> result =
// This constructs the expression tree through the jOOQ DSL
ctx.selectFrom(ACCOUNTS)
.where(ac.getAccountIdConstraint())
.and(ac.getUsernameConstraint())
.and(ac.getPasswordConstraint())
.and(ac.getEmailConstraint())
// This internally creates a PreparedStatement, binds variables, executes it, and maps results
.fetch();