Тема 37. Spring Data JPA - BelyiZ/JavaCourses GitHub Wiki
- Общая информация о JPA и ORM
- Подключение к базе данных
- Spring-репозитории
- CRUD-операции
- Список литературы/курсов
Spring Data JPA - это удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение, в каких то случаях для этого будет достаточно объявить интерфейс и метод в нем, без имплементации. Он обеспечивает доступ к данным: реляционные и нереляционные БД
В мире Java EE стандартом дефакто для работы с базами данных является JPA (Java Persistence API). Spring Data JPA, будучи частью Spring Data, реализует взаимодействие с реляционными СУБД, основываясь на JPA.
Главными компонентами для взаимодействий с БД в Spring Data являются репозитории. Каждый репозиторий работает со своим классом-сущностью.
Стоит отметить,что Spring Data — это общее название множества подпроектов:
Spring Data JDBC, Spring Data JPA и множество других, таких как Spring Data REST, Spring Data Redis, Spring Data LDAP.
Spring Data JPA
Все проекты Spring Data упрощают создание репозиториев/DAO и SQL-запросов.
Особенностью Spring Data является то, что он понимает JPA-аннотации вашего класса User (@Entity, @Column, @Table и т.д.) и автоматически генерирует репозитории. Это означает, что получаем все основные CRUD-операции (save, delete, findBy) без необходимости писать дополнительный код.
ORM
(объектно-реляционное отображение) указывает на карту отношений объекта.
В разработке объектно-ориентированного программного обеспечения вы можете отображать объекты в реляционную базу данных через ORM
.
До тех пор, пока есть набор программ для создания объекта с базой данных, объект операции может напрямую управлять данными базы данных, можно сказать, что эта программа реализует карту объекта ORM
.
Проще говоря: ORM
- это отношение между классом класса и базы данных и базы данных, тем самым достижение класса Experational Entity
, эквивалентно цели эксплуатации таблицы базы данных.
Преимущества использования ORM
При внедрении приложения (не используя отображение O / R), возможно написать код уровня доступа, сохранять данные, изменять данные и удалять данные из базы данных, и этот код повторяется.
Использование ORM
значительно снизит повторяющийся код.
Объект реляционного сопоставления, Abbotation ORM
, в основном реализует отображение программных объектов к данным реляционной базы данных.
Полное имя JPA
- API Java Spistence
, API Java Pursistical API
.
JPA Аннотировала взаимосвязь карты объекта-реляционной таблицы через JDK 5.0 и сохраняет объект рабочего периода в базу данных.
Преимущества использования JPA
-
Стандартизация
JPA
является одним из стандартовJava EE
, выпущенных организациейJCP
, поэтому любые рамки, которые утверждают, что соблюдают стандарты JPA, следует той же архитектуре, обеспечивая тот же API доступа, обеспечивая то, чтоJPA
, разработанные приложениям Enterprise, могут пройти небольшое количество модификаций В рамках JPA. -
Поддержка функций уровня контейнера
JPA Framework
поддерживает большие наборы данных, транзакции, одновременные транзакции на уровне контейнеров, которые делают JPAS за пределы ограничений простых структур постоянства и играют большую роль в корпоративных приложениях.
- Легко и удобно
Одним из главных целей JPA является предоставление более простой модели программирования: создание объекта в рамках JPA и создание класса Java простой, нет никаких ограничений и ограничений, просто нужно использовать javax.persistente.entity. И интерфейс также очень прост, нет никаких требований к специальным правилам и шаблонам проектирования, а разработчики могут легко освоить. JPA разработан на основе неинвазивных принципов, поэтому он может быть проще и другие рамки или интеграция контейнера.
- Запрос
Язык запроса JPA является объектно-ориентированным, а не базой данных, которая создает операторы запроса с объектно-ориентированным натуральным синтаксисом, который можно увидеть как эквивалент Hibernate HQL. JPA определяет уникальный JPQL (язык запроса Java). JPQL является расширением EJB QL. Это язык запроса для объектов. Операционные объекты являются объектами, а не реляционными базами данных, а также могут поддерживать объемные обновления и модификации, объединения, группу Имея и т. Д. Обычно только SQL может предоставить расширенные функции запроса и даже подзапросных подзам.
- Расширенные возможности
Объектно-ориентированные расширенные особенности, такие как наследование, полиморфизм и классы между классами, такие как сложная связь между мультиплексиями и классами, так что разработчики могут максимизировать использование объектно-ориентированных моделей, не требуя обработки этих функций в реляционной базе данных. упорство.
- Отношения JPA с гибернатом Спецификация JPA по сути является спецификацией ORM, обратите внимание, что Framework ORM - поскольку JPA не предоставляет реализацию ORM, она только разработана, предоставляя некоторые интерфейсы API программирования, но конкретная реализация осуществляется производителями услуг.
Отношения JPA и Hibernate похожи на драйверы JDBC и JDBC, JPA является спецификацией, а Hibernate также является реализацией JPA в дополнение к структуре ORM. Как заменить гибернацию? Может ли спецификация JDBC привлекать базовую базу данных? Ответ негативно, то есть, если операция базы данных выполняется с использованием спецификации JPA, базовая система требует гибернации в качестве своего класса реализации для полной настойчивости данных.
При моделировании реальной системы или процесса хорошим вариантом являются репозитории в стиле доменного проектирования (DDD).
Именно для этой цели возможно использовать Spring Data JPA
в качестве уровня абстракции доступа к данным.
Spring Data JPA
— дополнительный удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение.
Spring Data JPA
по умолчанию использует Hibernate
в качестве реализации JPA
.
Во многих случаях нам не нужно было бы самим писать какие-либо запросы.
Вместо этого нам нужно только создать интерфейсы, которые, в свою очередь, расширяют общие интерфейсы хранилища данных Spring
:
public interface LocationRepository extends JpaRepository {
}
И это само по себе позволило бы нам выполнять общие операции – CRUD
, подкачка и сортировка – на объекте Location
, который имеет первичный ключ типа Long
.
Кроме того, Spring Data JPA
оснащен механизмом построения запросов, который обеспечивает возможность генерировать запросы от нашего имени, используя соглашения об именах методов:
public interface StoreRepository extends JpaRepository {
List findStoreByLocationId(Long locationId);
}
Таким образом основное понятие в Spring Data
— это репозиторий. Это несколько интерфейсов которые используют JPA Entity
для взаимодействия с ней.
Так например интерфейс
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID>
обеспечивает основные операции по поиску, сохранения, удалению данных (CRUD операции)
T save(T entity);
Optional findById(ID primaryKey);
void delete(T entity);
Есть и другие абстракции, например PagingAndSortingRepository
.
Пользовательские репозитории
При необходимости мы можем обогатить наш репозиторий моделей, написав интерфейс фрагмента и реализовав желаемую функциональность.
Затем это может быть введено в наш собственный репозиторий JPA
.
Например, здесь обогащаем наш Репозиторий типов элементов путем расширения репозитория фрагментов:
public interface ItemTypeRepository
extends JpaRepository, CustomItemTypeRepository {
}
Здесь CustomItemTypeRepository
это другой интерфейс:
public interface CustomItemTypeRepository {
void deleteCustomById(ItemType entity);
}
Его реализация может быть хранилищем любого типа, а не только JPA:
public class CustomItemTypeRepositoryImpl implements CustomItemTypeRepository {
@Autowired
private EntityManager entityManager;
@Override
public void deleteCustomById(ItemType itemType) {
entityManager.remove(itemType);
}
}
Необходимо убедиться, что у него есть постфикс Impl
.
Однако мы можем установить пользовательский постфикс, используя аннотацию:
@EnableJpaRepositories(
basePackages = "com.baeldung.repository", repositoryImplementationPostfix = "CustomImpl")
Создание Репозиториев с использованием нескольких фрагментов
Расширение интерфейсов репозитория только с помощью одной пользовательской реализации - это было ограничение, из-за которого пришлось бы объединить все связанные функции в один объект. Для более крупных проектов со сложными моделями предметной области это приводит к раздутым классам.
Теперь, с выходом Spring
5, у нас есть возможность обогатить наш репозиторий JPA
несколькими репозиториями фрагментов. Опять же, остается требование, чтобы у нас были эти фрагменты в виде пар интерфейс-реализация.
Чтобы продемонстрировать это, создадим два фрагмента:
public interface CustomItemTypeRepository {
void deleteCustom(ItemType entity);
void findThenDelete(Long id);
}
public interface CustomItemRepository {
Item findItemById(Long id);
void deleteCustom(Item entity);
void findThenDelete(Long id);
}
Конечно, нужно было бы написать их реализации.
Но вместо того, чтобы подключать эти пользовательские репозитории – со связанными функциями – в их собственные репозитории JPA
, возможно расширить функциональность одного репозитория JPA
:
public interface ItemTypeRepository
extends JpaRepository, CustomItemTypeRepository, CustomItemRepository {
}
Теперь у нас будет вся связанная функциональность в одном репозитории.
Работа с двусмысленностью
Поскольку мы наследуем от нескольких репозиториев, у нас могут возникнуть проблемы с определением того, какая из наших реализаций будет использоваться в случае столкновения.
Например, в нашем примере оба хранилища фрагментов имеют метод find Then Delete ()
с одинаковой сигнатурой.
В этом сценарии порядок объявления интерфейсов используется для устранения неоднозначности. Следовательно, в нашем случае метод внутри Репозитория пользовательских типов элементов будет использоваться с момента его объявления первым.
Мы можем проверить это с помощью этого тестового случая:
@Test
public void givenItemAndItemTypeWhenDeleteThenItemTypeDeleted() {
Optional itemType = composedRepository.findById(1L);
assertTrue(itemType.isPresent());
Item item = composedRepository.findItemById(2L);
assertNotNull(item);
composedRepository.findThenDelete(1L);
Optional sameItemType = composedRepository.findById(1L);
assertFalse(sameItemType.isPresent());
Item sameItem = composedRepository.findItemById(2L);
assertNotNull(sameItem);
}
@Test
public void givenItemAndItemTypeWhenDeleteThenItemTypeDeleted() {
Optional itemType = composedRepository.findById(1L);
assertTrue(itemType.isPresent());
Item item = composedRepository.findItemById(2L);
assertNotNull(item);
composedRepository.findThenDelete(1L);
Optional sameItemType = composedRepository.findById(1L);
assertFalse(sameItemType.isPresent());
Item sameItem = composedRepository.findItemById(2L);
assertNotNull(sameItem);
}
Напомним, что Spring Data JPA
- это удобный механизм для взаимодействия с сущностями базы данных, организации их в репозитории, извлечение данных, изменение.
Т.е. если того перечня что предоставляет интерфейс достаточно для взаимодействия с сущностью, то можно прямо расширить базовый интерфейс для своей сущности, дополнить его своими методами запросов и выполнять операции.
Рассмотрим шаги, которые нужны для самого простого случая (не отвлекаясь пока на конфигурации, ORM, базу данных).
- Создать сущность
@Entity
@Table(name = "EMPLOYEES")
public class Employees {
private Long employeeId;
private String firstName;
private String lastName;
private String email;
// . . .
- Наследоваться от одного из интерфейсов
Spring Data
, например отCrudRepository
@Repository
public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>
- Использовать в клиенте (сервисе) новый интерфейс для операций с данными
@Service
public class EmployeesDataService {
@Autowired
private CustomizedEmployeesCrudRepository employeesCrudRepository;
@Transactional
public void testEmployeesCrudRepository() {
Optional<Employees> employeesOptional = employeesCrudRepository.findById(127L);
//....
}
Воспользуемся готовым методом findById
.
Без имплементации, получим готовый перечень операций из CrudRepository
:
S save(S var1);
Iterable<S> saveAll(Iterable<S> var1);
Optional<T> findById(ID var1);
boolean existsById(ID var1);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> var1);
long count();
void deleteById(ID var1);
void delete(T var1);
void deleteAll(Iterable<? extends T> var1);
void deleteAll();
Понятно что этого перечня, скорее всего не хватит для взаимодействия с сущностью, и тут можно расширить свой интерфейс дополнительными методами запросов.
2. Методы запросов из имени метода
Запросы к сущности можно строить прямо из имени метода.
Для этого используется механизм префиксов find…By, read…By, query…By, count…By, и get…By, далее от префикса метода начинает разбор остальной части. Вводное предложение может содержать дополнительные выражения, например, Distinct. Далее первый By действует как разделитель, чтобы указать начало фактических критериев. Можно определить условия для свойств сущностей и объединить их с помощью And и Or. Примеры
@Repository
public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> {
// искать по полям firstName And LastName
Optional<Employees> findByFirstNameAndLastName(String firstName, String lastName);
// найти первые 5 по FirstName начинающихся с символов и сортировать по FirstName
List<Employees> findFirst5ByFirstNameStartsWithOrderByFirstName(String firstNameStartsWith);
В документации определен весь перечень, и правила написания метода.
В качестве результата могут быть сущность T
, Optional
, List
, Stream
.
В среде разработки, например в Idea
, есть подсказка для написания методов запросов.
Достаточно только определить подобным образом метод, без имплементации и Spring
подготовит запрос к сущности.
@SpringBootTest
public class DemoSpringDataApplicationTests {
@Autowired
private CustomizedEmployeesCrudRepository employeesCrudRepository;
@Test
@Transactional
public void testFindByFirstNameAndLastName() {
Optional<Employees> employeesOptional = employeesCrudRepository.findByFirstNameAndLastName("Alex", "Ivanov");
3. Конфигурация и настройка
Здесь лишь коснусь некоторых особенностей.
В context.xml
определенны бины transactionManager
, dataSource
и entityManagerFactory
.
Важно указать в нем также
<jpa:repositories base-package="com.example.demoSpringData.repositories"/>
путь где определены репозитории.
EntityManagerFactory
настроен на работу с Hibernate ORM
, а он в свою очередь с БД Oracle XE
, тут возможны и другие варианты, в context.xml
все это видно.
В pom
файле есть все зависимости.
4. Специальная обработка параметров
В методах запросов, в их параметрах можно использовать специальные параметры Pageable
, Sort
, а также ограничения Top
и First
.
Например вот так можно взять вторую страницу (индекс с -0), размером в три элемента и сортировкой по firstName
, предварительно указав в методе репозитория параметр Pageable
, также будут использованы критерии из имени метода — "Искать по FirstName начиная с % „
@Repository
public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long> {
List<Employees> findByFirstNameStartsWith(String firstNameStartsWith, Pageable page);
//....
}
// пример вызова
@Test
@Transactional
public void testFindByFirstNameStartsWithOrderByFirstNamePage() {
List<Employees> list = employeesCrudRepository
.findByFirstNameStartsWith("A", PageRequest.of(1,3, Sort.by("firstName")));
list.forEach(e -> System.out.println(e.getFirstName() + " " +e.getLastName()));
}
5. Пользовательские реализации для репозитория
Предположим что в репозитории нужен метод, который не получается описать именем метода, тогда можно реализовать с помощью своего интерфейса и класса его имплементирующего. Добавим в репозиторий метод получения сотрудников с максимальной оплатой труда.
Объявляю интерфейс
public interface CustomizedEmployees<T> {
List<T> getEmployeesMaxSalary();
}
Имплементирую интерфейс. С помощью HQL (SQL)
получаю сотрудников с максимальной оплатой, возможны и другие реализации.
public class CustomizedEmployeesImpl implements CustomizedEmployees {
@PersistenceContext
private EntityManager em;
@Override
public List getEmployeesMaxSalary() {
return em.createQuery("from Employees where salary = (select max(salary) from Employees )", Employees.class)
.getResultList();
}
}
А также расширяю Crud Repository Employees
еще и CustomizedEmployees
.
@Repository
public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees>
Здесь есть одна важная особенность. Класс имплементирующий интерфейс, должен заканчиваться (postfix
) на Impl
, или в конфигурации надо поставить свой postfix
<repositories base-package="com.repository" repository-impl-postfix="MyPostfix" />
Проверяем работу этого метода через репозиторий
public class DemoSpringDataApplicationTests {
@Autowired
private CustomizedEmployeesCrudRepository employeesCrudRepository;
@Test
@Transactional
public void testMaxSalaryEmployees() {
List<Employees> employees = employeesCrudRepository.getEmployeesMaxSalary();
employees.stream()
.forEach(e -> System.out.println(e.getFirstName() + " " + e.getLastName() + " " + e.getSalary()));
}
Другой случай, когда необходимо изменить поведение уже существующего метода в интерфейсе Spring
, например delete
в CrudRepository
, необходимо чтобы вместо удаления из БД, выставлялся признак удаления. Техника точно такая же.
public interface CustomizedEmployees<T> {
void delete(T entity);
// ...
}
// Имплементация CustomizedEmployees
public class CustomizedEmployeesImpl implements CustomizedEmployees {
@PersistenceContext
private EntityManager em;
@Transactional
@Override
public void delete(Object entity) {
Employees employees = (Employees) entity;
employees.setDeleted(true);
em.persist(employees);
}
Теперь если в employeesCrudRepository
вызвать delete
, то объект будет только помечен как удаленный.
6. Пользовательский базовый репозиторий
В предыдущем примере показано как переопределить delete
в Crud
репозитории сущности, но если это надо делать для всех сущностей проекта, делать для каждой свой интерфейс нерационально, тогда в Spring data
можно настроить свой базовый репозиторий.
Для этого:
Объявляется интерфейс и в нем метод для переопределения (или общий для всех сущностей проекта).
Тут я еще для своих сущностей вводим свой интерфейс BaseEntity
(это не обязательно), для удобства вызова общих методов, его методы совпадают с методами сущности.
public interface BaseEntity {
Boolean getDeleted();
void setDeleted(Boolean deleted);
}
// Сущность Employees
@Entity
@Table(name = "EMPLOYEES")
public class Employees implements BaseEntity {
private Boolean deleted;
@Override
public Boolean getDeleted() {
return deleted;
}
@Override
public void setDeleted(Boolean deleted) {
this.deleted = deleted;
}
// Базовый пользовательский интерфейс
@NoRepositoryBean
public interface BaseRepository <T extends BaseEntity, ID extends Serializable>
extends JpaRepository<T, ID> {
void delete(T entity);
}
//Базовый пользовательский класс имплементирующий BaseRepository
public class BaseRepositoryImpl <T extends BaseEntity, ID extends Serializable>
extends SimpleJpaRepository<T, ID>
implements BaseRepository<T, ID> {
private final EntityManager entityManager;
public BaseRepositoryImpl(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
super(entityInformation, entityManager);
this.entityManager = entityManager;
}
@Transactional
@Override
public void delete(BaseEntity entity) {
entity.setDeleted(true);
entityManager.persist(entity);
}
}
В конфигурации надо указать этот базовый репозиторий, он будет общий для всех репозиториев проекта
<jpa:repositories base-package="com.example.demoSpringData.repositories"
base-class="com.example.demoSpringData.BaseRepositoryImpl"/>
Теперь Employees Repository
(и др.) надо расширять от BaseRepository
и уже его использовать в клиенте.
public interface EmployeesBaseRepository extends BaseRepository <Employees, Long> {
// ...
}
Проверим работу EmployeesBaseRepository
public class DemoSpringDataApplicationTests {
@Resource
private EmployeesBaseRepository employeesBaseRepository;
@Test
@Transactional
@Commit
public void testBaseRepository() {
Employees employees = new Employees();
employees.setLastName("Ivanov");
// Query by Example (QBE)
Example<Employees> example = Example.of(employees);
Optional<Employees> employeesOptional = employeesBaseRepository.findOne(example);
employeesOptional.ifPresent(employeesBaseRepository::delete);
}
Теперь также как и ранее, объект будет помечен как удаленный, и это будет выполняться для всех сущностей, которые расширяют интерфейс BaseRepository
.
В примере был применен метод поиска — Query by Example (QBE)
.
7. Методы запросов — Query
Если нужен специфичный метод или его реализация, которую нельзя описать через имя метода, то это можно сделать через некоторый Customized
интерфейс (CustomizedEmployees
) и сделать реализацию вычисления.
А можно пойти другим путем, через указание запроса (HQL
или SQL
), как вычислить данную функцию.
Для примера c getEmployeesMaxSalary
, этот вариант реализации даже проще. Усложним его входным параметром salary
. Т.е. достаточно объявить в интерфейсе метод и запрос вычисления.
@Repository
public interface CustomizedEmployeesCrudRepository extends CrudRepository<Employees, Long>, CustomizedEmployees<Employees> {
@Query("select e from Employees e where e.salary > :salary")
List<Employees> findEmployeesWithMoreThanSalary(@Param("salary") Long salary, Sort sort);
// ...
}
Проверяем
@Test
@Transactional
public void testFindEmployeesWithMoreThanSalary() {
List<Employees> employees = employeesCrudRepository.findEmployeesWithMoreThanSalary(10000L, Sort.by("lastName"));
Упомяну лишь еще, что запросы могут быть и модифицирующие, для этого к ним добавляется еще аннотация @Modifying
@Modifying
@Query("update Employees e set e.firstName = ?1 where e.employeeId = ?2")
int setFirstnameFor(String firstName, String employeeId);
Еще одной из замечательных возможностей Query
аннотации — это подстановка типа домена сущности в запрос по шаблону #{#entityName}
, через SpEL
выражения.
Так например в моем гипотетическом примере, когда необходимо для всех сущностей иметь признак "удален", создадим базовый интерфейс с методом получения списка объектов с признаком "удален" или "активный".
@NoRepositoryBean
public interface ParentEntityRepository<T> extends Repository<T, Long> {
@Query("select t from #{#entityName} t where t.deleted = ?1")
List<T> findMarked(Boolean deleted);
}
Далее все репозитории для сущностей можно расширять от него.
Интерфейсы которые не являются репозиториями, но находятся в "base-package" папке конфигурации, надо аннотировать @NoRepositoryBean
.
Репозиторий Employees
@Repository
public interface EmployeesEntityRepository extends ParentEntityRepository <Employees> {
}
Теперь когда будет выполняться запрос, в тело запроса будет подставлено имя сущности T для конкретного репозитория который будет расширять ParentEntityRepository
, в данном случае Employees
.
Проверка
@SpringBootTest
public class DemoSpringDataApplicationTests {
@Autowired
private EmployeesEntityRepository employeesEntityRepository;
@Test
@Transactional
public void testEntityName() {
List<Employees> employeesMarked = employeesEntityRepository.findMarked(true);
// ...
Преимущества использования:
Spring упрощает выполнение операций с базами данных над объектами нашего домена без написания большого количества кода или даже SQL
-запросов.
Операции CRUD
(создание, чтение, обновление, удаление) — это аббревиатура, обозначающая четыре функции, которые мы используем для реализации приложений постоянного хранения и приложений реляционных баз данных, включая Oracle Database.
CRUD
постоянно используется для всего, что связано с базами данных и проектированием баз данных.
Например, при разработке веб-сайтов используется REST
(передача репрезентативного состояния), который является надмножеством CRUD
, используемого для ресурсов HTTP
.
С другой стороны, CRUD
не менее важен для конечных пользователей.
Без него такие вещи, как регистрация на веб-сайтах, создание блогов или закладок, были бы невозможны.
Большинство приложений, которые мы используем, позволяют нам добавлять или создавать новые записи, искать существующие, вносить в них изменения или удалять их.
CRUD предлагает следующие преимущества:
- Облегчает контроль безопасности, удовлетворяя различные требования доступа.
- Упрощает разработку приложений, делая их более масштабируемыми.
- Имеет лучшую производительность по сравнению со специальными операторами
SQL
.
CREATE
Create
позволяет добавлять новые строки в вашу таблицу.
Возможно сделать это с помощью команды INSERT INTO
.
Команда начинается с INSERT INTO
ключевого слова, за которым следует имя таблицы, имена столбцов и значения, которые нужно вставить.
При использовании у INSERT INTO
вас есть два варианта:
INSERT INTO table_name
VALUES (value1, value2, value3, ...);
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
В приведенном ниже примере мы добавим данные в нашу таблицу пекарни.
INSERT INTO menu
VALUES (1, 'croissant', 1, '2020-12-16');
If we want to add multiple rows, we do that using:
INSERT INTO menu
VALUES
(2, 'bread', 3, '2020-12-16' ),
(3, 'eclairs', 2, '2020-12-16' );
Это добавит новые строки в таблицу меню, и каждая запись будет иметь уникальный id.
READ
Функция чтения похожа на функцию поиска, поскольку позволяет извлекать определенные записи и считывать их значения.
Читать относится к SELECT
Например, давайте посмотрим на товары, которые мы продаем в нашей пекарне. Для этого мы должны отобразить все данные в нашей таблице меню, используя:
SELECT * FROM menu;
Это не внесет никаких изменений в таблицу меню, а просто отобразит все записи в этой таблице.
Взгляните на этот пример, чтобы увидеть, как SELECT
извлекаются желаемые данные:
IF OBJECT_ID('cusp_CustomerRead') IS NOT NULL
BEGIN
DROP PROC cusp_CustomerRead
END
GO
CREATE PROC cusp_CustomerRead
@CustomerID int
AS
BEGIN
SELECT CustomerID, FirstName, LastName, Email, PhoneNumber
FROM Customer
WHERE (CustomerID = @CustomerID)
END
GO
UPDATE
Обновление — это то, как мы изменяем существующую запись в таблице.
Мы можем использовать это для изменения существующих записей в базе данных.
При выполнении UPDATE
вам необходимо определить целевую таблицу и столбцы, которые необходимо обновить.
Вам также понадобятся связанные значения, а иногда и строки.
Рекомендуется ограничить количество строк, так как это помогает избежать проблем с параллелизмом.
Чтобы обновить существующую запись, используйте следующее:
UPDATE table_name
SET column1 = value1, column2 = value2, ...
WHERE condition;
Допустим, мы хотим обновить название и цену товара. Мы бы использовали:
UPDATE menu
SET item_name = 'chocolate croissant', price = 2.5
WHERE item_id = 1;
Это обновит таблицу, так что предыдущая запись с id 1теперь будет заменена шоколадным круассаном с price 2.5.
DELETE
Удалить используется для удаления записи из таблицы.
SQL
и имеет встроенную функцию удаления для одновременного удаления одной или нескольких записей из базы данных.
Некоторые приложения реляционных баз данных могут разрешать жесткое удаление (безвозвратное удаление) или мягкое удаление (обновление статуса строки).
Команда удаления выглядит следующим образом:
DELETE FROM table_name WHERE condition;
Если мы хотим удалить один элемент из таблицы, мы используем:
DELETE FROM menu WHERE item_name='bread';
Это приведет к удалению строки с хлебным предметом из таблицы. Если вы хотите удалить все записи из таблицы, вы можете использовать:
DELETE FROM menu;
#Список-литературы/курсов