Что такое листенер в бд
Перейти к содержимому

Что такое листенер в бд

  • автор:

Что такое прослушиватель группы доступности?

Прослушиватель группы доступности ― это виртуальное сетевое имя (VNN), к которому могут подключаться клиенты, чтобы получить доступ к базе данных из первичной или вторичной реплики группы доступности Always On. Прослушиватель позволяет клиенту подключаться к реплике, не зная физического имени экземпляра SQL Server. Так как прослушиватель маршрутизирует трафик, строку подключения клиента не нужно изменять после отработки отказа.

Прослушиватель группы доступности состоит из службы доменных имен прослушивателя (DNS), обозначения порта прослушивателя, а также одного или нескольких IP-адресов. Для работы прослушивателя группы доступности поддерживается только протокол TCP. Имя DNS прослушивателя должно быть уникальным в домене и в NetBIOS. При создании прослушивателя он становится ресурсом кластера с соответствующим виртуальным сетевым именем (VNN), виртуальным IP-адресом (VIP) и зависимостью группы доступности. Клиент с помощью DNS разрешает VNN в несколько IP-адресов, а затем пытается подключаться по каждому адресу, пока запрос подключения не завершится успехом или не истечет время ожидания.

Если для одной или нескольких вторичных реплик для чтения настроена маршрутизация только для чтения, то клиентские соединения с прослушивателем с намерением чтения автоматически направляются во вторичную реплику для чтения.

В этой статье представлены общие сведения о прослушивателе группы доступности. Можно также настроить прослушиватель, а затем узнать, как подключиться к прослушивателю.

Параметры прослушивателя

Прослушиватель группы доступности использует следующие элементы:

Уникальное имя DNS
Оно известно также как имя виртуальной сети (VNN). Действуют правила именования Active Directory для DNS-имен узла. Дополнительные сведения см. в статье базы знаний Соглашения о наименовании в Active Directory для компьютеров, доменов, сайтов и подразделений .

Один или несколько виртуальных IP-адресов (VIP)
Виртуальные IP-адреса настраиваются для одной или нескольких подсетей, для которых группа доступности может выполнить отработку отказа.

Настройка IP-адресов
Для данного прослушивателя группы доступности IP-адрес может использовать протокол DHCP или один или несколько статических IP-адресов. Использование DHCP может привести к задержкам подключения во время отработки отказа, поэтому его не рекомендуется использовать в рабочих средах. Группы доступности, которые распространяются на несколько подсетей или используют конфигурации гибридной сети, должны использовать статический IP-адрес.

Порт прослушивателя

При настройке прослушивателя группы доступности необходимо назначить порт через SSMS. Для упрощения строки подключения клиента в качестве порта по умолчанию можно задать порт 1433. Это означает, что при использовании порта 1433 вам не понадобится включать номер порта в строку подключения приложения. Кроме того, поскольку каждый прослушиватель группы доступности будет иметь собственное имя виртуальной сети, каждый прослушиватель группы доступности, настроенный в одном кластере WSFC, может использовать один и тот же порт по умолчанию ― 1433.

Если для имен виртуальной сети прослушивателя группы доступности используется порт по умолчанию 1433, необходимо будет сделать так, чтобы никакая другая служба в узле кластера не использовала этот порт. В противном случае возникнет конфликт порта.

Если один из экземпляров SQL Server уже прослушивает TCP-порт 1433 через прослушиватель экземпляра и при этом на данном компьютере больше нет служб (включая дополнительные экземпляры SQL Server), прослушивающие порт 1433, это не приведет к конфликту порта с прослушивателем группы доступности. Обусловлено это тем, что прослушиватель группы доступности может совместно использовать один TCP-порт внутри одного процесса. Однако вы не должны настраивать несколько экземпляров SQL Server (параллельное использование) так, чтобы они прослушивали один порт, поскольку в этом случае одному из них не удастся прослушивать подключения.

Вы также можете назначить нестандартный порт прослушивателя группы доступности. Однако в этом случае при подключении к прослушивателю понадобится явно использовать целевой порт в строке подключения приложения. Кроме того, для этого порта придется создавать разрешение в брандмауэре.

Вы можете подключиться к прослушивателю, указав имя и порт (если не используется 1433). Таким портом может быть либо порт прослушивателя, либо базовый порт SQL Server, настроенный так, чтобы обеспечить прослушивание.

В следующих примерах демонстрируются некоторые функциональные возможности прослушивателя:

Настройка:

  • IP-адрес, прослушиваемый SQL Server: 192.168.20.2
  • Порт, который прослушивает SQL Server: 50254
  • Настроенный IP-адрес прослушивателя: 192.168.20.15
  • Настроенное имя прослушивателя: aglistener19
  • Настроенный порт прослушивателя: 50123
sqlcmd -S 192.168.20.15,50123 1> 
sqlcmd -S aglistener19 
sqlcmd -S aglistener19,50123 1> 
sqlcmd -S aglistener19,50254 1> 

Поведение клиентских подключений при отработке отказа

В случае отработки отказа группы доступности существующие постоянные подключения к группе доступности разрываются, при этом, чтобы продолжить работать с той же базой данных-источником или доступной только для чтения базой данных-получателем, клиент должен установить новое соединение. Пока на стороне сервера выполняется отработка отказа, связь с группой доступности может прерваться, что заставит клиентское приложение начать попытки установить новое подключение до тех пор, пока база данных-источник не будет переведена в режим «в сети».

Если группа доступности возвращается в режим «в сети» в то время, когда клиентское приложение пытается установить соединение, и до истечения времени ожидания подключения, то драйвер клиента может успешно выполнить одну из своих внутренних попыток установить соединение. В этом случае приложение не выдаст никакого сообщения об ошибке.

Дальнейшие действия

Теперь, когда вы знакомы с функциями прослушивателя группы доступности, создайте прослушиватель, а затем настройте приложение для подключения к прослушивателю. Вы также можете ознакомиться с различными стратегиями мониторинга группы доступности, чтобы обеспечить работоспособность группы доступности.

Дополнительные сведения о группах доступности см. в разделе Обзор групп доступности Always On (SQL Server).

Обратная связь

Были ли сведения на этой странице полезными?

Настройка сети (Настройка слущающего процесса Listener)

2 конфигурационных файла отвечают за подключение к Oracle.
Один обязательный (listener.ora) и один скорее для удобства, но для работы некоторых программ, он также может быть обязательным (tnsnames.ora).

По умолчанию файлы хранятся:

listener.ora

LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = hostname.domain.com)(PORT = "port_number")) ) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = SID1) (ORACLE_HOME = /u01/app/oracle/product/11.2) (SID_NAME = SID1) ) (SID_DESC = (GLOBAL_DBNAME = SID2) (ORACLE_HOME = /u01/app/oracle/product/11.2) (SID_NAME = SID2) ) ) 

tnsnames.ora

В данном файле описываются подробности подключения к базе данных. Т.о, становится возможным явно не указывать некоторые параметры. (Например, хост, порт и др.). И сразу обращаться по имени.

SID1 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = hostname.domain.com)(PORT = "port_number")) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = SID1) ) ) SID2 = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = hostname.domain.com)(PORT = "port_number")) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = SID2) ) ) 
// Должен работать (Но это не точно) $ tnsping SID2 

В следующем примере, происходит подключение к базе данных с использованием записи с именем orcl в файле tnsnames.ora.

Т.е. для подключения к базе, не приходится дополнительно вводить host, port, sid

tnsnames.ora

Основные команды службы слушателя (Listener):

$ lsnrctl status $ lsnrctl stop $ lsnrctl start $ lsnrctl restart 

Информация о Listener из командной строки:

$ ps -edf | grep tns root 13 2 0 Aug09 ? 00:00:00 [netns] oracle12 6604 1 0 Aug09 ? 00:00:02 /u01/oracle/grid/12.1/bin/tnslsnr LISTENER -no_crs_notify -inherit oracle12 16991 14456 0 09:26 pts/1 00:00:00 grep tns 
$ lsnrctl services LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 15-AUG-2015 15:09:04 Copyright (c) 1991, 2014, Oracle. All rights reserved. Connecting to (ADDRESS=(PROTOCOL=tcp)(HOST=)(PORT=1521)) Services Summary. Service "+ASM" has 1 instance(s). Instance "+ASM", status READY, has 1 handler(s) for this service. Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER Service "orcl12XDB" has 1 instance(s). Instance "orcl12", status READY, has 1 handler(s) for this service. Handler(s): "D000" established:0 refused:0 current:0 max:1022 state:ready DISPATCHER (ADDRESS=(PROTOCOL=tcp)(HOST=piter.localdomain)(PORT=60254)) Service "slave" has 1 instance(s). Instance "orcl12", status READY, has 1 handler(s) for this service. Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER Service "slave_DGB" has 1 instance(s). Instance "orcl12", status READY, has 1 handler(s) for this service. Handler(s): "DEDICATED" established:0 refused:0 state:ready LOCAL SERVER The command completed successfully 

Информация о Listener из консоли sqlplus:

SQL> show parameter local_listener; NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ local_listener string LISTENER_ORCL12 
SQL> show parameter listener NAME TYPE ------------------------------------ --------------------------------- VALUE ------------------------------ listener_networks string local_listener string remote_listener string 
SQL> alter system set local_listener='(DESCRIPTION =(ADDRESS = (PROTOCOL = TCP)(HOST = moscow.localdomain)(PORT = 1521)))' scope=both; 

OFFTOPIC Listener для grid

$ srvctl status listener Listener LISTENER is enabled Listener LISTENER is running on node(s): piter 
$ srvctl config listener Name: LISTENER Type: Database Listener Home: /u01/oracle/grid/12.1 End points: TCP:1521 Listener is enabled. 

Способ настроить tnsnames, предложенный в чате:

connect / as sysdba alter session set container=pdb_a; alter system register; 

После этого она зарегается в листенере, если до этого её не было.

В tnsnames.ora: (ip адрес только поправь)

pdb_a = (DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP) (HOST=10.1.1.14) (PORT=1521))) (CONNECT_DATA=(SERVICE_NAME=pdb_a))) 

Tags: Oracle Database, Network, Listener

Single DataGuard RAC

Oracle DBA

Собираем также материалы по: SQL & PL/SQL

Лучше потратить какое-то количество времени, чтобы записать успешный опыт, чем потом повторно воспроизводить его по памяти.

Все материалы обновляются по мере нахождения лучших практик и апгрейда знаний. Если будут желающие добавлять свои знания или исправлять ошибки и неточности, пишите в телеграм чате. Если будет учавствовать больше людей, качество материалов будет улучшаться и обновляться быстрее. Ссылки на ваши профили в соц. сетях будут добавлены в статьях, в которых вы учавствуете.

Подключение к прослушивателю группы доступности Always On

После настройки прослушивателя группы доступности необходимо обновить строку подключения для подключения к прослушивателю группы доступности Always On. Это приведет к автоматическому перенаправлению трафика из приложения в нужную реплику без необходимости вручную обновлять строку подключения после каждой отработки отказа.

Подключение в основной реплика

Чтобы подключиться к первичной реплике с доступом для чтения и записи, в строке подключения укажите DNS-имя прослушивателя группы доступности.

Например, чтобы подключиться к первичной реплике в SQL Server Management Studio через прослушиватель, введите DNS-имя прослушивателя в поле имени сервера:

Connect to listener in SSMS

Во время отработки отказа при изменении первичной реплики существующие подключения к прослушивателю прерываются, а новые соединения направляются в новую первичную реплику.

Пример простейшей строки соединения для поставщика данных ADO.NET (System.Data.SqlClient):

Server=tcp: AGListener,1433;Database=MyDB;Integrated Security=SSPI 

Вы можете проверить, к какой реплике в данный момент вы подключены через прослушиватель, выполнив следующую команду Transact-SQL (T-SQL):

SELECT @@SERVERNAME 

Например, если SQLVM1 — это первичная реплика:

Check replica connectivity

Вы по-прежнему можете подключаться непосредственно к экземпляру SQL Server, используя имя экземпляра первичной или вторичной реплики вместо использования прослушивателя группы доступности. Однако вы потеряете преимущество автоматического перенаправления новых подключений к новой текущей первичной реплике. Кроме того, вы потеряете преимущество маршрутизации только для чтения, при которой подключения, указанные с read-intent , автоматически направляются в доступную для чтения вторичную реплику.

Подключение к реплике только для чтения

Маршрутизация только для чтения означает автоматическую маршрутизацию входящих подключений к доступной для чтения вторичной реплике, которая поддерживает доступ только для чтения.

Подключения автоматически направляются в реплику только для чтения, если выполняются следующие условия:

  • Как минимум одна вторичная реплика устанавливается для доступа только для чтения, а первичная и все вторичные реплики только для чтения настраиваются для поддержки маршрутизации только для чтения.
  • Строка подключения ссылается на базу данных, относящуюся к группе доступности. Альтернативой является наличие базы данных, настроенной как базы данных по умолчанию, для имени входа, используемого при подключении. Дополнительные сведения см. в этой статье о работе алгоритма с маршрутизацией только для чтения.
  • В строке подключения указывается прослушиватель группы доступности, а в качестве намерения приложения входящего подключения задается доступ только для чтения (например, с помощью ключевого слова Application Intent=ReadOnly в строке подключения ODBC или OLEDB либо атрибутами или свойствами соединения).

Атрибут намерения приложения сохраняется в сеансе клиента во время входа в систему, после чего экземпляр SQL Server обрабатывает это назначение и определяет, что делать в соответствии с конфигурацией группы доступности, а также текущим состоянием чтения и записи целевой базы данных на вторичной реплике.

Например, чтобы подключиться к реплике только для чтения с помощью SQL Server Management Studio, выберите Параметры в диалоговом окне Подключение к серверу, выберите вкладку Дополнительные параметры подключения, а затем в текстовом поле укажите ApplicationIntent=ReadOnly :

Read only connection in SSMS

Пример строки подключения для поставщика ADO.NET (Systen.Data.SqlClient), обозначающий намерение приложения получить доступ только для чтения:

Server=tcp:AGListener;Database=AdventureWorks;Integrated Security=SSPI;ApplicationIntent=ReadOnly 

Порты не по умолчанию

При создании прослушивателя необходимо назначить порт, который будет использоваться прослушивателем. Если порт является портом по умолчанию 1433, то при подключении к прослушивателю не нужно указывать номер порта. Однако если это не порт 1433, он должен быть указан в строке подключения в формате listenername,port , например:

Connect with a non-default port

Пример строки подключения для поставщика ADO.NET (Systen.Data.SqlClient), указывающий порт не по умолчанию для прослушивателя:

Server=tcp:AGListener,1445;Database=AdventureWorks;Integrated Security=SSPI 

Обход прослушивателей

Хотя прослушиватели групп доступности обеспечивают поддержку перенаправления отработки отказа и маршрутизации только для чтения, клиентские подключения не обязательно должны использовать их. Клиентское подключение может обращаться непосредственно к экземпляру SQL Server, а не к прослушивателю группы доступности.

С точки зрения экземпляра SQL Server нет никакой разницы, использует соединение для входа в систему прослушиватель группы доступности или конечную точку другого экземпляра. Экземпляр SQL Server проверяет состояние целевой базы данных и разрешает или запрещает подключение, исходя из конфигурации группы доступности, а также текущего состояния базы данных на экземпляре. Например, если клиентское приложение подключается напрямую к порту экземпляра SQL Server, а затем соединяется с целевой базой данных, размещенной в группе доступности, при этом целевая база данных является базой данных-источником и находится в сети, связь будет успешно установлена. Если база данных-получатель не находится в сети или находится в переходном состоянии, связь с ней установить не удастся.

Кроме того, при миграции из базы данных зеркало в группы доступности AlwaysOn приложения могут указывать базу данных зеркало строка подключения, если существует только одна вторичная реплика, и она запрещает подключения пользователей.

Зеркало базы данных строка подключения

Если в группе доступности имеется только одна вторичная реплика и она настроена с помощью параметров ALLOW_CONNECTIONS = READ_ONLY или ALLOW_CONNECTIONS = NON для этой вторичной реплики, клиенты смогут подключаться к первичной реплике доступности с помощью строк подключения к зеркально отображаемой базе данных. Такой подход можно использовать при переносе существующего приложения с зеркально отображаемой базы данных в группу доступности при условии ограничения группы доступности до двух реплик доступности (одной первичной и одной вторичной). При добавлении дополнительных вторичных реплик потребуется создать прослушиватель группы доступности и обновить приложения так, чтобы они использовали DNS-имя прослушивателя группы доступности.

При использовании зеркало базы данных строка подключения клиент может использовать собственный клиент SQL Server или поставщик данных платформа .NET Framework для SQL Server. В строке подключения, предоставленной клиентом, должно быть как минимум указано имя экземпляра сервера, имя изначального участника, для определения экземпляра сервера, на котором первоначально размещалась реплика доступности, к которой необходимо подключиться. При необходимости строка подключения может также содержать имя другого экземпляра сервера, имя партнера по обеспечению отработки отказа, обозначающее экземпляр сервера, на котором первоначально размещалась вторичная реплика, в качестве имени участника отработки отказа.

Дополнительные сведения о строках подключения зеркального отображения баз данных см. в разделе Подключение клиентов к сеансу зеркального отображения базы данных (SQL Server).

Отработка отказа с несколькими подсетями

Если используются клиентские библиотеки, поддерживающие в строке подключения параметр подключения MultiSubnetFailover, то можно оптимизировать отработку отказа группы доступности в другую подсеть, задав для свойства MultiSubnetFailover значение True или Yes, в зависимости от синтаксиса используемого поставщика данных.

Этим параметром рекомендуется пользоваться для соединения с прослушивателем группы доступности как с одной, так и с несколькими подсетями, а также для имени экземпляра отказоустойчивого кластера SQL Server. При использовании этого параметра задействуется дополнительная оптимизация, даже при работе с одной подсетью.

Параметр подключения MultiSubnetFailover работает только с протоколом TCP и поддерживается только при подключении к прослушивателю группы доступности и любому имени виртуальной сети, подключаемому к SQL Server.

Вот пример подобной строки подключения (позволяющей выполнять отработку отказа в нескольких подсетях) для поставщика данных ADO.NET (System.Data.SqlClient):

Server=tcp:AGListener,1433;Database=AdventureWorks;Integrated Security=SSPI; MultiSubnetFailover=True 

Параметру подключения MultiSubnetFailover следует задать значение True , даже если группа доступности размещена только в одной подсети. Это позволяет настроить новых клиентов для обеспечения поддержки расширения в будущем без необходимости вносить какие-либо изменения в строки подключения клиентов, а также оптимизирует производительность отработки отказа при работе в одной подсети. Хотя параметр подключения MultiSubnetFailover не является обязательным, он обеспечивает повышение скорости отработки отказа в подсети. Обусловлено это тем, что драйвер клиента пытается открыть TCP-сокет для каждого IP-адреса, параллельно связанного с группой доступности. Драйвер клиента ждет ответа от первого IP-адреса с сообщением об успехе, а после его получения использует этот IP-адрес для подключения.

Прослушиватели и SSL-сертификаты

При подключении к прослушивателю группы доступности, если экземпляры-участники SQL Server используют TLS|SSL-сертификаты в сочетании с шифрованием сеанса, для обеспечения шифрования драйвер клиента, устанавливающего подключение, должен поддерживать альтернативное имя объекта (Subject Alternate Name) из TLS/SSL-сертификата.

Для каждого узла сервера-участника в отказоустойчивом кластере необходимо настроить сертификат X.509, задав список всех прослушивателей групп доступности, указанных в альтернативном имени объекта (Subject Alternate Name) сертификата.

Формат значений сертификата:

CN = Server.FQDN SAN = Server.FQDN,Listener1.FQDN,Listener2.FQDN 

Например, у вас есть следующий код:

Servername: Win2019 Instance: SQL2019 AG: AG2019 Listener: Listener2019 Domain: contoso.com (which is also the FQDN) 

Для WSFC с одной группой доступности сертификат должен иметь полное доменное имя (FQDN) сервера и FQDN прослушивателя:

CN: Win2019.contoso.com SAN: Win2019.contoso.com, Listener2019.contoso.com 

В такой конфигурации соединения будут шифроваться при подключении к экземпляру ( WIN2019\SQL2019 ) или прослушивателю ( Listener2019 ).

В зависимости от настройки сети существует небольшое число клиентов, которым может потребоваться добавить NetBIOS в сеть SAN. В этом случае значения сертификата должны быть:

CN: Win2019.contoso.com SAN: Win2019,Win2019.contoso.com,Listener2019,Listener2019.contoso.com 

Если WSFC имеет три прослушивателя группы доступности, например Прослушиватель1, Прослушиватель2, Прослушиватель3

Значения сертификата должны быть:

CN: Win2019.contoso.com SAN: Win2019.contoso.com,Listener1.contoso.com,Listener2.contoso.com,Listener3.contoso.com 

Прослушиватели и Kerberos (SPN)

Администратор домена должен настроить имя субъекта-службы (SPN) в Active Directory для каждого прослушивателя группы доступности, чтобы включить протокол Kerberos для клиентских подключений к прослушивателю. При регистрации имени субъекта-службы необходимо использовать учетную запись службы экземпляра сервера, на котором размещена реплика доступности. Для обеспечения работы SPN во всех репликах необходимо использовать одну учетную запись службы для всех экземпляров из кластера WSFC, на которых размещается группа доступности.

Для задания SPN используйте программу командной строки Windows setspn . Пример настройки SPN для прослушивателя группы доступности AG1listener.Adventure-Works.com , размещенной в наборе экземпляров SQL Server, работающих под учетной записью домена corp\svclogin2 :

setspn -A MSSQLSvc/AG1listener.Adventure-Works.com:1433 corp\svclogin2 

Дополнительные сведения о ручной регистрации SPN для SQL Server см. в разделе Регистрация имени участника-службы для соединений Kerberos.

Следующие шаги

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

Дополнительные сведения о группах доступности см. в разделе Обзор групп доступности Always On (SQL Server).

Обратная связь

Были ли сведения на этой странице полезными?

Что такое листенер в бд

Entity Listeners предназначены для реакции на события жизненного цикла экземпляров сущностей на уровне Middleware.

Слушатель представляет собой класс, реализующий один или несколько интерфейсов пакета com.haulmont.cuba.core.listener . Слушатель будет реагировать на события типов, соответствующих реализуемым интерфейсам.

BeforeDetachEntityListener

Метод onBeforeDetach() вызывается перед отделением объекта от EntityManager при коммите транзакции.

Данный слушатель можно использовать, например, для заполнения неперсистентных атрибутов сущности перед отправкой ее на клиентский уровень.

BeforeAttachEntityListener

Метод onBeforeAttach() вызывается перед введением объекта в персистентный контекст при выполнении операции EntityManager.merge() .

Данный слушатель можно использовать, например, для заполнения персистентных атрибутов сущности перед сохранением ее в базе данных.

BeforeInsertEntityListener

Метод onBeforeInsert() вызывается перед выполнением вставки записи в БД. В данном методе возможны любые операции с текущим EntityManager .

Метод onAfterInsert() вызывается после выполнения вставки записи в БД, но до коммита транзакции. В данном методе нельзя модифицировать текущий персистентный контекст, однако можно производить изменения в БД с помощью QueryRunner.

Метод onBeforeUpdate() вызывается перед изменением записи в БД. В данном методе возможны любые операции с текущим EntityManager .

Метод onAfterUpdate() вызывается после изменения записи в БД, но до коммита транзакции. В данном методе нельзя модифицировать текущий персистентный контекст, однако можно производить изменения в БД с помощью QueryRunner .

Метод onBeforeDelete() вызывается перед удалением записи из БД (или в случае мягкого удаления — перед изменением записи). В данном методе возможны любые операции с текущим EntityManager .

Метод onAfterDelete() вызывается после удаления записи из БД (или в случае мягкого удаления — после изменения записи), но до коммита транзакции. В данном методе нельзя модифицировать текущий персистентный контекст, однако можно производить изменения в БД с помощью QueryRunner .

Entity Listener должен являться Spring-бином, поэтому в нем можно использовать инжекцию в поля и сеттеры. Для всех экземпляров некоторого класса сущности создается один экземпляр слушателя определенного типа, поэтому слушатель не должен иметь изменяемого состояния.

Следует иметь в виду, что для BeforeInsertEntityListener фреймворк гарантирует managed state только для корневой сущности, принимаемой слушателем. Ее ссылки, встречающиеся в графе объектов, могут быть в состоянии detached. Поэтому если вам необходимо изменять эти объекты, используйте метод EntityManager.merge() , а если только иметь возможность обращаться к любым их атрибутам, то метод EntityManager.find() . Например:

package com.company.sample.listener; import com.company.sample.core.DiscountCalculator; import com.company.sample.entity.*; import com.haulmont.cuba.core.EntityManager; import com.haulmont.cuba.core.listener.*; import org.springframework.stereotype.Component; import javax.inject.Inject; import java.math.BigDecimal; @Component("sample_OrderEntityListener") public class OrderEntityListener implements BeforeInsertEntityListener, BeforeUpdateEntityListener, BeforeDeleteEntityListener < @Inject private DiscountCalculator discountCalculator; // a managed bean of the middle tier @Override public void onBeforeInsert(Order entity, EntityManager entityManager) < calculateDiscount(entity.getCustomer(), entityManager); >@Override public void onBeforeUpdate(Order entity, EntityManager entityManager) < calculateDiscount(entity.getCustomer(), entityManager); >@Override public void onBeforeDelete(Order entity, EntityManager entityManager) < calculateDiscount(entity.getCustomer(), entityManager); >private void calculateDiscount(Customer customer, EntityManager entityManager) < if (customer == null) return; // Delegate calculation to a managed bean of the middle tier BigDecimal discount = discountCalculator.calculateDiscount(customer.getId()); // Merge customer instance because it comes to onBeforeInsert as part of another // entity's object graph and can be detached Customer managedCustomer = entityManager.merge(customer); // Set the discount for the customer. It will be saved on transaction commit. managedCustomer.setDiscount(discount); > >

Все слушатели кроме BeforeAttachEntityListener выполняются внутри транзакции. Это значит, что если внутри слушателя выбрасывается исключение, текущая транзакция откатывается и все изменения в базе данных теряются.

Если вам необходимо выполнить некоторые действия после успешного завершения транзакции, используйте callback-интерфейс TransactionSynchronization фреймворка Spring для того чтобы отложить выполнение до нужной фазы транзакции. Например:

package com.company.sales.service; import com.company.sales.entity.Customer; import com.haulmont.cuba.core.EntityManager; import com.haulmont.cuba.core.listener.BeforeInsertEntityListener; import com.haulmont.cuba.core.listener.BeforeUpdateEntityListener; import org.springframework.stereotype.Component; import org.springframework.transaction.support.TransactionSynchronizationAdapter; import org.springframework.transaction.support.TransactionSynchronizationManager; @Component("sales_CustomerEntityListener") public class CustomerEntityListener implements BeforeInsertEntityListener, BeforeUpdateEntityListener < @Override public void onBeforeInsert(Customer entity, EntityManager entityManager) < printCustomer(entity); >@Override public void onBeforeUpdate(Customer entity, EntityManager entityManager) < printCustomer(entity); >private void printCustomer(Customer customer) < System.out.println("In transaction: " + customer); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() < @Override public void afterCommit() < System.out.println("After transaction commit: " + customer); > >); > >

Регистрация entity listeners

Entity Listener может быть задан двумя способами:

  • Статически — имена бинов слушателей указываются в аннотации @Listeners на классе сущности:
@Entity(. ) @Table(. ) @Listeners("sample_MyEntityListener") public class MyEntity extends StandardEntity
package com.company.sample.core; import com.haulmont.cuba.core.global.Events; import com.haulmont.cuba.core.sys.events.AppContextInitializedEvent; import com.haulmont.cuba.core.sys.listener.EntityListenerManager; import com.haulmont.cuba.security.entity.User; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import javax.inject.Inject; @Component("sample_AppLifecycle") public class AppLifecycle < @Inject private EntityListenerManager entityListenerManager; @EventListener(AppContextInitializedEvent.class) // notify after AppContext is initialized @Order(Events.LOWEST_PLATFORM_PRECEDENCE + 100) // run after all framework listeners public void initEntityListeners() < entityListenerManager.addListener(User.class, "sample_UserEntityListener"); > >

Если для сущности объявлены несколько слушателей одного типа (например, аннотациями класса сущности и его предков, плюс динамически), то их вызов будет выполняться в следующем порядке:

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *