Ревью 2 теория. Инструкция по созданию бизнесобъектов. Strategy это поведенческий паттерн, выносит набор алгоритмов в собственные классы и делает их взаимозаменимыми
Скачать 0.74 Mb.
|
21. Транзакции в Spring?Spring поддерживает два типа управления транзакциями: 1. Программное управление транзакциями — когда разработчик должен сам управлять транзакциями. 2. Декларативное управление транзакциями — означает отделение управления транзакциями от бизнес-логики. Разработчик использует только аннотации в конфигурации на основе XML для управления транзакциями. Spring создает proxy для классов, объявленных аннотацией @Transactional. Proxy в большинстве случаев невидим во время выполнения. Он предоставляет способ для Spring вводить поведение «до», «после» или «во время» вызовов методов в proxy-объект. Поэтому, когда метод помечен аннотацией @Transactional, Spring динамически создает proxy. Когда клиенты совершают вызовы в наш объект, вызовы перехватываются, а поведение будет вводиться через механизм proxy. Когда Spring загружает определения бина и настроен на поиск аннотаций @Transactional, он создаст эти proxy-объекты вокруг нашего бина. Эти proxy-объекты являются экземплярами классов, которые будут автоматически генерироваться во время выполнения. Поведение этих proxy-объектов по умолчанию при вызове метода — это просто вызвать тот же метод в «target» бин (т.е. наш бин). Proxy также могут быть снабжены «перехватчиками» (Interceptor), и, когда они присутствуют, эти “перехватчики” будут вызываться proxy-сервером до того, как он вызовет наш целевой метод бина. Для целевого бина, аннотированного с помощью @Transactional, Spring создаст TransactionInterceptor и передаст его созданному proxy-объекту. Поэтому, когда мы вызываем метод из клиентского кода, мы вызываем метод на proxy-объекте, который сначала вызывает TransactionInterceptor (который начинает транзакцию), который, в свою очередь, вызывает метод в нашем целевом бине. Когда вызов завершается, TransactionInterceptor принимает и завершает/откатывает транзакцию. Обычно управление транзакциями происходит в service слое приложения. Начиная с версии 3.1 Spring ввел аннотацию @EnableTransactionManagement, которая используется с аннотацией @Configuration над классами и включает поддержку транзакций. Транзакционная модель: Транзакционная модель функционирует на уровне транзакций. В рамках одного соединения может быть много транзакций. От одного пользователя может быть много одновременных и независимых соединений, а также конкурентных транзакций. Если взять за основу такие известные реляционные базы как MySQL и PostgreSQL — одно соединение одновременно держать две разные транзакции открытыми не может, т.к. одно соединение — только одна открытая транзакция. Нет возможности в рамках одного соединения выполнять одновременно несколько команд. Они предоставляют неблокирующий вызов, но не дождавшись конца ответа новые запросы отправлять у не получится. Например, в MySQL каждый «thread», держит соединение. Он не отслеживает, каким процессом это соединение открыто, т.е. ему без разницы, один процесс открыл множество соединений или это множество процессов. MySQL выполняет запросы параллельно, в рамках «тредной модели», но существуют блокировки. Виды транзакционных моделей: 1. Local — голый JDBC 2. Programmatic — JPA 3. Declarative — Spring (когда ставим аннотацию). Что происходит внутри Spring при объявлении аннотации @Transactional: В Spring есть такое понятие как SpringDefaultNameConvension — именование бинов по умолчанию. По умолчанию Spring ищет есть ли у нас бин с именем TransactionManager. Если есть, то Spring его найдет и сам подключит, нам не надо его дополнительно настраивать. Но если у нас несколько TransactionManager, тогда мы должны указать явно. Дальше указываем дополнительные параметры, такие как уровни изоляции транзакций, свойство propagation и т.д. 1. @Transactional и объявлен TransactionManager – TransactionManager создает EntityManager, если он необходим и осуществляет старт новой транзакции. В зависимости от того, выполняется ли хоть одна транзакция в текущий момент или отсутствует параметр «propagation» (по умолчанию propagation = Propagation.REQUIRED) у метода, аннотированного @Transactional, создается новая транзакция. Алгоритм создания новой транзакции: 1. создается новый EntityManager — EntityManager привязывается к «текущему потоку Thread»; 2. берется соединение из пула соединений БД; 3. это соединение привязывается к «текущему потоку Thread» при помощи ThreadLocal (Класс ThreadLocal предоставляет локальные переменные потока. Каждый поток имеет свою собственную инициализированную копию переменной). Пример кода: @Configuration @EnableTransactionManagement public class Config { private final EntityManagerFactory factory; private final DataSource dataSource; @Autowired public Config(EntityManagerFactory factory, DataSource dataSource) { this.factory = factory; this.dataSource = dataSource; } @Bean(name = "transactionManager") public PlatformTransactionManager transactionManager() { JpaTransactionManager tm = new JpaTransactionManager(); tm.setEntityManagerFactory(factory); tm.setDataSource(dataSource); return tm; } } Аннотация @EnableTransactionManagement означает, что классы, помеченные @Transactional, должны быть обернуты аспектом транзакций. 2. Прописываем EntityManagerFactory если используем JPA, прописываем DataSource если JDBC и т.д. Пример кода: @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) { LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean(); localContainerEntityManagerFactoryBean.setDataSource(dataSource); localContainerEntityManagerFactoryBean.setPackagesToScan(environment.getRequiredProperty("db.entity.package")); JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); localContainerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter); localContainerEntityManagerFactoryBean.setJpaProperties(additionalProperties()); return localContainerEntityManagerFactoryBean; } Пример .xml конфигурации: class=«org.springframework.orm.jpa.JpaTransactionManager»> 3. Указываем в аннотации proxy-target-class = «true» или ставим тег Java Transaction API (JTA) – это API, для поддержки транзакций, входящее в стандарт серверной платформы для языка программирования Java – Jakarta EE. Определяет взаимодействие между менеджером транзакций и другими участниками распределенной транзакционной системы. Спецификация API разработана в рамках Java Community Process в качестве JSR 907. Обеспечивает разделение границ транзакции, а также API к стандарту X/Open XA, описывающему взаимодействие ресурсов в транзакциях. В архитектуре X/Open XA менеджер транзакций или монитор обработки транзакций координирует операции к множественным ресурсам, таким как базы данных. У каждого ресурса есть свой собственный менеджер. Менеджер ресурса, как правило, имеет собственный API для манипулирования ресурсом, например, для управления реляционными СУБД используются интерфейсы JDBC. Кроме того, менеджер ресурса взаимодействует с монитором обработки транзакций, для координации распределенных транзакций между собственным ресурсом и другим ресурсами, а также взаимодействует с монитором обработки транзакций для начала, перепоручения или отката транзакций. Для чего это нужно в Springconfig? Spring работает по принципу проксирования: 1. Для бинов он создает proxy; 2. Используется подход АОП для добавления какого-то поведения; 3.1. Spring начинает работать, выполнять свои классы и первый из них это AopAutoProxyConfigurer, который вызывает метод configureAutoProxyCreator(); 3.2. Потом создается класс TransactionInterceptor; 3.3. Далее Spring находит TransactionManager и подключает его к TransactionInterceptor; 3.4 Spring регистрирует TransactionInterceptor как бин. Аннотация @Transactional определяет область действия одной транзакции базы данных. Транзакция БД происходит внутри области действий persistence context. Persistence context в JPA является EntityManager, который использует внутри класс Session ORM-фреймворка Hibernate (если использовать Hibernate как persistence провайдер). Один объект EntityManager может быть использован несколькими транзакциями БД. |