45
Реляционные базы данных Модель предметной области

Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Embed Size (px)

Citation preview

Page 1: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Реляционные базы данных

Модель предметной области

Page 2: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Модель предметной областиСовокупность сущностей и их отношений в

базе данныхОтражающая взаимосвязи между

реальными объектами предметной области

Page 3: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Цели проектирования модели П.О.Точно отразить реальные взаимосвязи

между сущностямиУпростить логическую структуру БДОбеспечить удобное использование БДОблегчить возможную эволюцию моделиОптимально использовать физические

возможности машины

Page 4: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Терминология реляционных БД

Page 5: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Терминология реляционных БДОтношение ( = таблица)Атрибут ( = столбец)Заголовок отношения ( = типы столбцов)Кортеж ( = строка, запись)Первичный ключ ( = идентификатор)Внешний ключ ( = связь, отношение)

Page 6: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

НормализацияПроектирование начинается с одной

условной супертаблицы (отношения)Нормализация - декомпозиция отношения с

выделением меньших отношений и связей между ними

Выделяют не менее 5 нормальных формЗадача - свести исходное отношение к

приемлемой нормальной форме

Page 7: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

ИдентификаторыПервичный ключ (Primary Key)

Неявный ключСуррогатный ключЕстественный ключSequence / Serial / Identity

Вторичный ключ (Secondary Key)Композитный ключФункциональный ключУникальный ключ

Page 8: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

ИндексФизическая реализация вторичного ключаКомпактно организованная структураОсуществляет поиск записи по значению

ключа - помогает ускорить запросыОсуществляет проверку условия

(constraint) на пространстве ключей

Page 9: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Реализация индексаКак правило, физически хранится отдельно от

таблицыСодержит только данные ключа и ссылки на

соответствующие записиОрганизован в виде структуры поиска -

дерево поиска, хеш-таблица, гистограммаМожет храниться в памяти или на диске, в

зависимости от этого - разные реализации

Page 10: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

ВзаимосвязьТермин - внешний ключ (Foreign Key)Столбец-ссылка, указывает на ключ в

другой таблицеФизически реализуется в виде ссылки на

индекс в другой таблицеИспользование ссылок позволяет СУБД

переходить сразу к нужной записи

Page 11: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Типы взаимосвязи1:(0..1) “Один к одному”. Вспомогательная

таблица либо дополнительные столбцы1:* - “Один к многим”. Внешний ключ.*:* - “Многие ко многим”. Промежуточная

таблица с двумя внешними ключами.

Page 12: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Планирование запросовСУБД составляет план выполнения

каждого запроса с учетом физической организации данных

В плане выполнения задействуются индексы и связи между таблицами

При проектировании нужно убедиться, что планы выполнения наиболее важных запросов выстраиваются оптимально

Page 13: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Эффект от индексовНа построение и обновление индекса

тратится время - замедляется вставка, удаление и модификация

Можно быстро перейти к записи по значению вторичного ключа

При работе с внешними ключами часть операций можно производить на индексе

Page 14: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Результат проектированияСписок таблиц с заголовкамиМеханизмы генерации идентификаторовЗапланированные индексы (с типами)Связи между таблицамиСводный обзор планов выполнения

важнейших запросов

Page 15: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Подключение к базе данныхРеляционные базы данных

Page 16: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

SQL CLIsql> create table animals (id integer, name varchar, weight decimal);sql> show tables;TABLE_NAME | TABLE_SCHEMAANIMALS | PUBLICsql> insert into animals values (1, 'kitten', 2.5);sql> select name from animals where weight < 3.0;NAMEkitten

Page 17: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

JDBCOpen DataBase Connectivity (1992) -

унифицированное API SQL баз данныхJava DataBase Connectivity (1997) -

унифицированное Java API SQL БДИзначально JDBC просто оборачивало

ODBC, однако потом были написаны нативные реализации

Page 18: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Пример JDBCClass.forName("com.mysql.jdbc.Driver"); // Загрузка драйвераString url = "jdbc:mysql://localhost:3306/db_name";Connection conn = DriverManager.getConnection(url, user, pass);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery("SELECT * FROM users");while (rs.next()) { // Process row}stmt.close();

Page 19: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Проблема - слишком много буквРучное управление подключениямиРучное управление запросами к базеРучное управление транзакциямиОтсутствие конкурентного доступаОпасности при закрытии ресурсовНизкоуровневое API для данныхСложная работа с исключениями

Page 20: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Решение - Spring JDBCРасширение Spring FrameworkУправляет подключениями и запросамиВовремя закрывает дескрипторыТесно интегрировано с JTA и Spring

Transactions (см далее)Каноничная иерархия исключенийВысокоуровневое API для запросов

Page 21: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Пример Spring JDBCJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);int updated = jdbcTemplate.update( "insert into animals " + "(id, name, weight) " + "values (1, 'kitten', 2.5)");List<String> names = jdbcTemplate.queryForList( "select name from animals " + "where weight < 3.0", String.class);jdbcTemplate.execute("alter table animals " + "add column (height decimal)");

Page 22: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Реляционные базы данных

Устройство Spring JDBC

Page 23: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

DataSource<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /></bean>

Page 24: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

DataSource@Beanpublic DataSource dataSource( @Value("${jdbc.url}") String url, @Value("${jdbc.username}") String username, @Value("${jdbc.password}") String password) { return new DriverManagerDataSource(url, username, password);}

Page 25: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Connection PoolingSpring DataSource на каждый запрос

открывает новые подключенияВыгодно многократно переиспользовать

созданные подключенияЭто сложная задача с массой нюансовЕсть готовые реализации - C3P0, DBCP,

BoneCP

Page 26: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /></bean>

Пример BoneCP Datasource

Page 27: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

JDBC TemplateJdbcTemplate - класс-фасад, центральный

класс Spring JDBCПредоставляет методы для упрощенной

работы с JDBCСоздается вокруг конкретного DataSourceJdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

Page 28: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Методы JDBC TemplatejdbcTemplate.execute( “alter table users add column (last_login timestamp)”);int count = jdbcTemplate.queryForObject( “select count(*) from table”, Integer.class);String userName = jdbcTemplate.queryForObject( “select name from users where uid = 1”, String.class);List<String> admins = jdbcTemplate.queryForList( “select name from users where is_admin = 1”, String.class);Map<String, Object> row3 = jdbcTemplate.queryForMap( “select * from rows where row = 3”);

Page 29: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Методы JDBC Templateint inserted = jdbcTemplate.update( “insert into animals (id, name, weight) ” + “values (1, ‘kitten’, 2.5)”);int updated = jdbcTemplate.update( “update animals set is_heavy = 1 where weight > 50”);int deleted = jdbcTemplate.update( “delete from animals where is_heavy = 0”);

Page 30: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Реляционные базы данных

Возможности Spring JDBC

Page 31: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Row MapperList<Animal> animals = jdbcTemplate.query( "select * from animals", new RowMapper<Animal>() { public Animal mapRow(ResultSet rs, int rowNum) throws SQLException { Animal animal = new Animal(); animal.setId(rs.getInt("id")); animal.setName(rs.getString("name")); animal.setWeight(rs.getDouble("weight")); return animal; }});

Page 32: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Row MapperList<Animal> animals = jdbcTemplate.query( "select * from animals", (rs, rowNum) -> { Animal animal = new Animal(); animal.setId(rs.getInt("id")); animal.setName(rs.getString("name")); animal.setWeight(rs.getDouble("weight")); return animal;});

Page 33: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Row Callbackclass MeanCallback implements RowCallbackHandler { double sum = 0; int count = 0; public double getMean() { return sum/count; }

public void processRow(ResultSet rs) { sum += rs.getDouble(1); count += 1; }}

Page 34: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Row CallbackMeanCallback callback = new MeanCallback();String sql = "select weight from animals where in_zoo = 1";jdbcTemplate.query(sql, callback);double mean = callback.getMean();

Page 35: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Стандартизация исключенийВ JDBC фигурирует checked SQLExceptionУ каждого вендора свой подход к ошибкамИсключения в транзакционной среде

требуют внимательной обработкиSpring берет на себя разбор исключений Он использует свою unchecked иерархиюМаппинги пишутся отдельно к каждому

вендору (много доступно из коробки)

Page 36: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Prepared StatementСтадии обработки SQL-запроса:

Передача текста запросаПарсинг в синтаксическое деревоПостроение плана выполненияВыполнение (вжжжж!)

Для массовых однотипных запросов “планировочные” стадии несут оверхед

Есть возможность избежать этого

Page 37: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Prepared StatementЗапрос с Placeholder’ами:

select count(*) from animals where weight >= ? and weight < ? and country_id = 4;

Отправим запрос на сервер:Передача текста запросаПарсинг в синтаксическое деревоПостроение плана выполнения

Запомним ID запроса

Page 38: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Prepared StatementДля запроса достаточно отправить только

ID и значения Placeholder’овЭкономия на передаче данных, парсинге

текста и построении планаДля легких запросов это >50% времени

Page 39: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Prepared Statementstatic ANIMAL_ROW_MAPPER = new RowMapper<Animal>() {...}

for (int animalId : animalIds) { Animal animal = jdbcTemplate.queryForObject( "select * from animals where id = ? ", animalId, ANIMAL_ROW_MAPPER); animalsInZoo.add(animal); jdbcTemplate.update( "update animals set in_zoo = 1 where id = ? ", animalId);}

Page 40: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Batch UpdateList<Object[]> batchArgs = new ArrayList<>();batchArgs.add(new Object[] {2, "Panther", 200.0});batchArgs.add(new Object[] {3, "Leon", 250.0});batchArgs.add(new Object[] {4, "Tiger", 300.0}); jdbcTemplate.batchUpdate( "insert into animals values (?, ?, ?)", batchArgs);

Page 41: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Ручные Statement Setter’ыList<Animal> animals = ...;int batchSize = ...;String query = "insert into animals values (?, ?, ?)";jdbcTemplate.batchUpdate(query, animals, batchSize, new ParameterizedPreparedStatementSetter<Animal>() { public void setValues(PreparedStatement ps, Animal animal) throws SQLException { ps.setInt(1, animal.getId()); ps.setString(2, animal.getName()); ps.setDouble(3, animal.getWeight()); }});

Page 42: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Ручные Statement Setter’ыList<Animal> animals = ...;int batchSize = ...;String query = "insert into animals values (?, ?, ?";jdbcTemplate.batchUpdate(query, animals, batchSize, (ps, animal) -> { ps.setInt(1, animal.getId()); ps.setString(2, animal.getName()); ps.setDouble(3, animal.getWeight()); });

Page 43: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Maven dependencies<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.0.6.RELEASE</version></dependency><dependency> <groupId>com.jolbox</groupId> <artifactId>bonecp</artifactId> <version>0.8.0.RELEASE</version></dependency>

Page 44: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Рекомендуемая литература

Page 45: Industrial Programming Java - Lection Pack 03 - Relational Databases - Lavrentyev Fedor

Рекомендуемая литература

Кристофер Дейт.Введение в системы баз данных.Восьмое (!) издание.