简体   繁体   English

预备陈述是否以这种方式工作?

[英]Does the prepared-statement work this way?

I am trying to populate one table in my database with pretty complex data. 我试图用非常复杂的数据填充数据库中的一个表。 For this, I am using a generator API (which gives me random data). 为此,我使用了生成器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();
        }
    }
}

This is the method that populates my "Crackers" tab. 这是填充“ Crackers”选项卡的方法。 I am wondering if this be accepted as a prepared statement. 我想知道这是否可以作为准备好的陈述接受。 When I run it in psql interactive command line tool, exactly that statement with some chosen ids (eg 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) it works flawlessly. 当我在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)可以正常工作。

Does my preparedstatement break the Constraint? 我的准备陈述会打破约束吗?

Any ideas? 有任何想法吗?

LATER EDIT: The inconsistency is the form of that null values can reach my Crackers table (eg Cracker(1, "hello", null, null, 3, 123) appears in the table. 稍后编辑:不一致的形式是空值可以到达我的Crackers表(例如,Cracker(1,“ hello”,null,null,3,123)出现在表中。

The code is correct, though the prepared statement must be closed, and it would be better to create the statement once, before the for loop. 该代码是正确的,尽管必须关闭准备好的语句,并且最好在for循环之前创建一次该语句。

Now there is crackers.length() times a statement created but not closed. 现在有crackers.length()乘以创建但未关闭的语句。 That might give problems. 这可能会带来问题。

Use the try-with-resouce syntax for automatic closing, irrespective of any exception or return. 使用try-with-resouce语法进行自动关闭,而不考虑任何异常或返回。

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

And call executeUpdate instead of the more general execute . 然后调用executeUpdate而不是更通用的execute The resulting update count might be of interest (1/0). 结果更新计数可能是令人感兴趣的(1/0)。

There is nothing about Prepared statement. 与Prepared语句无关。 Constraint can be broken by parameters you set to it. 约束可以通过您设置的参数来打破。 And you can run your PLSQL statement as anonimous block in PreparedStatement as well. 您也可以在PreparedStatement中将PLSQL语句作为匿名块运行。

Just surround it with BEGIN ... END. 只需用BEGIN ...结束将其包围即可。 only one thing is different - for JDBC parameters are ? 唯一不同的是-JDBC参数是? mark not :parameter as for PLSQL and there is no way to use named parameter. 对于PLSQL,将not标记为:parameter,并且无法使用命名参数。

That means if you need to use parameter more than once for JDBC you have to have that many ? 这意味着,如果您需要对JDBC多次使用参数,那么必须有那么多? marks and set all of them. 标记并设置所有这些标记。

So, focus on parameters you pass to and their sequence. 因此,请注意传递给它们的参数及其顺序。

I realised I had the wrong constraints on my table. 我意识到我的桌子上约束不正确。 I was letting null values in. There was nothing wrong with the prepared statement. 我让空值进入。准备好的语句没有错。

The right query to create the table is this one: 创建表的正确查询是这样的:

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)" +
            ")";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM