Java JDBC中的命名参数

Java JDBC中的命名参数,java,jdbc,named-parameters,Java,Jdbc,Named Parameters,JDBC中是否有命名参数而不是位置参数,如下面ADO.NET查询中的@name,@city select * from customers where name=@name and city = @city JDBC不支持命名参数。除非您一定要使用普通的JDBC(这会带来麻烦,让我告诉您),否则我建议您使用Springs优秀的JDBCTemplate,它可以在不使用整个IoC容器的情况下使用 支持命名参数,您可以这样使用它们: NamedParameterJdbcTemplate jdbcT

JDBC中是否有命名参数而不是位置参数,如下面ADO.NET查询中的
@name
@city

select * from customers where name=@name and city = @city

JDBC不支持命名参数。除非您一定要使用普通的JDBC(这会带来麻烦,让我告诉您),否则我建议您使用Springs优秀的JDBCTemplate,它可以在不使用整个IoC容器的情况下使用

支持命名参数,您可以这样使用它们:

 NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);

 MapSqlParameterSource paramSource = new MapSqlParameterSource();
 paramSource.addValue("name", name);
 paramSource.addValue("city", city);
 jdbcTemplate.queryForRowSet("SELECT * FROM customers WHERE name = :name AND city = :city", paramSource);

您不能在JDBC本身中使用命名参数。您可以尝试使用Spring框架,因为它有一些扩展,允许在查询中使用命名参数。

普通JDBC只支持
CallableStatement
中的命名参数(例如
setString(“name”,name)
),即使如此,我怀疑底层存储过程实现也必须支持它

有关如何使用命名参数的示例:

//uss Sybase ASE sysobjects table...adjust for your RDBMS
stmt = conn.prepareCall("create procedure p1 (@id int = null, @name varchar(255) = null) as begin "
        + "if @id is not null "
        + "select * from sysobjects where id = @id "
        + "else if @name is not null "
        + "select * from sysobjects where name = @name "
        + " end");
stmt.execute();

//call the proc using one of the 2 optional params
stmt = conn.prepareCall("{call p1 ?}");
stmt.setInt("@id", 10);
ResultSet rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}


//use the other optional param
stmt = conn.prepareCall("{call p1 ?}");
stmt.setString("@name", "sysprocedures");
rs = stmt.executeQuery();
while (rs.next())
{
    System.out.println(rs.getString(1));
}
public class NamedParamStatement {
    public NamedParamStatement(Connection conn, String sql) throws SQLException {
        int pos;
        while((pos = sql.indexOf(":")) != -1) {
            int end = sql.substring(pos).indexOf(" ");
            if (end == -1)
                end = sql.length();
            else
                end += pos;
            fields.add(sql.substring(pos+1,end));
            sql = sql.substring(0, pos) + "?" + sql.substring(end);
        }       
        prepStmt = conn.prepareStatement(sql);
    }

    public PreparedStatement getPreparedStatement() {
        return prepStmt;
    }
    public ResultSet executeQuery() throws SQLException {
        return prepStmt.executeQuery();
    }
    public void close() throws SQLException {
        prepStmt.close();
    }

    public void setInt(String name, int value) throws SQLException {        
        prepStmt.setInt(getIndex(name), value);
    }

    private int getIndex(String name) {
        return fields.indexOf(name)+1;
    }
    private PreparedStatement prepStmt;
    private List<String> fields = new ArrayList<String>();
}

普通JDBC不支持命名参数

如果您使用的是DB2,那么直接使用DB2类:


  • 为了避免包含大型框架,我认为一个简单的自制类可以做到这一点

    处理命名参数的类示例:

    //uss Sybase ASE sysobjects table...adjust for your RDBMS
    stmt = conn.prepareCall("create procedure p1 (@id int = null, @name varchar(255) = null) as begin "
            + "if @id is not null "
            + "select * from sysobjects where id = @id "
            + "else if @name is not null "
            + "select * from sysobjects where name = @name "
            + " end");
    stmt.execute();
    
    //call the proc using one of the 2 optional params
    stmt = conn.prepareCall("{call p1 ?}");
    stmt.setInt("@id", 10);
    ResultSet rs = stmt.executeQuery();
    while (rs.next())
    {
        System.out.println(rs.getString(1));
    }
    
    
    //use the other optional param
    stmt = conn.prepareCall("{call p1 ?}");
    stmt.setString("@name", "sysprocedures");
    rs = stmt.executeQuery();
    while (rs.next())
    {
        System.out.println(rs.getString(1));
    }
    
    public class NamedParamStatement {
        public NamedParamStatement(Connection conn, String sql) throws SQLException {
            int pos;
            while((pos = sql.indexOf(":")) != -1) {
                int end = sql.substring(pos).indexOf(" ");
                if (end == -1)
                    end = sql.length();
                else
                    end += pos;
                fields.add(sql.substring(pos+1,end));
                sql = sql.substring(0, pos) + "?" + sql.substring(end);
            }       
            prepStmt = conn.prepareStatement(sql);
        }
    
        public PreparedStatement getPreparedStatement() {
            return prepStmt;
        }
        public ResultSet executeQuery() throws SQLException {
            return prepStmt.executeQuery();
        }
        public void close() throws SQLException {
            prepStmt.close();
        }
    
        public void setInt(String name, int value) throws SQLException {        
            prepStmt.setInt(getIndex(name), value);
        }
    
        private int getIndex(String name) {
            return fields.indexOf(name)+1;
        }
        private PreparedStatement prepStmt;
        private List<String> fields = new ArrayList<String>();
    }
    
    公共类namedParameter语句{
    public NamedParamStatement(连接连接,字符串sql)引发SQLException{
    int pos;
    而((pos=sql.indexOf(“:”)!=-1){
    int end=sql.substring(pos.indexOf(“”);
    如果(结束==-1)
    end=sql.length();
    其他的
    结束+=位置;
    添加(sql.substring(pos+1,end));
    sql=sql.substring(0,pos)+“?”+sql.substring(end);
    }       
    prepsmt=conn.prepareStatement(sql);
    }
    public PreparedStatement getPreparedStatement(){
    返回预测试;
    }
    public ResultSet executeQuery()引发SQLException{
    返回prepsmt.executeQuery();
    }
    public void close()引发SQLException{
    prepsmt.close();
    }
    public void setInt(字符串名称,int值)引发SQLException{
    setInt(getIndex(name),value);
    }
    私有int getIndex(字符串名称){
    返回字段。indexOf(name)+1;
    }
    私人编制的财务报表;
    私有列表字段=新的ArrayList();
    }
    
    调用类的示例:

    String sql;
    sql = "SELECT id, Name, Age, TS FROM TestTable WHERE Age < :age OR id = :id";
    NamedParamStatement stmt = new NamedParamStatement(conn, sql);
    stmt.setInt("age", 35);
    stmt.setInt("id", 2);
    ResultSet rs = stmt.executeQuery();
    
    stringsql;
    sql=“从测试表中选择id、Name、Age、TS,其中Age<:Age或id=:id”;
    NamedParamStatement stmt=新的NamedParamStatement(conn,sql);
    stmt.setInt(“年龄”,35岁);
    stmt.setInt(“id”,2);
    ResultSet rs=stmt.executeQuery();
    

    请注意,上面的简单示例不会处理两次使用命名参数。它也不能使用:sign-inside引号。

    谢谢-但我不能使用Spring,因为我不能对现有的代码库做太多更改:(@Malax的要点是,您可以使用spring standalone中的NamedParameterJdbcTemplate。您不必更改代码库的任何其他部分。但是您必须在项目中包含许多spring jar,只需使用一些与NamedParameterJdbcTemplate相关的类。这是org.springframework.jdbc.jar无法做到的独立使用。解压缩jar文件-并将您想要的类文件复制到您的项目中。瞧。
    SpringJDBC
    模块依赖于
    SpringCore
    SpringFramework
    SpringTX
    NamedParameterJdbcTemplate
    需要一些重写才能使用独立。
    NamedParameterStatement
    不是Java API中的一个类。True。下面是指向它的链接:是的,它是正确的,但并非所有db都支持此功能。我在postgresql上进行了测试,它不起作用。是的,显然数据库必须先支持命名参数……而postgres似乎不支持。问题表明他们的db确实支持此功能,并且希望了解o使用JDBC中的功能。我对您的功能进行了一些小的修改。`Pattern findParametersPattern=Pattern.compile('(?我想我会做一些类似的事情。我想最好是覆盖@WillieT代码的thioughgist的索引器,gist可以很好地改进。indexof用于获取索引?我还建议添加
    实现自动关闭
    (req java7+)本文提供了此类的快速实现:
    我认为Oracle JDBC驱动程序支持在使用CallableStatement
    时使用命名参数调用常规SQL语句。