简体   繁体   中英

How to recover from a unique constraint violation using Spring JDBCTemplate?

I am using spring jdbcTemplate with HSQLDB for inserting data into a PROFILE table that has 3 columns which have UNIQUE constraint applied to them ie username, phone number, driving license number.

I am able to identify the unique constraint violation using error code. But since there are multiple columns that have unique constraint this information is not enough to identify the column and display appropriate error message.

Any Ideas how this can be achieved?

There's no standard way to do that. You can parse exception message to find violated constraint name. Here's simple example:

public class HSqlDbTest {
    public static void main(String[] args) throws Exception {
        String url = "jdbc:hsqldb:mem:test";
        Class.forName("org.hsqldb.jdbcDriver");
        try (Connection connection = DriverManager.getConnection(url, "sa", "")) {
            String createTableSql = "" +
                    "create table test (" +
                    "  a integer not null,            " +
                    "  b integer not null,            " +
                    "  constraint a_uniq unique (a),  " +
                    "  constraint b_uniq unique (b)   " +
                    ")                                ";
            try (Statement statement = connection.createStatement()) {
                statement.executeUpdate(createTableSql);
            }

            try (PreparedStatement statement = connection.prepareStatement("insert into test (a, b) values (?, ?)")) {
                statement.setInt(1, 1);
                statement.setInt(2, 1);
                statement.executeUpdate();

                statement.setInt(1, 2);
                statement.setInt(2, 1);
                statement.executeUpdate();
            } catch (SQLIntegrityConstraintViolationException e) {
                Pattern pattern = Pattern.compile("integrity constraint violation: unique constraint or index violation; (\\w+) table: (\\w+)");
                Matcher matcher = pattern.matcher(e.getMessage());
                if (matcher.matches()) {
                    String constraintName = matcher.group(1);
                    String tableName = matcher.group(2);
                    System.out.printf("Violated constrant \"%s\" in the table \"%s\"\n", constraintName, tableName);
                }
            }
        }
    }
}

But I advise you not to go this way. Exception message is not standard and can change if you change your database. If there are multiple constraint violations, you will only get the first of them.

What you should do is to do separate select into your table to check whether that phone number or user name is already registered. It's much more reliable way to accomplish your task.

What you can do is catch DuplicateKeyException . From this you can then test against what fields could be causing the problem. This has the benefit that you don't need to parse exception messages that are vendor implemented

public void updateWidget(long id,
                         String name,
                         String category) {
    try {
        jt.update("update WIDGET" +
                  "   set DISPLAY_NAME = ?" +
                  "      ,CATEGORY = ?" +
                  " where ID = ?",
                  name,
                  category,
                  id);
    } catch (DuplicateKeyException ex) {
        // perform tests in turn, you could also perform a query to return
        // all violation counts if it is more efficient.
        if (jt.queryForObject("select count(1)" +
                              "  from WIDGET" +
                              " where NAME = ?",
                              Integer.class,
                              displayName) > 0) {
            throw new IllegalArgumentException(
                    "Widget name may not be duplicated.");
        }
        LOG.warn("Some unique constraint violation occurred: {}",
                 ex.getMessage(), ex);
        throw new IllegalArgumentException(
                "Some unique constraint violation occurred.");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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