Java JDBC中的命名参数
JDBC中是否有命名参数而不是位置参数,如下面ADO.NET查询中的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
@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语句。