JDBC Deleting an Entry - Primary Keys/CONCUR_UPDAT

2019-06-11 14:18发布

问题:

I´m dealing with a little database with a Swing GUI that is already functional, allowing the use to add a name and search for an entry. Now I have to implement the delete option. Here are the hints that I´m being given:

•Make sure the Statement is created as updatable.
•Make sure to update the insert statements to include the primary key field. Use the word "default" as the value for the field (no quotes)
•Make sure to include the primary key field in the query for the ResultSet

Currently I´m getting this error:

com.mysql.jdbc.NotUpdatable: Result Set not updatable (referenced table has no primary keys).This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE, the query must select only one table, can not use functions and must select all primary keys from that table. See the JDBC 2.1 API Specification, section 5.6 for more details. at greenDB.PhoneBookFrame$2.actionPerformed(PhoneBookFrame.java:119)

Now, this is a very straightforward error but still I´m having issues fixing it.

I have multiple classes, but the main ones are the DatabaseManager and the PhoneBookGui that instatiates the DatabaseManager. On the DatabaseManager, this is how the statement is created:

stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,  
                            ResultSet.CONCUR_UPDATABLE);

So, following the hints described above, the code above creates an updatable statement, correct?

Coming to the primary keys, I modified the table creation to add a primary key adding default values as suggested above. Here´s what I came up with:

"create table Listings (" +
    "PRIMARY KEY (id)" + //was not here before
    "LAST_NAME  varchar (16)," +
    "FIRST_NAME varchar (16)," +
    "AREA_CODE  varchar(3)," +
    "PREFIX     varchar(3)," +
    "SUFFIX     varchar(4))",
"insert into Listings values ('DEFAULT', 'ANDERSON', 'JOHN',  '314', '825', '1695')",
"insert into Listings values ('DEFAULT', 'CABLES',   'WALLY', '212', '434', '9685')",
"insert into Listings values ('DEFAULT', 'FRY',      'EDGAR', '415', '542', '5885')",
"insert into Listings values ('DEFAULT', 'MARTIN',   'EDGAR', '665', '662', '9001')",
"insert into Listings values ('DEFAULT', 'TUCKER',   'JOHN',  '707', '696', '8541')",

Now, presuming this is correct, I come to the third part, which is to make sure to include the primary key field in the query for ResultSet. Should this be done on the DatabaseManager class or on the instanted Database inside the GUI? I think the latter option is what I should do.

As I said, my GUI has buttons to add and to remove inputs. The add button is working perfectly, and I´ve did some changes on the code to include the primary key field. Here´s part of the code for the ActionListener on the add button:

class GetListener implements ActionListener {
    public void actionPerformed(ActionEvent aEvent) {
      String defaultPrimaryKey = "default"; //was not here before
      (other strings...)
      myDB.doGetQuery(buildQuery(defaultPrimaryKey, last, first, ac, pre ,sfx)); //added the primary key String
      ResultSet rset = myDB.getResultSet();
      (...)

Finally, this is the code for the remove button:

public void actionPerformed(ActionEvent aEvent) {
   try {
      int selected = table.getSelectedRow();
      ResultSet rset  = myDB.getResultSet();

      if(selected != -1 && selected < tblModel.getRowCount()) {
         rset.absolute(table.getSelectedRow() + 1);
         rset.first();
         rset.deleteRow(); // line where I get the error
         table.repaint();
         table.clearSelection();
      }

Any ideas how I might link all this information regarding primary keys and updatable statements to the deleteRow() method above?

回答1:

I have the solution for whomever relevant.

Primary key value can not be the same for many rows in the same table. Primary key defines each row uniquely so each row needs to have different value for the primary key field. For that when you are creating your table "Listings", you can use

"create table Listings (" +
    "LAST_NAME  varchar (16)," +
    "FIRST_NAME varchar (16)," +
    "AREA_CODE  varchar(3)," +
    "PREFIX     varchar(3)," +
    "SUFFIX     varchar(4)," +
    "ID MEDIUMINT NOT NULL AUTO_INCREMENT," + //this is the change you need
            "PRIMARY KEY (ID))",  //this is the change you need
    "insert into Listings (LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX) values ('ANDERSON', 'JOHN',  '314',  '825', '1965')",
    "insert into Listings (LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX) values ('CABLES', 'WALLY', '212',  '434', '9585')",
    "insert into Listings (LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX) values ('FRY', 'EDGAR', '415', '542', '5885')",
     "insert into Listings (LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX) values ('MARTIN',   'EDGAR', '665', '662', '9001')",
     "insert into Listings (LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX) values ('TUCKER',   'JOHN',  '707', '696', '8541')",

the following is essential and it is correct

stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,  
                            ResultSet.CONCUR_UPDATABLE);

The last part is when you are trying to delete a row make sure that in your query you include the primary key which is "ID". For example:

String query = "select ID, LAST_NAME, FIRST_NAME, AREA_CODE, PREFIX, SUFFIX from Listings" + whereClause;
resultSet = statement.executeQuery(query);
resultSet.deleteRow();