Spring обнаруживает
@Transactional и создает прокси для класса или метода.Прокси перехватывает вызов метода, аннотированного
@Transactional.Прокси делегирует управление
TransactionInterceptor, который начинает транзакцию через PlatformTransactionManager.Исходный метод выполняется.
Если метод завершился успешно, транзакция фиксируется (
commit). Если метод выбросил исключение, транзакция откатывается (rollback).Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔1
Чтобы выбрать данные из двух таблиц в одном запросе, используется оператор JOIN. Например, INNER JOIN объединяет строки, где есть совпадения в обеих таблицах, а LEFT JOIN возвращает все строки из первой таблицы и соответствующие строки из второй, заполняя NULL там, где данных нет.
В SQL существует несколько видов операторов JOIN, которые позволяют объединять данные из двух или более таблиц на основе определенных условий. Основные типы JOIN включают
INNER JOIN, LEFT JOIN, RIGHT JOIN, и каждый из них имеет свои особенности и использование. Рассмотрим их различия на примере двух таблиц:Таблица A:
id | name
-----------
1 | Alice
2 | Bob
3 | Charlie
Таблица B:
id | city
-----------
1 | New York
3 | Los Angeles
4 | Chicago
INNER JOIN возвращает только те строки, которые имеют совпадения в обеих таблицах. Если нет совпадающих строк, такие строки не включаются в результат.SELECT A.id, A.name, B.city
FROM A
INNER JOIN B ON A.id = B.id;
Результат:
id | name | city
------------------------
1 | Alice | New York
3 | Charlie | Los Angeles
LEFT JOIN возвращает все строки из левой таблицы (A) и совпадающие строки из правой таблицы (B). Если совпадения не найдено, в результате будут строки из левой таблицы с NULL значениями для столбцов из правой таблицы.SELECT A.id, A.name, B.city
FROM A
LEFT JOIN B ON A.id = B.id;
Результат:
id | name | city
------------------------
1 | Alice | New York
2 | Bob | NULL
3 | Charlie | Los Angeles
RIGHT JOIN возвращает все строки из правой таблицы (B) и совпадающие строки из левой таблицы (A). Если совпадения не найдено, в результате будут строки из правой таблицы с NULL значениями для столбцов из левой таблицы.SELECT A.id, A.name, B.city
FROM A
RIGHT JOIN B ON A.id = B.id;
Результат:
id | name | city
------------------------
1 | Alice | New York
3 | Charlie | Los Angeles
4 | NULL | Chicago
FULL JOIN возвращает все строки, когда есть совпадение в одной из таблиц. Это объединение LEFT JOIN и RIGHT JOIN. Если совпадения не найдено, результат будет содержать NULL значения для столбцов из другой таблицы.SELECT A.id, A.name, B.city
FROM A
FULL JOIN B ON A.id = B.id;
id | name | city
------------------------
1 | Alice | New York
2 | Bob | NULL
3 | Charlie | Los Angeles
4 | NULL | Chicago
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это методология управления проектами и одна из наиболее популярных реализаций Agile, предназначенная для гибкой разработки программного обеспечения. Scrum помогает командам работать более эффективно и адаптироваться к изменениям в требованиях и приоритетах. Основные концепции и элементы Scrum включают следующие компоненты:
Scrum разбивает работу над проектом на небольшие итерации, называемые спринтами. Каждый спринт обычно длится от одной до четырех недель и заканчивается созданием работающего инкремента продукта.
Команды в Scrum сами управляют своей работой и распределяют задачи между участниками без вмешательства извне.
В Scrum выделяются три основных роли:
Product Owner (Владелец продукта): отвечает за создание и управление бэклогом продукта, определение приоритетов и взаимодействие с заинтересованными сторонами.
Scrum Master: помогает команде следовать принципам Scrum, устраняет препятствия и обеспечивает эффективность работы команды.
Development Team (Команда разработки): непосредственно занимается созданием продукта, включает специалистов различных профилей, необходимых для выполнения задач.
список всех требований и функций, которые должны быть реализованы в продукте. Элементы бэклога приоритизируются владельцем продукта.
список задач, которые команда обязуется выполнить в текущем спринте. Эти задачи выбираются из бэклога продукта на основе приоритетов и возможностей команды.
фиксированный период времени, в течение которого команда работает над выполнением задач из бэклога спринта. В конце спринта команда демонстрирует результат своей работы.
ежедневные короткие встречи (обычно 15 минут), на которых команда обсуждает прогресс, планирует работу на день и выявляет препятствия.
встреча в конце каждого спринта, на которой команда демонстрирует результаты своей работы заинтересованным сторонам и получает обратную связь.
встреча после завершения спринта, на которой команда анализирует свою работу, обсуждает, что было хорошо, что можно улучшить, и разрабатывает план улучшений на следующий спринт.
Scrum позволяет быстро адаптироваться к изменяющимся требованиям и приоритетам.
Частые демонстрации результата и обратная связь обеспечивают высокую степень прозрачности процесса разработки.
Регулярные проверки и ретроспективы помогают команде постоянно улучшать качество продукта и процесса.
Scrum способствует более тесному взаимодействию между членами команды и заинтересованными сторонами.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В реляционных базах данных, операции объединения (JOIN) позволяют объединить строки из двух или более таблиц на основе связанных между собой столбцов. Существует несколько типов JOIN, каждый из которых имеет свои особенности и применим для разных ситуаций. Рассмотрим основные типы JOIN:
Объединяет строки из обеих таблиц, если они удовлетворяют условию объединения. Когда необходимо выбрать только те строки, которые имеют соответствующие значения в обеих таблицах.
SELECT *
FROM таблица1
INNER JOIN таблица2
ON таблица1.ключ = таблица2.ключ;
Возвращает все строки из левой таблицы и соответствующие строки из правой таблицы. Если соответствующей строки в правой таблице нет, в результирующем наборе данных для столбцов правой таблицы будут значения NULL. Когда необходимо выбрать все строки из одной таблицы и соответствующие данные из другой таблицы, если они существуют.
SELECT *
FROM таблица1
LEFT JOIN таблица2
ON таблица1.ключ = таблица2.ключ;
Возвращает все строки из правой таблицы и соответствующие строки из левой таблицы. Если соответствующей строки в левой таблице нет, в результирующем наборе данных для столбцов левой таблицы будут значения NULL. Когда необходимо выбрать все строки из одной таблицы (правой) и соответствующие данные из другой таблицы (левой), если они существуют.
SELECT *
FROM таблица1
RIGHT JOIN таблица2
ON таблица1.ключ = таблица2.ключ;
Возвращает все строки, когда есть совпадения либо в левой, либо в правой таблице. Если строки не соответствуют в одной из таблиц, для этой таблицы будут значения NULL. Когда необходимо выбрать все строки из обеих таблиц, независимо от того, есть ли соответствующие строки в другой таблице.
SELECT *
FROM таблица1
FULL JOIN таблица2
ON таблица1.ключ = таблица2.ключ;
Возвращает декартово произведение двух таблиц, то есть все возможные комбинации строк из обеих таблиц. Когда необходимо создать комбинации всех строк из обеих таблиц. Используется редко и с осторожностью, так как может привести к очень большому количеству строк.
SELECT *
FROM таблица1
CROSS JOIN таблица2;
Применяется для объединения таблицы самой с собой. Обычно используется для сравнения строк внутри одной и той же таблицы. Когда необходимо сопоставить строки одной таблицы друг с другом, например, для анализа иерархий или поиска парных записей.
SELECT A.*
FROM таблица A, таблица B
WHERE A.ключ = B.ключ;
Автоматически объединяет таблицы по всем столбцам с одинаковыми именами и типами данных. Когда у таблиц есть столбцы с одинаковыми именами, и нужно объединить их без явного указания условий объединения.
SELECT *
FROM таблица1
NATURAL JOIN таблица2;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Каждая запись в одной таблице связана с одной и только одной записью в другой таблице.
Пользователь (User) и Паспорт (Passport)
Каждому пользователю соответствует один уникальный паспорт. В реляционных базах данных можно реализовать эту связь с помощью уникального внешнего ключа.
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE passports (
id SERIAL PRIMARY KEY,
user_id INTEGER UNIQUE,
passport_number VARCHAR(50),
FOREIGN KEY (user_id) REFERENCES users(id)
);
Каждая запись в одной таблице может быть связана с несколькими записями в другой таблице, но каждая запись в другой таблице связана только с одной записью в первой таблице.
Пользователь (User) и Заказы (Orders)
Один пользователь может сделать много заказов, но каждый заказ связан с одним пользователем. Эта связь обычно реализуется с помощью внешнего ключа.
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER,
order_date DATE,
FOREIGN KEY (user_id) REFERENCES users(id)
);
Каждая запись в одной таблице может быть связана с множеством записей в другой таблице, и наоборот.
Студенты (Students) и Курсы (Courses)
Один студент может записаться на множество курсов, и каждый курс может быть записан многими студентами. Эта связь обычно реализуется с помощью промежуточной таблицы (таблицы связи), которая содержит внешние ключи обеих связанных таблиц.
CREATE TABLE students (
id SERIAL PRIMARY KEY,
name VARCHAR(100)
);
CREATE TABLE courses (
id SERIAL PRIMARY KEY,
course_name VARCHAR(100)
);
CREATE TABLE student_courses (
student_id INTEGER,
course_id INTEGER,
PRIMARY KEY (student_id, course_id),
FOREIGN KEY (student_id) REFERENCES students(id),
FOREIGN KEY (course_id) REFERENCES courses(id)
);
В нереляционных базах данных связи могут быть организованы иначе, поскольку они часто не поддерживают традиционные реляционные модели.
Вложенные документы
Например, в MongoDB документы могут включать вложенные документы или массивы, что позволяет моделировать отношения "один ко многим" и "многие ко многим" внутри одного документа.
{
"_id": 1,
"name": "John",
"orders": [
{ "order_id": 1, "order_date": "2023-08-01" },
{ "order_id": 2, "order_date": "2023-08-05" }
]
}Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Индексы в базе данных - это структуры, которые улучшают скорость операций поиска данных в таблице базы данных. Они работают по принципу, аналогичному указателю в книге, который позволяет быстро находить нужную информацию. Индексы создаются на одном или нескольких столбцах таблицы и позволяют значительно ускорить выполнение запросов, особенно при работе с большими объемами данных.
Основная функция индексов - это сокращение времени, необходимого для поиска записей в таблице. Без индексов база данных должна бы была проверять каждую запись, чтобы найти нужные данные.
Индексы могут значительно повысить производительность запросов SELECT, особенно тех, которые часто выполняются.
Индексы могут использоваться для ускорения операций сортировки, так как данные в индексе могут быть отсортированы.
Индексы также используются для обеспечения уникальности значений в столбцах. Например, уникальный индекс гарантирует, что в столбце не будет повторяющихся значений.
Индексы создаются с помощью SQL-запросов, таких как
CREATE INDEX. Можно создавать индексы на один столбец или на несколько столбцов (составные индексы).Существует несколько типов индексов, включая B-дерево, хеш-индексы, битмап-индексы и другие. Каждый тип имеет свои особенности и применяется в зависимости от конкретных задач.
При выполнении запросов база данных автоматически использует индексы для оптимизации поиска данных. Это не требует дополнительных действий со стороны пользователя.
Важно понимать, что индексы требуют дополнительного пространства на диске и могут замедлять операции вставки, обновления и удаления данных, так как индексы нужно поддерживать в актуальном состоянии. Поэтому следует тщательно продумывать, какие индексы необходимы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Docker - это платформа для автоматизации развёртывания, масштабирования и управления контейнеризированными приложениями. Она позволяет разработчикам создавать, тестировать и разворачивать приложения в изолированных средах, называемых контейнерами.
Это серверное ПО, которое запускает и управляет контейнерами. Состоит из двух частей:
Docker Daemon: Служба, которая управляет всеми объектами Docker (контейнерами, образами и т.д.).
Docker CLI: Командная строка, через которую пользователи взаимодействуют с Docker Daemon.
Это шаблоны для создания контейнеров. Образ включает в себя все зависимости, библиотеки, конфигурационные файлы, скрипты и код, необходимый для запуска приложения.
Это изолированные среды, в которых выполняются приложения. Контейнеры создаются на основе образов и содержат всё необходимое для работы приложения.
Это облачный сервис для хранения и распределения Docker-образов. Разработчики могут загружать свои образы в Docker Hub и делиться ими с другими пользователями.
Это инструмент для определения и управления многоконтейнерными Docker-приложениями. С помощью файла
docker-compose.yml можно описать конфигурацию всех контейнеров, сетей и томов, необходимых для работы приложения.Каждый контейнер работает в своей собственной изолированной среде, что предотвращает конфликты между приложениями.
Образы Docker могут работать на любом сервере с установленным Docker, независимо от операционной системы.
Контейнеры можно легко масштабировать в зависимости от нагрузки.
Контейнеры запускаются гораздо быстрее, чем виртуальные машины.
Docker интегрируется с системами непрерывной интеграции и доставки, упрощая процессы разработки и развёртывания.
docker build: Создание образа из Dockerfile.
docker run: Запуск нового контейнера из образа.
docker ps: Список запущенных контейнеров.
docker stop: Остановка работающего контейнера.
docker rm: Удаление остановленного контейнера.
docker pull: Загрузка образа из Docker Hub.
docker push: Загрузка образа в Docker Hub.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это метод программирования, при котором функция вызывает саму себя для решения подзадачи, являющейся частью общей задачи. Такой подход применяется, когда проблему можно разделить на более мелкие аналогичные части.
При вызове рекурсивной функции создается новый контекст выполнения, в котором хранятся ее локальные переменные и текущий прогресс. Каждый новый вызов функции откладывается в стек вызовов, пока не будет достигнуто базовое условие (условие выхода), после чего начинается обратный процесс – возвращение значений и сворачивание стека.
например, обход деревьев (DFS) или графов.
например, алгоритм "разделяй и властвуй" (быстрая сортировка, сортировка слиянием).
вычисление факториала, чисел Фибоначчи, генерация перестановок.
например, в компиляторах для обработки синтаксических деревьев.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Транзакция может читать данные, измененные другой транзакцией, даже если та еще не зафиксирована. Грязные чтения, неповторимые чтения и фантомные чтения. Редко используется на практике из-за высокого риска неконсистентных данных.
Транзакция видит только те изменения, которые были зафиксированы другими транзакциями. Незафиксированные изменения не видны. Неповторимые чтения и фантомные чтения. Широко используется, обеспечивает баланс между производительностью и консистентностью данных.
Гарантирует, что если транзакция повторно читает данные, она получит те же самые значения, даже если другие транзакции изменяют данные. Фантомные чтения. Используется, когда требуется более высокий уровень консистентности данных, но допускаются фантомные чтения.
Обеспечивает максимальный уровень изоляции. Транзакции выполняются так, как если бы они были сериализованы, то есть последовательно. Нет. Обеспечивает наивысшую консистентность данных, но может значительно снижать производительность из-за блокировок и задержек.
Происходит, когда транзакция читает данные, измененные другой транзакцией, которая еще не зафиксирована. Уровень Read Uncommitted допускает эту аномалию.
Происходит, когда транзакция читает те же данные несколько раз и получает разные значения из-за фиксации изменений другой транзакцией. Уровни Read Committed и выше предотвращают грязные чтения, но Read Committed допускает неповторимые чтения.
Происходит, когда транзакция выполняет одно и то же запрос несколько раз и видит разные наборы строк из-за вставки, обновления или удаления данных другой транзакцией. Уровень Repeatable Read предотвращает неповторимые чтения, но допускает фантомные чтения. Уровень Serializable предотвращает все три аномалии.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Да, в SQL есть диалекты. Это стандартный язык для управления реляционными базами данных, но каждая система управления базами данных (СУБД) может реализовывать его по-своему, добавляя собственные расширения и особенности. Эти вариации называются диалектами SQL.
хотя существуют стандарты SQL (например, SQL-92, SQL:1999, SQL:2003, SQL:2011 и другие), не все СУБД полностью их поддерживают. Вместо этого каждая СУБД адаптирует стандарт под свои нужды.
разработчики СУБД добавляют специфические функции и операторы, которые улучшают производительность и позволяют работать с данными эффективнее.
каждая СУБД может предлагать уникальные функции, такие как пользовательские типы данных, расширенные индексы, собственные функции аналитики и т. д.
имеет специфические функции, такие как
LIMIT для ограничения количества строк в запросе и специфичный синтаксис для UPSERT (INSERT ... ON DUPLICATE KEY UPDATE).поддерживает сложные типы данных, такие как JSON и массивы, а также расширенные функции работы с рекурсивными запросами.
включает процедурные расширения, такие как
DECLARE, BEGIN ... END, TRY ... CATCH и другие.содержит мощный встроенный язык программирования для написания хранимых процедур и триггеров.
минималистичный диалект, который не поддерживает некоторые сложные конструкции, но удобен для встраиваемых решений.
Если проект должен работать на разных СУБД, следует использовать стандартный SQL (ANSI SQL) или ORM (например, SQLAlchemy, Hibernate), который может адаптировать запросы под нужный диалект. При выборе конкретной СУБД важно изучить её специфические возможности и ограничения, так как переносимость SQL-кода между разными диалектами не всегда тривиальна.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Один из основных принципов объектно-ориентированного программирования (ООП), наряду с наследованием и полиморфизмом. Смысл инкапсуляции заключается в объединении данных и методов, работающих с этими данными, в одном объекте, а также в ограничении доступа к этим данным из внешнего мира.
В инкапсуляции данные (свойства) объекта скрываются от внешнего доступа и защищаются от некорректных изменений. Это достигается путем использования модификаторов доступа (например,
private, protected, public).Вместо прямого доступа к данным, предоставляются методы (геттеры и сеттеры) для чтения и изменения значений свойств. Это позволяет контролировать, каким образом данные могут быть изменены или получены.
Инкапсуляция помогает защитить внутреннее состояние объекта от некорректных или неожиданных изменений, обеспечивая целостность данных и уменьшая вероятность ошибок.
На Java
public class Person {
private String name;
private int age;
// Конструктор
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// Геттер для имени
public String getName() {
return name;
}
// Сеттер для имени
public void setName(String name) {
this.name = name;
}
// Геттер для возраста
public int getAge() {
return age;
}
// Сеттер для возраста
public void setAge(int age) {
if (age > 0) {
this.age = age;
} else {
System.out.println("Возраст должен быть положительным числом.");
}
}
}На Python
class Person:
def __init__(self, name, age):
self._name = name
self._age = age
# Геттер для имени
@property
def name(self):
return self._name
# Сеттер для имени
@name.setter
def name(self, name):
self._name = name
# Геттер для возраста
@property
def age(self):
return self._age
# Сеттер для возраста
@age.setter
def age(self, age):
if age > 0:
self._age = age
else:
print("Возраст должен быть положительным числом.")
# Пример использования
person = Person("John", 30)
print(person.name) # John
person.age = -5 # Возраст должен быть положительным числом.
print(person.age) # 30
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Асинхронные операции позволяют программам выполнять задачи в фоновом режиме, не блокируя основной поток выполнения. Это улучшает производительность и отзывчивость приложений.
HTTP-запросы: Асинхронные HTTP-запросы позволяют приложениям запрашивать данные у веб-серверов без блокировки пользовательского интерфейса. Например, загрузка данных из API, отправка форм и файлов. WebSockets: Поддержка двустороннего взаимодействия между клиентом и сервером в реальном времени. Это используется в чатах, онлайн-играх и других приложениях, где требуется мгновенная передача данных. API-вызовы: Асинхронные вызовы к внешним API позволяют продолжать выполнение других операций, не дожидаясь ответа от сервера.
Файловые операции: Асинхронное чтение и запись файлов позволяет обрабатывать большие объемы данных без блокировки основного потока выполнения. Работа с базами данных: Асинхронные запросы к базам данных уменьшают время ожидания и улучшают масштабируемость приложения.
Обработка задач в фоне: Выполнение длительных задач, таких как обработка изображений, видео, данных, без блокировки основного потока. Это позволяет улучшить пользовательский опыт, так как приложение остается отзывчивым. Периодические задания: Планирование и выполнение задач по расписанию, например, обновление данных, резервное копирование, мониторинг системы.
Асинхронные события: Обработка событий пользовательского интерфейса (например, нажатие кнопок, ввод данных) асинхронно для повышения отзывчивости приложений. Анимации и переходы: Асинхронное выполнение анимаций и переходов улучшает пользовательский опыт за счет плавности и непрерывности интерфейса.
Стриминг данных: Асинхронная обработка потоков данных в реальном времени, таких как видео, аудио, данные с датчиков. Это позволяет эффективно управлять непрерывными потоками информации. Реактивное программирование: Асинхронное реагирование на изменения данных и событий. Реактивные системы позволяют обрабатывать данные по мере их поступления, что особенно важно в приложениях, работающих с большим количеством данных.
Параллельные вычисления: Разделение больших задач на более мелкие части, которые выполняются параллельно. Это улучшает производительность при обработке больших объемов данных или выполнении сложных вычислений. Машинное обучение: Асинхронное обучение моделей и выполнение предсказаний позволяет эффективно использовать вычислительные ресурсы.
Асинхронная обработка пользовательских запросов, выполнение сетевых операций и взаимодействие с базами данных для повышения производительности и отзывчивости.
Асинхронные операции обеспечивают плавную работу интерфейса и эффективное использование ресурсов при выполнении сетевых запросов и операций ввода/вывода.
Асинхронное взаимодействие с серверами, обработка событий пользователя и управление игровыми объектами в реальном времени.
Параллельное выполнение вычислительных задач и обработка больших объемов данных для повышения эффективности исследований.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
В SQL,
JOIN операторы используются для объединения строк из двух или более таблиц на основе логического отношения между ними. Вот различия между LEFT JOIN, RIGHT JOIN и INNER JOIN:INNER JOIN возвращает только те строки, которые имеют совпадения в обеих таблицах, участвующих в соединении.SELECT A.*, B.*
FROM TableA A
INNER JOIN TableB B ON A.id = B.id;
LEFT JOIN возвращает все строки из левой таблицы и совпадающие строки из правой таблицы. Если совпадений нет, результат всё равно будет включать строки из левой таблицы с NULL значениями для столбцов из правой таблицы.SELECT A.*, B.*
FROM TableA A
LEFT JOIN TableB B ON A.id = B.id;
RIGHT JOIN (или RIGHT OUTER JOIN)RIGHT JOIN возвращает все строки из правой таблицы и совпадающие строки из левой таблицы. Если совпадений нет, результат всё равно будет включать строки из правой таблицы с NULL значениями для столбцов из левой таблицы.SELECT A.*, B.*
FROM TableA A
RIGHT JOIN TableB B ON A.id = B.id;
INNER JOIN
SELECT Employees.name, Departments.dept_name
FROM Employees
INNER JOIN Departments ON Employees.dept_id = Departments.dept_id;
LEFT JOIN
SELECT Employees.name, Departments.dept_name
FROM Employees
LEFT JOIN Departments ON Employees.dept_id = Departments.dept_id;
RIGHT JOIN
SELECT Employees.name, Departments.dept_name
FROM Employees
RIGHT JOIN Departments ON Employees.dept_id = Departments.dept_id;
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Это принцип программирования, который гласит, что информация или логика в коде не должны дублироваться. Каждый фрагмент знаний должен иметь одно, однозначное и авторитетное представление в системе. Этот принцип был введен в книге "The Pragmatic Programmer" Эндрю Хантом и Дэвидом Томасом.
Код должен быть написан так, чтобы не повторяться. Если одно и то же действие или информация используются в нескольких местах, они должны быть вынесены в одно место и использоваться повторно.
Изменения в коде нужно вносить в одном месте, что упрощает его сопровождение и уменьшает вероятность ошибок.
Код становится более понятным и структурированным, что облегчает его чтение и понимание.
Вынос общих операций в функции или методы, которые затем можно вызывать в различных частях программы.
Создание модулей или библиотек, которые содержат повторяющуюся логику и могут быть переиспользованы в различных проектах.
Объявление констант вместо использования "магических чисел" или строковых литералов в нескольких местах кода.
Использование шаблонов в HTML, XML или других языках разметки для генерации повторяющихся структур.
Хранение конфигурационных данных в одном месте, а не встраивание их в код.
Меньшее количество кода и дублирования упрощает понимание системы и снижает её сложность.
Легче поддерживать и обновлять код, так как изменения нужно вносить в одном месте.
Снижается вероятность ошибок, поскольку одно и то же изменение не нужно делать в нескольких местах.
Переиспользование кода ускоряет разработку, так как не нужно повторно писать уже существующий функционал.
Одинаковые блоки кода, выполняющие одну и ту же задачу, размещены в разных частях программы.
Те же самые данные (например, настройки или конфигурации) хранятся в нескольких местах.
Одни и те же структуры данных определены в разных местах программы.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Для выбора данных из двух таблиц без использования метода
JOIN можно использовать подзапросы. Подзапросы позволяют выполнять вложенные запросы, где результат одного запроса используется в другом запросе.Вы можете использовать подзапрос в операторе
SELECT, чтобы извлечь данные из одной таблицы, используя значения из другой таблицы.SELECT
o.order_id,
o.order_date,
(SELECT c.customer_name FROM customers c WHERE c.customer_id = o.customer_id) AS customer_name
FROM
orders o;
Вы можете использовать подзапрос в операторе
WHERE, чтобы фильтровать данные на основе условий из другой таблицы.SELECT
o.order_id,
o.order_date
FROM
orders o
WHERE
o.customer_id IN (SELECT c.customer_id FROM customers c WHERE c.city = 'New York');
Вы можете использовать подзапрос в операторе
FROM, чтобы создать временную таблицу и затем выбрать данные из нее.SELECT
c.customer_name,
latest_orders.order_id,
latest_orders.order_date
FROM
customers c,
(SELECT
o.customer_id,
o.order_id,
o.order_date
FROM
orders o
WHERE
o.order_date = (SELECT MAX(order_date) FROM orders o2 WHERE o2.customer_id = o.customer_id)
) AS latest_orders
WHERE
c.customer_id = latest_orders.customer_id;
Подзапросы могут быть полезны при использовании агрегатных функций для получения обобщенной информации из одной таблицы, связанной с другой таблицей.
SELECT
c.customer_name,
(SELECT COUNT(*) FROM orders o WHERE o.customer_id = c.customer_id) AS total_orders
FROM
customers c;
Оператор
EXISTS проверяет наличие строк в подзапросе и возвращает TRUE, если подзапрос возвращает хотя бы одну строку.SELECT
c.customer_name
FROM
customers c
WHERE
EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊1
Это последовательность одной или нескольких операций над базой данных, которая выполняется как единое целое. Транзакции обеспечивают, что все операции в рамках транзакции либо успешно выполняются, либо полностью отменяются, что гарантирует целостность данных.
Транзакция должна быть либо выполнена полностью, либо не выполнена вовсе. Если какая-то часть транзакции не удается, вся транзакция откатывается (roll back) к исходному состоянию.
Транзакция переводит базу данных из одного согласованного состояния в другое. Это означает, что после завершения транзакции все правила целостности данных должны быть соблюдены.
Результаты выполнения транзакции не должны быть видны другим параллельно выполняющимся транзакциям до тех пор, пока данная транзакция не завершится. Это предотвращает влияние одной транзакции на другую.
После успешного завершения транзакции (коммита) ее результаты должны быть зафиксированы в базе данных и сохранены, даже если произойдет сбой системы.
На SQL
BEGIN TRANSACTION;
-- Пример операций внутри транзакции
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- Если все операции прошли успешно
COMMIT;
-- Если произошла ошибка
ROLLBACK;
Пример на Java (использование JDBC)
Connection connection = null;
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "user", "password");
connection.setAutoCommit(false); // Начало транзакции
// Пример операций внутри транзакции
PreparedStatement pstmt1 = connection.prepareStatement("UPDATE accounts SET balance = balance - 100 WHERE account_id = ?");
pstmt1.setInt(1, 1);
pstmt1.executeUpdate();
PreparedStatement pstmt2 = connection.prepareStatement("UPDATE accounts SET balance = balance + 100 WHERE account_id = ?");
pstmt2.setInt(1, 2);
pstmt2.executeUpdate();
connection.commit(); // Коммит транзакции
} catch (SQLException e) {
if (connection != null) {
try {
connection.rollback(); // Откат транзакции при ошибке
} catch (SQLException ex) {
ex.printStackTrace();
}
}
e.printStackTrace();
} finally {
if (connection != null) {
try {
connection.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Это акроним, представляющий четыре ключевых свойства транзакций в системах управления базами данных (СУБД), которые гарантируют надежность и согласованность при выполнении операций с данными. Эти свойства необходимы для обеспечения целостности данных в многопользовательских и распределенных системах.
Атомарность гарантирует, что каждая транзакция выполняется полностью или не выполняется вовсе. Если любая часть транзакции завершается с ошибкой, то все изменения, внесенные в ходе этой транзакции, отменяются. Это свойство обеспечивает целостность данных, предотвращая частичные обновления. Пример: Если транзакция состоит из двух операций (перевод денег с одного счета на другой), то обе операции должны быть выполнены успешно или ни одна из них не должна быть выполнена.
Согласованность обеспечивает, что транзакция переводит базу данных из одного согласованного состояния в другое согласованное состояние. Это означает, что все правила и ограничения, заданные в базе данных (такие как целостность ссылок, уникальность и т.д.), должны быть соблюдены до и после выполнения транзакции. Пример: В базе данных учетных записей баланс счета не может быть отрицательным. Транзакция должна гарантировать, что это правило не будет нарушено.
Изолированность гарантирует, что результаты выполнения транзакции невидимы для других транзакций, пока она не будет завершена. Это свойство предотвращает проблемы, связанные с параллельным выполнением транзакций, такие как "грязные" чтения, неповторяемые чтения и фантомные чтения. Пример: Если одна транзакция читает данные, то она не увидит изменения, сделанные другой параллельно выполняющейся транзакцией, до тех пор, пока вторая транзакция не будет завершена.
Долговечность гарантирует, что после завершения транзакции ее результаты будут сохранены и останутся в базе данных даже в случае сбоя системы или потери питания. Это достигается путем записи изменений на диск и использования механизмов резервного копирования. Пример: После успешного выполнения транзакции, фиксирующей покупку товаров, информация о покупке останется в базе данных, даже если система сразу после этого выйдет из строя.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Идемпотентность — это свойство операции, при котором повторное выполнение этой операции приводит к тому же результату, что и однократное выполнение. Это понятие часто используется в контексте HTTP методов, API запросов и транзакций в системах с распределенной архитектурой.
GET: Получение ресурса. Повторный запрос не изменяет состояние ресурса.
PUT: Обновление или создание ресурса. Повторный запрос с одинаковыми данными приводит к одному и тому же состоянию ресурса.
DELETE: Удаление ресурса. Повторный запрос удаляет ресурс, если он существует, или не изменяет состояние, если ресурс уже удален.
POST: Создание нового ресурса. Повторный запрос приводит к созданию нового ресурса с новым идентификатором, что изменяет состояние системы.
GET запрос
GET /user/123
PUT запрос
PUT /user/123
{
"name": "John Doe",
"age": 30
}
Идемпотентная операция
UPDATE users SET name = 'John Doe' WHERE id = 123;
Неидемпотентная операция
INSERT INTO users (name, age) VALUES ('John Doe', 30);Идемпотентные операции помогают в обеспечении надежности и устойчивости систем, особенно в условиях повторных запросов из-за сетевых сбоев или таймаутов.
При сбоях в системе легче повторно выполнить идемпотентную операцию, не беспокоясь о непредвиденных изменениях состояния.
Идемпотентность упрощает разработку и тестирование, так как позволяет предсказуемо управлять состоянием системы при повторных запросах.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1
Это принцип проектирования и разработки, который предполагает, что системы и решения должны быть максимально простыми и избегать ненужной сложности. Этот принцип особенно важен в программировании и инженерии, так как помогает создавать более понятные, поддерживаемые и надежные системы.
Системы должны быть простыми в понимании и использовании. Чем проще система, тем меньше вероятность возникновения ошибок. Простота достигается за счет минимизации количества компонентов и взаимодействий между ними.
Код должен быть понятным и легко читаемым. Это облегчает его поддержку и модификацию. Использование понятных имен переменных, функций и классов, а также понятная структура кода способствуют ясности.
Компоненты или функциональность следует избегать. Если какой-то элемент системы не добавляет реальной ценности, его следует убрать. Это включает в себя как аппаратное, так и программное обеспечение.
Системы должны быть разбиты на небольшие, независимые модули, каждый из которых выполняет свою четко определенную задачу. Модульность помогает в тестировании, повторном использовании и поддержке кода.
При разработке функций или методов следует избегать создания слишком сложных алгоритмов, если можно использовать более простые и понятные решения. Использование стандартных библиотек и инструментов вместо написания собственного кода с нуля, когда это возможно.
В системной архитектуре следует избегать излишнего усложнения связей между компонентами системы. Использование простых и проверенных шаблонов проектирования вместо сложных и экспериментальных решений.
Документация должна быть простой и понятной, избегая излишне технических или сложных объяснений. Хорошо структурированная и лаконичная документация помогает пользователям и разработчикам быстрее понять систему.
Простые системы легче понимать и поддерживать, что снижает затраты на обучение и поддержку.
Чем проще система, тем меньше вероятность возникновения ошибок и проблем при её использовании.
Простые решения часто требуют меньше ресурсов и могут работать быстрее и эффективнее.
Простые и модульные системы легче масштабировать и расширять по мере необходимости.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from easyoffer
Новая фича на easyoffer – Автоотлики
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Вы автоматически откликаетесь на подходящие вам вакансии. Попробуйте её бесплатно и начните получать больше предложений о работе.
🚀 Запуск занимаем всего 3 минуты, а экономит очень много времени
🛡 Это безопасно: easyoffer официально одобрен HeadHunter и прошел его модерацию.
🥷🏻 Автоотклик незаметен для рекртера. Автоотклик ничем не отличается от обычного отклика, который вы делаете вручную
Рекрутеры давно используют автоматизацию для поиска кандидатов. Так почему вы должны откликаться вручную?
💡Совет – Добавьте шаблон сопроводительного письма, чтобы откликаться на большее количество вакансий (на некоторые вакансии нельзя откликнуться без сопроводительного)
Попробовать бесплатно → https://easyoffer.ru/autoapply
Это стандартный протокол для веб-серверов, который позволяет запускать внешние программы (скрипты) для генерации веб-страниц динамически. CGI скрипты могут быть написаны на различных языках программирования, таких как Perl, Python, PHP, C и других. Когда веб-сервер получает запрос на страницу, обрабатываемую CGI, он запускает соответствующий скрипт и передает ему данные запроса.
CGI прост в реализации и не требует сложной настройки. Поддерживает множество языков программирования, что делает его универсальным решением.
CGI является стандартом и поддерживается практически всеми веб-серверами.
Каждый запрос запускает новый процесс, что обеспечивает изоляцию запросов и повышает безопасность.
Каждый запрос создает новый процесс, что может быть ресурсоемким и замедлять работу сервера при большом количестве запросов. Создание и завершение процессов занимает время, что увеличивает задержку ответа.
Плохая производительность при высоких нагрузках делает CGI плохо подходящим для масштабируемых веб-приложений. Ограниченная возможность использования пула процессов для повышения эффективности.
Сложнее интегрироваться с современными технологиями и фреймворками. Отсутствие встроенных средств для работы с сессиями, аутентификацией и другими функциями современных веб-приложений.
Улучшенная версия CGI, которая повторно использует процессы для обработки нескольких запросов, что повышает производительность.
Языки и фреймворки, такие как PHP, ASP.NET, Node.js, Django, Ruby on Rails, которые интегрируются непосредственно с веб-серверами и обеспечивают высокую производительность.
Стандартный интерфейс для Python-приложений, позволяющий эффективную обработку запросов.
Серверы приложений, такие как Apache Tomcat, JBoss, которые предоставляют контейнеры для выполнения веб-приложений и управления ими.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM