Как вызвать dbms_application_info с помощью инъекции EntityManager

Мы создаем приложение Java EE / JPA / CDI с базой данных Oracle. Модель данных (которую мы не можем изменить) реализует безопасность частично с помощью представлений и client_info... что-то вроде...

create view the_view
as select * 
from the_table
where organization_id = USERENV('CLIENT_INFO')

где userenv('CLIENT_INFO') в основном устанавливается вызовом

dbms_application_info.set_client_info(11);

Итак, у нас есть ряд Stateless Beans, которые в основном используют Persistence Context и выполняют запросы (как собственные запросы, так и обычные POJO), и нам нужен способ ввести информацию о клиенте (которую мы можем получить из контекста безопасности) в PersistenceContext, прежде чем делать вызовы к EntityManager.

В двух словах, мне нужно иметь возможность вызывать следующее...

@PersistenceContext 
EntityManager em;

@Inject
UserInfo userInfo;

public TheView getTableData(long id) {
    // At this point security Information should be set.. 
    // Call the query
    return em.find(TheView.class, id);

}

без необходимости вызывать setClientInfo() вручную...

Одним из способов сделать это, вероятно, будет использование перехватчиков, аннотирование метода и вызов там (при условии, что я смогу получить PersistenceContext, который будет использовать метод. )... будет ли это вообще работать?

Есть ли другой способ сделать это?

TIA!

Решение

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

Я не уверен на 100%, правильно ли я понял ваши требования, но кажется, что было бы неплохо отделить логику авторизации от реальной бизнес-логики, чтобы иметь возможность написать что-то подобное:

...

@IsEditor("someMoreData")
public X getData() {
 ...
}

IsEditor является перехватчиком и будет инкапсулировать соответствующий поиск в БД.

Seam Security как независимые модули CDI поставляются с парой концепций (& реализаций), вы должны обязательно ознакомиться с ними.

Комментарии (1)

Если вы используете EclipseLink, здесь есть информация об использовании EclipseLink с Oracle VPD, которая кажется похожей.

В принципе, вы можете использовать события для выполнения вашего вызова.

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching/Shared_and_Isolated#Oracle_Virtual_Private_Database_.28VPD.29

Комментарии (1)