如何在java中的全局DbConnection中使用准备好的sql语句?

如何在java中的全局DbConnection中使用准备好的sql语句?,java,jdbc,prepared-statement,Java,Jdbc,Prepared Statement,在学校,我有一个Java项目,其中有几个Maven库 对于我们的数据库连接,我制作了一个“全局”连接文件,在这个文件中我有一些基本的选择、更新和删除方法,您可以使用例如:select(query)从其他文件调用这些方法 我从这个问题中得到了这个代码: 现在问题来了,;我们需要一个准备好的语句,如何在保持select方法全局可用的同时实现它 以下是DbConnection类: publicArrayList选择(字符串查询){ 试一试{ Statement Statement=this.conne

在学校,我有一个Java项目,其中有几个Maven库

对于我们的数据库连接,我制作了一个“全局”连接文件,在这个文件中我有一些基本的选择、更新和删除方法,您可以使用例如:
select(query)从其他文件调用这些方法
我从这个问题中得到了这个代码:

现在问题来了,;我们需要一个准备好的语句,如何在保持select方法全局可用的同时实现它

以下是DbConnection类:

publicArrayList选择(字符串查询){
试一试{
Statement Statement=this.connection.createStatement();
ResultSet rs=语句.executeQuery(查询);
ResultSetMetaData元数据=rs.getMetaData();
ArrayList结果=新建ArrayList();
while(rs.next()){
ArrayList行=新的ArrayList();

对于(inti=1;i,正如一些评论中所建议的,您的方法违反了Java安全准则,原因有很多,其中最重要的是:

  • 它不执行并检查输入
  • 这是SQL注入攻击的一扇大门,因为它无法控制对数据库执行哪种类型的查询
但是,如果这只是一项学校工作,我可以使用
PreparedStatemnt

这样做的目的是假设调用者知道输入查询中包含的参数数量,并给出其值的确切数量。
基于此,我能想到的最简单的实现是以下实现:

public ArrayList<Map<String, Object>> performGenericParameterizedQuery(String queryWithParameters, 
    Object ... values) {
    
    ArrayList<Map<String, Object>> result = new ArrayList<>();
    
    try(PreparedStatement ps = this.connection.preparedStatement(queryWithParameters)) {
        
        for(int i=0; i<values.length; i++) {
            ps.setObject(i+1, values[i]);
        }
        
        ResultSet rs = ps.executeQuery();
        
        ResultSetMetaData metaData = rs.getMetaData();

        while (rs.next()){

            Map<String, Object> row = new HashMap<>();

            for (int i = 1; i <= metaData.getColumnCount(); i++){
                String strColumnName = metaData.getColumnName(i);
                Object columnValue = rs.getObject(i);
                row.put(columnValue, strColumnName);
            }
            result.add(row);
        }
    
    }catch (SQLException e){
        e.printStackTrace();
    }

    return result;
}
public ArrayList performGenericParameterizedQuery(字符串查询带参数,
对象…值){
ArrayList结果=新建ArrayList();
try(PreparedStatement ps=this.connection.PreparedStatement(queryWithParameters)){

对于(inti=0;iWell),可以使用
connection.prepareStatement(查询)
但是,除非您想设置参数,否则您不会获得太多。另外,您应该注意,从外部传递查询是一种安全风险。在这样的学校项目中,为了简单起见,这样做是可以的,等等。但决不要在生产中这样做。@Thomas您将如何编程?其他组在每次查询时都会反复重复相同的代码你需要给数据库打个电话。我想这样编程,你不必每次给数据库打电话都重复。如果学校允许的话,我会使用hibernate或其他ORM atm:)@seanpaulharsevoort我同意@Thomas。对于安全最佳实践,应该始终验证输入,但除此之外,您实现的方法为SQL注入敞开了大门。您不应该有这样的“通用性”查询方法,但实现只执行所需查询的方法。然后,使用
PreparedStatement
而不是经典的
Statement
,方法输入参数应该是作为where条件传递的值。@Marctizzano你能再解释一下吗?bc我只是记住了KISS,我ant实现最安全的解决方案:)我忘了提到这段代码是在数据访问层,查询是从其他类生成的,并作为变量传递到DbConnection类中。谢谢!我仍然想知道在使用JDBC和三层体系结构时,最佳实践是什么。我的代码是完全的狗屎吗?还是我的意图错了?再次感谢你的代码,我会后悔的关于安全指南,现在不用担心,这是你在学习OCP Java 11时学到的东西。实际上,这并不常见,但我也是这样做的。如果你足够好奇,你可以看看:关于三层体系结构,这都是关于实现“Repository”层只处理DB,服务层利用Repository层,上层(可以是控制器类或业务逻辑类)保存并使用服务实例。您可以在网上找到大量文档,例如,先看一下: