当我使用java preparedstatement时,如何在防止SQL注入的同时将代码重用到不同的表中?

当我使用java preparedstatement时,如何在防止SQL注入的同时将代码重用到不同的表中?,java,sql,Java,Sql,例如,我有两张桌子 create table teacher( teacherNum varchar(20) NOT NULL, teacherName varchar(20) NOT NULL, sex varchar(10) NOT NULL, title varchar(15) NOT NULL, password varchar(30) NOT NULL, PRIMARY KEY(teacherNum) ); create table lesson( le

例如,我有两张桌子

create table teacher(
  teacherNum varchar(20) NOT NULL,
  teacherName varchar(20) NOT NULL,
  sex varchar(10) NOT NULL,
  title varchar(15) NOT NULL,
  password varchar(30) NOT NULL,
  PRIMARY KEY(teacherNum)
);


create table lesson(
  lessonNum varchar(20) NOT NULL,
  lessonName    varchar(20) NOT NULL,
  year  int NOT NULL,
  term varchar(4) NOT NULL,
  credit int NOT NULL,
  teacherNum    varchar(10) NOT NULL,
  beforeLessonNum varchar(5),
  PRIMARY KEY(lessonNum),
  foreign key (teacherNum) references teacher(teacherNum)
);
我想写一个insert函数,它的签名如下

public void insert(String table,String ...values)

我知道我可以通过字符串连接来实现,但我也知道这会增加SQL注入的风险。那么我如何编写这个函数呢?

只要不使用用户提供的值,字符串连接就可以了。例如,这很好:

String sql = "INSERT INTO " + (condition ? "teacher" : "lesson") + " ("/*...*/;
…因为您要组合的字符串完全在您的控制之下。只需确保将各种PreparedStatement setXyz方法与输入函数的值一起使用,这些值可能来自用户

也就是说,坦率地说,我在这里没有看到很多代码重用的机会。您有不同的表名、不同的列名、不同的列数。。。另外,您已经将该方法显示为接受字符串…值-您如何知道哪些值适用于哪些列?如果您需要所有列,那么方法签名不应该误导编码人员,因为它建议可以接受不同数量的列。您无法知道应用于每个值的类型。简而言之:这是一个自找麻烦的设计


现在,您可以有一个知道表名及其列的名称和类型的基类,然后在基类上有一个通用的insertMap values方法。然后在映射中有两个循环:第一个循环通过从映射中获取每个列名来构建SQL,检查它是否对抛出异常的表有效,并将其添加到插入的列列表中。然后你加上足够数量的?对于“值”部分。您可以准备该语句,然后使用适当的setXyz方法再次循环以设置每个值。但在这一点上,你正在重新发明轮子。相反,您应该看看已知的、经过编码的、经过测试的、经过验证的ORM解决方案。

我在这里没有看到太多代码重用的机会。你有不同的表名,不同的列名,不同的列数…最好是对不同的表使用不同的函数使用字符串连接而不是参数化的值通常也会对性能不利,因为大多数DBMS必须为查询的每个变体制定新的执行计划。@popovitsj:仅当查询不同时。如果您对一组静态列执行字符串concat,并且只使用公共方法输入表名等,那么您将得到相同的查询。但我认为这次行动真的应该有不同的方向。。。