![Java and RDBMS Married with Issues Database Constraints Speaker](https://data.docslib.org/img/3a60ab92a6e30910dab9bd827208bcff-1.webp)
Java and RDBMS Married with issues Database constraints Speaker Jeroen van Schagen Situation store Java Relational Application Database retrieve JDBC JDBC • Java Database Connectivity • Data Access API ( java.sql, javax.sql ) • JDK 1.1 (1997) • Relational Database • Many implementations Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); Database Maintain data User name : varchar(3) NOT-NULL, UNIQUE Name can only have up to 3 characters Name is required Name can only occur once Constraint types Not null Check Unique key Length Type Foreign key Primary key User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); What happens? Assuming the user table is empty User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); 1 row updated User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql); WhatWhat will happens? happen? User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql); SQLIntegrityConstraint WhatViolationException will happen? executeUpdate(sql) INSERT return 1 Inserted 1 Applicatio JDBC Database n executeUpdate(sql) INSERT throw Unique violation SQLIntegrityConstraint ViolationException User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql); User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; try { statement.executeUpdate(sql); statement.executeUpdate(sql); } catch (SQLIntegrityConstraintViolationException e) { throw new RuntimeException(“Name already exists”); } User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (NULL)”; statement.executeUpdate(sql); What happens? User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (NULL)”; statement.executeUpdate(sql); SQLIntegrityConstraint ViolationException User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (NULL)”; try { statement.executeUpdate(sql); } catch (SQLIntegrityConstraintViolationException e) { throw new RuntimeException(“Name is required”); throw new RuntimeException(“Name already exists”); } Unique key violation SQLIntegrityConstraint ViolationException Not null violation Unique key violation SQLIntegrityConstraint ViolationException Not null violation Which was violated? SQLException + getSQLState() : int + getMessage() : String SQLIntegrityConstraint ViolationException SQLException + getSQLState() : int + getMessage() : String SQLIntegrityConstraint ViolationException State Name 23000 Integrity constraint 23001 Restrict violation 23502 Not null violation 23503 Foreign key violation 23505 Unique violation 23514 Check violation User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (NULL)”; try { statement.executeUpdate(sql); } catch (SQLIntegrityConstraintViolationException e) { if (e.getSQLState() == 23502) { throw new RuntimeException(“Name is required”); } else if (e.getSQLState() == 23505) { throw new RuntimeException(“Name already exists”); } } User name : varchar(3) NOT-NULL, UNIQUE Connection connection = …; Statement statement = connection.createStatement(); String sql = “INSERT INTO user (name) VALUES (NULL)”; try { statement.executeUpdate(sql); } catch (SQLIntegrityConstraintViolationException e) { if (e.getSQLState() == 23502) { throw new RuntimeException(“Name is required”); } else if (e.getSQLState() == 23505) { throw new RuntimeException(“Name already exists”); } } Complicated Boilerplate Assumptions Multiple not-null values User name : varchar(3) NOT-NULL, UNIQUE email : varchar(30) NOT-NULL, UNIQUE Multiple not-null values Multiple unique values Which was violated? User name : varchar(3) NOT-NULL, uk_user_name UNIQUE email : varchar(30) NOT-NULL, uk_user_email UNIQUE SQLException + getSQLState() : int + getMessage() : String SQLIntegrityConstraint ViolationException Vendor messages They are all diferent Oracle ORA-00001: unique constraint (GOTO.UK_USER_NAME) violated\n MySQL Duplicate entry 'Jan' for key 'uk_user_name' HSQL integrity constraint violation: unique constraint or index violation; UK_USER_NAME table: USER PostgreSQL ERROR: duplicate key value violates unique constraint \"uk_user_name\" Detail: Key (name)=(Jan) already exists. H2 Unique index or primary key violation: "UK_USER_NAME_INDEX_1 ON GOTO.USER(NAME)"; SQL statement:\ninsert into user (name) values (?) [23505-171] Vendor messages The info is there Oracle ORA-00001: unique constraint (GOTO.UK_USER_NAME) violated\n MySQL Duplicate entry 'Jan' for key 'uk_user_name' HSQL integrity constraint violation: unique constraint or index violation; UK_USER_NAME table: USER PostgreSQL ERROR: duplicate key value violates unique constraint \"uk_user_name\" Detail: Key (name)=(Jan) already exists. H2 Unique index or primary key violation: "UK_USER_NAME_INDEX_1 ON GOTO.USER(NAME)"; SQL statement:\ninsert into user (name) values (?) [23505-171] Extract violation info • Message Just too difcult • Pattern matching Focus on application logic • Vendor specific Concrete exception classes UniqueKeyViolationException NotNullViolationException JDBC needs a better exception API ( for integrity constraints ) Access to constraint info getColumnName() getConstraintName() Workaround Prevent violations Prevent violations • Data integrity checks in application layer. Prevent not-null if (user.getName() == null) { throw new RuntimeException(“Name is required”); } Javax validation public class User { @NotNull private String name; } No SQL exception Conveys Less database interaction Less interaction throw new RuntimeException Applicatio Database n Duplication Application Database User User @NotNull name : varchar(3) private String name NOT-NULL, UNIQUE Duplication Application Database User User @NotNull name : varchar(3) private String name NOT-NULL, UNIQUE Kept in sync Unexpected SQL exceptions Prevent unique violation • Complicated • Depends on other rows id name NULL Testable in isolation id name Jan id name Jan Requires data users id name 1 Piet 2 Jan 3 Henk No SQL exceptions if (countUsersWithName(user.getName()) > 0) { throw new RuntimeException(“Name already exists”); } private int countUsersWithName(String name) { return jdbcTemplate.queryForObject( “SELECT COUNT(1) FROM user where name = ?”, name, Long.class); } Extra query Not atomic Problem: Not atomic Thread 1 COUNT WHERE name = ‘Jan’ return 0 Thread 2 INSERT (name) VALUES (‘Jan’) Applicatio Database n INSERTED 1 Uncaught Thread 1 Unexpected INSERT (name) VALUES (‘Jan’) Unique key violation Decision on old data Recap Lack proper solution Not null No SQL exceptions Duplication Error prone Unique key No SQL exceptions Extra query Error prone Solution Java Repository Bridge - JaRB Databases are good at maintaining integrity; let them! Prevent exception Catch exception Testable in isolation Not null Unique key Type Foreign key Length Primary key Check Prevent exception Validation Not null Type Length User name : varchar(3) NOT-NULL, UNIQUE @Entity email : varchar(100) @DatabaseConstrained public class User { @NotNull @Length(max=3) private String name; private String email; Retrieve } constraints Database as No duplication only truth validate(new User(‘Henk’)); 1. Loop over properties 3. Check name ‘Henk’ on metadata name = ‘Henk’ email = null Application 2. Get metadata varchar(3) user.name not null Determine column name (Hibernate) Database “ Name cannot be longer than 3 characters “ validate(new User(‘Henk’)); 1. Loop over properties 3. Check name ‘Henk’ on metadata name = ‘Henk’ email = null Application 2. Get metadata varchar(3) user.name not null Database validate(new User(‘Henk’)); validate(new User(null)); 1. Loop over properties 3. Check null name on metadata name = null email = null Application 2. Get metadata varchar(3) user.name not null Database “ Name cannot be null “ validate(new User(‘Henk’)); validate(new User(null)); 1. Loop over properties 3. Check null name on metadata name = null email = null Application 2. Get metadata varchar(3) user.name not null Database validate(new User(‘Henk’)); validate(new User(null)); validate(new User(‘Jan’)); 1. Loop over properties 3. Check name ‘Jan’ on metadata name =
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages95 Page
-
File Size-