准备好的声明是否以这种方式工作?

时间:2017-11-26 16:11:36

标签: java sql postgresql prepared-statement

我正在尝试用非常复杂的数据填充数据库中的一个表。为此,我使用的是生成器API(它为我提供了随机数据)。

public void populateCrackers(){
    PreparedStatement psm;
    String queryJoke = "(SELECT jid FROM Jokes WHERE jid=?)";
    String queryHat = "(SELECT hid FROM Hats WHERE hid=?)";
    String queryGift = "(SELECT gid FROM Gifts WHERE gid=?)";

    String query = "INSERT INTO Crackers(cid, name, jid, hid, gid, quantity) VALUES(" +
            "?, " +
            "?, " +
            queryJoke + ", " +
            queryHat + ", " +
            queryGift + ", " +
            "?)";

    System.out.println(query);

    String cracker_String = utils.JSONUtils.getJSON(crackerAPI, client);
    JSONObject crackerJSON = new JSONObject(cracker_String);
    JSONArray crackers = crackerJSON.getJSONArray("results");
    for(int j=0; j<crackers.length(); j++){
        try{
            psm = connection.prepareStatement(query);

            psm.setInt(1,crackers.getJSONObject(j).getInt("cid"));
            psm.setString(2, crackers.getJSONObject(j).getString("cname"));
            psm.setInt(3, crackers.getJSONObject(j).getInt("rjoke"));
            psm.setInt(4, crackers.getJSONObject(j).getInt("rhat"));
            psm.setInt(5, crackers.getJSONObject(j).getInt("rgift"));
            psm.setInt(6, crackers.getJSONObject(j).getInt("cquantity"));

            psm.execute();

            System.out.println(crackers.getJSONObject(j).get("cid") + " "
                    + crackers.getJSONObject(j).get("cname") + " "
                    + crackers.getJSONObject(j).get("cquantity") + " "
                    + crackers.getJSONObject(j).get("rjoke") + " "
                    + crackers.getJSONObject(j).get("rhat") + " "
                    + crackers.getJSONObject(j).get("rgift"));


        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

这是填充“Crackers”标签的方法。我想知道这是否被接受为准备好的声明。当我在psql交互式命令行工具中运行它时,恰好是带有一些选定id的语句(例如INSERT INTO Crackers (cid, name, hid, jid, gid, quantity) VALUES('cid', 'name', (SELECT hid FROM Hats WHERE hid=11), (SELECT jid FROM Jokes where jid=99), (SELECT gid FROM Gifts WHERE gid=13), 5)它可以完美地运行。

我的预备陈述是否打破了约束?

有什么想法吗?

LATER EDIT:不一致是null值可以到达我的Crackers表的形式(例如Cracker(1,“hello”,null,null,3,123)出现在表中。

3 个答案:

答案 0 :(得分:2)

代码是正确的,但必须关闭准备好的语句,最好在for循环之前创建一次语句。

现在有crackers.length()次语句创建但未关闭。这可能会带来问题。

使用try-with-resouce语法进行自动关闭,无论是否有任何异常或返回。

try (PreparedStatement psm = connection.prepareStatement(query)) {
    for (int j = 0; j < crackers.length(); j++) {
        ...
        psm.executeUpdate();

并致电executeUpdate而不是更一般的execute。产生的更新计数可能是有意义的(1/0)。

答案 1 :(得分:2)

Prepared声明没有任何内容。约束可以通过您设置的参数来破坏。您也可以在PreparedStatement中将PLSQL语句作为一个无限块运行。

用BEGIN围绕它......结束。只有一件事是不同的 - 对于JDBC参数是什么? mark not:PLSQL的参数,无法使用命名参数。

这意味着如果你需要为JDBC多次使用参数,你必须拥有那么多吗?标记并设置所有这些。

因此,请关注您传递给的参数及其序列。

答案 2 :(得分:1)

我意识到我的桌子上有错误的约束。我把空值放进去了。准备好的声明没有错。

创建表的正确查询是这样的:

String createCrackersQuery = "CREATE TABLE Crackers(" +
            "  cid INTEGER," +
            "  name VARCHAR NOT NULL," +
            "  jid INTEGER NOT NULL," +
            "  hid INTEGER NOT NULL," +
            "  gid INTEGER NOT NULL," +
            "  quantity INTEGER NOT NULL," +
            "  CONSTRAINT Cracker_Primary PRIMARY KEY (cid)," +
            "  CONSTRAINT Cracker_Name_Unique UNIQUE(name)," +
            "  CONSTRAINT Joke_Foreign FOREIGN KEY (jid) REFERENCES Jokes(jid)," +
            "  CONSTRAINT Hat_Foreign FOREIGN KEY (hid) REFERENCES Hats(hid), " +
            "  CONSTRAINT Gift_Foreign FOREIGN KEY (gid) REFERENCES Gifts(gid)" +
            ")";