95
Java and RDBMS Married with issues Database constraints

Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

  • Upload
    others

  • View
    47

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Java and RDBMSMarried with issues

Database constraints

Page 2: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Speaker

Jeroen van Schagen

Page 3: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Situation

store

retrieveJava

ApplicationRelational Database

JDBC

Page 4: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Java Database Connectivity

• Data Access API ( java.sql, javax.sql )

• JDK 1.1 (1997)

• Relational Database

• Many implementations

JDBC

Page 5: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql);

Page 6: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql);

Page 7: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

User

name : varchar(3) NOT-NULL, UNIQUE

Name can only haveup to 3 characters

Name is required

Name can only occur once

Database

Maintain data

Page 8: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Constraint types

Not null

Type

Length

Primary key Foreign key

Unique key

Check

Page 9: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql);

Username : varchar(3) NOT-NULL, UNIQUE

What happens?

Assuming the user table is empty

Page 10: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql);

Username : varchar(3) NOT-NULL, UNIQUE

1 row updated

Page 11: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql);

What will happen?

Username : varchar(3) NOT-NULL, UNIQUE

What happens?

Page 12: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql);

What will happen?

Username : varchar(3) NOT-NULL, UNIQUE

SQLIntegrityConstraintViolationException

Page 13: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Application JDBC Database

executeUpdate(sql) INSERT

return 1 Inserted 1

executeUpdate(sql) INSERT

Unique violationthrowSQLIntegrityConstraint

ViolationException

Page 14: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (‘Jan’)”; statement.executeUpdate(sql); statement.executeUpdate(sql);

Username : varchar(3) NOT-NULL, UNIQUE

Page 15: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

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”);}

Username : varchar(3) NOT-NULL, UNIQUE

Page 16: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (NULL)”; statement.executeUpdate(sql);

Username : varchar(3) NOT-NULL, UNIQUE

What happens?

Page 17: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Connection connection = …; Statement statement = connection.createStatement();

String sql = “INSERT INTO user (name) VALUES (NULL)”; statement.executeUpdate(sql);

Username : varchar(3) NOT-NULL, UNIQUE

SQLIntegrityConstraintViolationException

Page 18: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

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”);}

Username : varchar(3) NOT-NULL, UNIQUE

Page 19: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Unique key violation

SQLIntegrityConstraint ViolationException

Not null violation

Page 20: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Unique key violation

Not null violation

SQLIntegrityConstraint ViolationException

Which was violated?

Page 21: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

SQLException

+ getSQLState() : int+ getMessage() : String

SQLIntegrityConstraint ViolationException

Page 22: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

SQLException

+ getSQLState() : int+ getMessage() : String

SQLIntegrityConstraint ViolationException

Page 23: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

State Name

23000 Integrity constraint

23001 Restrict violation

23502 Not null violation

23503 Foreign key violation

23505 Unique violation

23514 Check violation

Page 24: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

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”); } }

Username : varchar(3) NOT-NULL, UNIQUE

Page 25: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

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”); } }

Username : varchar(3) NOT-NULL, UNIQUE

Complicated Boilerplate Assumptions

Page 26: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Multiple not-null values

User

name : varchar(3) NOT-NULL, UNIQUEemail : varchar(30) NOT-NULL, UNIQUE

Page 27: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

uk_user_name

uk_user_email

Multiple not-null valuesMultiple unique values

User

name : varchar(3) NOT-NULL, UNIQUEemail : varchar(30) NOT-NULL, UNIQUE

Which was violated?

Page 28: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

SQLException

+ getSQLState() : int+ getMessage() : String

SQLIntegrityConstraint ViolationException

Page 29: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Vendor messages

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.

Oracle ORA-00001: unique constraint (GOTO.UK_USER_NAME) violated\n

MySQL Duplicate entry 'Jan' for key 'uk_user_name'

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]

They are all different

Page 30: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Vendor messages

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.

Oracle ORA-00001: unique constraint (GOTO.UK_USER_NAME) violated\n

MySQL Duplicate entry 'Jan' for key 'uk_user_name'

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]

The info is there

Page 31: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Message

• Pattern matching

• Vendor specific

Extract violation info

Just too difficult

Focus on application logic

Page 32: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

JDBC needs a better exception API ( for integrity constraints )

Concrete exception classes

UniqueKeyViolationException

NotNullViolationException

Access to constraint info

getColumnName()

getConstraintName()

Page 33: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Workaround

Page 34: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Prevent violations

Page 35: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Data integrity checks in application layer.

Prevent violations

Page 36: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Prevent not-null

if (user.getName() == null) { throw new RuntimeException(“Name is required”); }

Page 37: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Javax validation

public class User { @NotNull private String name; }

Conveys

No SQL exception

Less database interaction

Page 38: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Application

Database

throw new RuntimeException

Less interaction

Page 39: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

User@NotNull private String name

User

name : varchar(3) NOT-NULL, UNIQUE

Application Database

Duplication

Page 40: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

User@NotNull private String name

User

name : varchar(3) NOT-NULL, UNIQUE

Application Database

Kept in sync Unexpected SQL exceptions

Duplication

Page 41: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Complicated

• Depends on other rows

Prevent unique violation

Page 42: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

id name

NULL

Testable in isolation

Page 43: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

id name

Jan

Page 44: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

id name

id nameusers

Piet

Henk

Jan

1

2

3

Jan

Requires data

Page 45: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

No SQL exceptions

Extra query Not atomic

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); }

Page 46: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Problem: Not atomic

Application Database

INSERT (name) VALUES (‘Jan’)

INSERTED 1

Thread 2

COUNT WHERE name = ‘Jan’return 0

Thread 1

INSERT (name) VALUES (‘Jan’)

Unique key violation

Thread 1

Decision onold data

UnexpectedUncaught

Page 47: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Recap

No SQL exceptions Error proneDuplication

Not null

Extra query

Unique key

No SQL exceptions Error prone

Lack proper solution

Page 48: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

SolutionJava Repository Bridge - JaRB

Page 49: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Databases are good atmaintaining integrity;

let them!

Page 50: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Catch exceptionPrevent exceptionTestable in isolation

Not null

Type

Length

Check

Unique key

Foreign key

Primary key

Page 51: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Prevent exceptionValidation

Not null Type Length

Page 52: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

@Entity @DatabaseConstrained public class User { @NotNull @Length(max=3) private String name; private String email; }

Username : varchar(3) NOT-NULL, UNIQUE email : varchar(100)

No duplication

Retrieve constraints

Database as only truth

Page 53: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

varchar(3) not null

name = ‘Henk’ email = null

1. Loop over properties 3. Check name ‘Henk’ on metadata

Database

Application

2. Get metadata user.name

Determine column name (Hibernate)

Page 54: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Database

Applicationname = ‘Henk’ email = null

varchar(3) not null

1. Loop over properties 3. Check name ‘Henk’ on metadata

“ Name cannot be longer than 3 characters “

2. Get metadata user.name

validate(new User(‘Henk’));

Page 55: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

name = null email = null

1. Loop over properties 3. Check null name on metadata

validate(new User(null));

varchar(3) not null

Database

Application

2. Get metadata user.name

Page 56: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

Applicationname = null email = null

varchar(3) not null

1. Loop over properties 3. Check null name on metadata

validate(new User(null));

“ Name cannot be null “

Database

2. Get metadata user.name

Page 57: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

name = ‘Jan’ email = null

1. Loop over properties 3. Check name ‘Jan’ on metadata

validate(new User(null));validate(new User(‘Jan’));

Database

Application

varchar(3) not null

2. Get metadata user.name

Page 58: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

Database

Applicationname = ‘Jan’ email = null

varchar(3) not null

1. Loop over properties 3. Check name ‘Jan’ on metadata

2. Get metadata user.name

validate(new User(null));validate(new User(‘Jan’));

Page 59: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

name = ‘Jan’ email = null

varchar(100)

1. Loop over properties 3. Check null email on metadata

Database

Application

2. Get metadata user.email

validate(new User(null));validate(new User(‘Jan’));

Page 60: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

Database

Applicationname = ‘Jan’ email = null

varchar(100)

1. Loop over properties 3. Check null email on metadata

2. Get metadata user.email

validate(new User(null));validate(new User(‘Jan’));

Page 61: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

validate(new User(‘Henk’));

Database

Applicationname = ‘Jan’ email = null

varchar(100)

1. Loop over properties 3. Check null email on metadata

2. Get metadata user.email

validate(new User(null));validate(new User(‘Jan’));

Page 62: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Super class@MappedSuperclass @DatabaseConstrained public abstract class BaseEntity { }

@Entity public class User extends BaseEntity { private String name; private String email; }

Page 63: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

JDBC

@DatabaseConstrained public class User { private String name; private String email; }

Custom schema mapper

Page 64: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Catch exceptionException translation

CheckUnique key Foreign key Primary key

Page 65: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Translate the JDBC exception into a proper constraint exception

Page 66: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Existing translators

Page 67: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Object Relation Mapping

• Extracts constraint name from message

Hibernate

Page 68: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Hibernate

ConstraintViolationExceptiongetConstraintName()

Access to constraint name

Hardcoded namesHeavy for plain JDBC

Page 69: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Hardcoded names

try { // Insert user } catch (ConstraintViolationException e) { if (e.getConstraintName() == “uk_user_name”) { // Handle error } }

Too technical

Focus on domain

Page 70: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• Dependency Injection

• Templates

• JDBC

• DAO

Spring

Page 71: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• JdbcTemplate

• SQLExceptionTranslator

• Error codes

• Register own classes

• No constraint name

Spring JDBC

Page 72: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Spring

DataAccessException

DataIntegrityViolationException

Consistent hierarchy

Extensible

Page 73: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

• ORM (e.g. Hibernate)

• PersistenceExceptionTranslator

• Proxy

Spring DAO

Page 74: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Spring$Proxy

PersistenceExceptionTranslator

ConstraintViolation Exception JPASystemException

UserRepository

Page 75: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

No constraint name

ConstraintViolationExceptiongetConstraintName()

JPASystemException

DataAccessException

cause

Hierarchy

Weaker API

Page 76: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Weaker API

try { userRepository.save(user); } catch (JPASystemException e) { ConstraintViolationException ce = (ConstraintViolationException) e.getCause(); if (ce.getConstraintName() == “uk_user_name”) { // Handle error } }

Unsafe cast

Why isn’t this easier?

Page 77: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Recap

Constraint name

Hierarchy

Extensible

Hibernate Spring JaRB

Best of both worlds

Page 78: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

JaRB

Concrete and domain specific exceptions.

Map each constraint to a custom exception.

Page 79: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

try { userRepository.save(new User(“Jan”)); } catch (UserNameAlreadyExistsException e) { error(“User name already exists.”); }

Page 80: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

try { userRepository.save(new User(“Jan”)); } catch (UserNameAlreadyExistsException e) { error(“User name already exists.”); } catch (UserEmailAlreadyExistsException e) { error(“User email already exists.”); }

Page 81: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Translator

SQLIntegrity ConstraintException

UserNameAlready ExistsException

Page 82: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Resolver

ERROR: duplicate key value violates unique constraint \"uk_user_name\" Detail: Key (name)=(Jan) already exists.

Extract all information from exception

SQLIntegrity ConstraintException

Page 83: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Resolver

ERROR: duplicate key value violates unique constraint \"uk_user_name\" Detail: Key (name)=(Jan) already exists.

Vendor specific

Pattern matching

Extract all information from exception

Column name Value

Constraint name

Version specific

SQLIntegrity ConstraintException

Page 84: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Resolvers

• Pattern matching (default) • PostgreSQL • Oracle • MySQL • HSQL • H2

• Hibernate: constraint name only

Page 85: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Factory

Create a concrete exception

Page 86: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Default factory

UniqueKeyViolationException

NotNullViolationException

LengthExceededViolationException

PrimaryKeyViolationException

CheckFailedException

InvalidTypeException

ForeignKeyViolationException

Page 87: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

DatabaseConstraintViolationException

UniqueKeyViolationException

NotNullViolationException

LengthExceededViolationException

PrimaryKeyViolationException

CheckFailedException

InvalidTypeException

ForeignKeyViolationException

UserNameAlreadyExistsException

Constraint info

Page 88: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Custom exceptions

@NamedConstraint(“uk_user_name”) public class UserNameAlreadyExistsException extends UniqueKeyViolationException { }

Scanned from class path

Registered on constraint

Page 89: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Custom exceptions

uk_user_name UserNameAlreadyExistsException

uk_user_email UniqueKeyViolationException

Page 90: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Injectable arguments

@NamedConstraint(“uk_user_name”) public class UserNameAlreadyExistsException extends UniqueKeyViolationException { UserNameAlreadyExistsException(…) { } }

DatabaseConstraintViolationThrowable (cause)

ExceptionFactory

Page 91: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Less concrete

try { userRepository.save(new User(“Jan”)); } catch (UniqueKeyViolationException e) { error(“User name already exists.”); }

Page 92: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

How?

Page 93: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Enable in Spring@EnableDatabaseConstraints(basePackage = “org.myproject”)

Enable exception translation

Enable database validation

Resolve database vendorRegister custom exceptions

<jarb:enable-constraints base-package=“org.myproject”/>

Page 94: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Get source

<dependency> <groupId>org.jarbframework</groupId> <artifactId>jarb-constraints</artifactId> <version>2.1.0</version></dependency>

Maven central

http://www.jarbframework.org

Github

Page 95: Java and RDBMS - gotocon.com · •Java Database Connectivity • Data Access API ( java.sql, javax.sql) • JDK 1.1 (1997) • Relational Database • Many implementations JDBC

Questions?