Java PreparedStatement executeBatch方法对主键引发唯一约束

我已经为我的DatabaseUtilities类编写了一个addContacts方法,供我的Messenger应用中使用。相关的数据库表是帐户联系人 accountContact 。我在尝试3NF时添加了后者。通过较低的JUnit测试工具运行代码时,我收到此错误:

无法添加联系人:[SQLITE_CONSTRAINT_PRIMARYKEY]主键约束失败(唯一约束失败:accountContact.uid,accountContact.cid)

我已经尝试将负责停止自动提交的代码注释掉,因为人们认为可能会出现提交混乱的问题,但这不是问题。我知道该SQL在直接在sqlite数据库中使用时会起作用,先将联系人一个接一个地添加,然后再添加accountContact记录。

以下代码是我的addContacts方法:

  boolean addContacts(List<Contact> contacts,account account) {
    try {
        try {
            conn.setautoCommit(false);

            queryInsertContact.clearParameters();
            queryInsertaccountContact.clearParameters();

            for (Contact contact : contacts) {
                if (ipv4Pattern.matcher(contact.getIpv4()).matches() && contact.getalias().length() <= 256 &&
                        contact.getTlsPort() >= 1024 && contact.getTlsPort() <= 65535) {
                    queryInsertContact.setString(1,contact.getcid());
                    queryInsertContact.setString(2,contact.getalias());
                    queryInsertContact.setString(3,contact.getIpv4());
                    queryInsertContact.setInt(4,contact.getTlsPort());
                    queryInsertContact.addBatch();

                    queryInsertaccountContact.setInt(1,account.getUid());
                    queryInsertaccountContact.setString(2,contact.getcid());
                    queryInsertaccountContact.addBatch();
                } else {
                    throw new SQLException("Format incorrect");
                }
            }

            queryInsertContact.executeBatch();
            queryInsertaccountContact.executeBatch(); // THE TEST HARnesS FAILS HERE

            conn.commit();
            return true;

        } catch (SQLException e) {

            System.out.println("failed to add contacts: " + e.getMessage());
            conn.rollback();
        } finally {
            conn.setautoCommit(true);
        }
    } catch (SQLException e) {
    }

    return false;
}

以下代码是我的addContacts测试工具:

 @org.junit.Test
public void addContacts() {

    List<Contact> contacts = new ArrayList<>();

    try {
        byte[] salt = getSalt(),hashWithSalt = getKey(salt,"password");
        String stringSalt = Base64.getEncoder().encodeToString(salt);
        String tempHash = Base64.getEncoder().encodeToString(hashWithSalt);

        account account = new account("james",tempHash,stringSalt,100000);
        Contact contact = new Contact("abc","accountboi","127.0.0.1",1025);
        databaseUtilities.addaccount(account,contact);

        try { // THIS CODE JUST GETS THE accOUNT INSTANCE WITH ITS UID DEFAULT WAS -1
            account = databaseUtilities.getaccount(account.getusername());
        }catch (SQLException e){}

        contacts.add(new Contact("f1dg13d7f8sfd","nrmad",1025));
    assertTrue(databaseUtilities.addContacts(contacts,account));

    contacts.clear();
    contacts.add(new Contact("f1dg13d7f8sfd",1025));
    assertFalse(databaseUtilities.addContacts(contacts,account));

    contacts.clear();
    contacts.add(new Contact("f1dg13d7f8sfd1","1234-0-0-1",account));

    contacts.clear();
    contacts.add(new Contact("f1dg13d7f8sfd2","127-a-a-a",1));
    assertFalse(databaseUtilities.addContacts(contacts,account));

    contacts.clear();
    contacts.add(new Contact("f1dg13d7f8sfd3","127.0.0.0",65536));
    assertFalse(databaseUtilities.addContacts(contacts,account));

    contacts.clear();
    contacts.add( new Contact("f1dg13d7f8sfd4",-1));
    assertFalse(databaseUtilities.addContacts(contacts,account));

    // UP TO HERE EVERYTHING IS WORKING. THE FOLLOWING CODE IS WHERE THE ERROR IS THROWN        

    contacts.clear();
    contacts.add(new Contact("a1",1025));
    contacts.add(new Contact("a2",1025));
    contacts.add(new Contact("a3",1025));

    assertTrue(databaseUtilities.addContacts(contacts,account)); // THIS STATEMENT


    }catch(NoSuchAlgorithmException |InvalidKeySpecException e){
        System.out.println(e.getMessage());
    }
}

以下SQL语句分别是帐户联系人 accountContact 表的转储:

CREATE TABLE contacts(cid TEXT PRIMARY KEY,alias TEXT NOT NULL,ipv4 TEXT NOT NULL,tlsport INTEGER NOT NULL);
CREATE TABLE accounts(uid INTEGER PRIMARY KEY,username TEXT NOT NULL,pass TEXT NOT NULL,salt TEXT NOT NULL,iterations INTEGER NOT NULL);
CREATE TABLE accountContact( uid INTEGER,cid TEXT,PRIMARY KEY(uid,cid),FOREIGN KEY (uid) REFERENCES accounts(uid),FOREIGN KEY (cid) REFERENCES contacts(cid));

这些SQL语句用于初始化以上代码中使用的准备好的语句

private static final String INSERT_CONTact = "INSERT INTO contacts(cid,alias,ipv4,tlsport) VALUES(?,?,?)";
private static final String INSERT_accOUNT = "INSERT INTO accounts(uid,username,pass,salt,iterations) VALUES(?,?)";
private static final String INSERT_accOUNTCONTact = "INSERT INTO accountContact(uid,cid) VALUES(?,?)";

这让我感到困惑了一段时间,我们将不胜感激。

谢谢

xiaoge1073 回答:Java PreparedStatement executeBatch方法对主键引发唯一约束

我使用的是PreparedStatement的clearParameters()方法,以为它将在每次测试addContacts()方法之后重置对象,但是有一个单独的方法可以对批处理clearBatch()进行此操作

本文链接:https://www.f2er.com/2434176.html

大家都在问