我目前正在处理一个项目,该项目要求我构建一个类,用于将文件中的数据详细信息上传到数据库中准备好的表中。到目前为止,我做得很好,但我的挑战是将要插入的数据格式化为java中sqlite语句的可接受格式。这是我的密码。。。
import java.io.*;
import java.sql.*;
import javax.swing.JOptionPane;
public class Data_Update {
Connection conn = JavaConnect.Connecrdb();
PreparedStatement pst = null;
File c;
Data_Update(File d) {
this.c = d;
}
boolean testFile() {
System.out.println(c.getName().substring(c.getName().length() - 4, c.getName().length()));
boolean t = c.getName().substring(c.getName().length() - 4, c.getName().length()).equals(".sql");
return t;
}
boolean createTable() throws FileNotFoundException, IOException, SQLException {
String r = "", p, q = "";
try {
FileInputStream h = new FileInputStream(c);
DataInputStream k = new DataInputStream(h);
BufferedReader j = new BufferedReader(new InputStreamReader(k));
while ((p = j.readLine()) != null) {
String s = "";
if ((p.startsWith("("))) {
while (!s.contains(")")) {
s = s + p;
}
if (s.contains(", '")) {
System.out.println("Yes");
} else {
System.out.println("No");
}
s.replaceAll("'str'", "'"+str+"'");
s.replace(", '", ", '"+");
s.replace("',", "+"',");
s.replace("('", "('"+");
s.replace("')", "+"')");
s.replace("),", ")");
System.out.println(s);
pst = conn.prepareStatement("insert into courseinformation (currentsession, regno, fullname, level, previouscourses, gpa,
outstandingcourses, proposedcourses, totalcourseno, totalunit, registered, pre_userid, dept, sch, registrationpin, refdatetime)
values " + s);
pst.execute();
}
}
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e);
return false;
}
return true;
}
}
结果是,所有替换后的最终字符串都不能满足插入记录的sql语句的标准
String.replace
和String.replaceAll
不会更改您的String
对象,它们在替换后返回新的String,因此您应该编写s = s.replace...
代码中还有很多其他问题,例如
while (!s.contains(")")) {
s = s + p;
}
如果p
不包含)
,则为无限循环
此外,手动转义字符串是在java中使用sqlapi的错误方式,您应该使用占位符和绑定参数到语句中。
对于给定的代码,很难创建一段立即运行的代码,但您可以以此为基础开始。
您似乎阅读了带有引号、逗号和方括号的SQL,并试图制作一些包含字符串的带有加号和双引号的准java。这被认为太过分了:简单的SQL可以工作。
尽管在这里我不构建SQL文本片段,而是将输入行拆分为要设置的单个值。这可以扩展到字段验证,以及字符串到特定类型的转换。
第一步是在单个事务中执行所有操作。这是一个巨大的加速。这意味着最后有一个提交,因此每个语句的自动提交都必须设置为false。在异常情况下,回滚。
预先定义PreparedStatement。
使用try with resources(try (X x = ...) { }
)会自动关闭资源(x
)。
在这里,我对数据做了一些假设。就像逗号没有作为文本值的一部分出现在输入中一样。
没有给出编码的InputStreamReader将采用本地平台编码,这是不可移植的:另一台电脑上的同一文件可能会使用错误的编码读取。
既没有字段验证也没有转换,始终使用setString
。
public void createTable(Connection conn, File c) throws IOException, SQLException {
final int fieldCount = 16;
conn.setAutoCommit(false);
try (PreparedStatement pst = conn.prepareStatement(
"insert into courseinformation (currentsession, regno, fullname, level, "
+ "previouscourses, gpa, outstandingcourses, proposedcourses, "
+ "totalcourseno, totalunit, registered, pre_userid, dept, sch, "
+ "registrationpin, refdatetime) "
+ "values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)")) { // 16 columns
try (BufferedReader in = new BufferedReader(
new InputStreamReader(new FileInputStream(c), "UTF-8"))) {
String line;
while ((line = in.readLine()) != null) {
// Assume that line is " ('...', ..., '...'),"
line = line.replaceFirst("^\s*\((.*)\),?\s*", "$1").trim();
String[] fields = line.split(",\s*", fieldCount);
for (int i = 0; i < fieldCount; ++i) {
String field = fields[i].trim().replaceFirst("^'(.*)'$", "$1");
pst.setString(1 + i, field); // SQL column nos counted from 1.
}
pst.execute();
}
}
conn.commit();
} catch (Throwable e) {
conn.rollback();
throw e;
}
}