JPA - Использование нескольких источников данных для определения контроля доступа

Я совершенно новичок в JPA и JSF и надеюсь, что вы можете помочь мне с моими вопросами. Мое приложение построено с использованием JSF 2.0 Framework, с использованием JPA 2.0/EclipseLink, работающей на Glassfish 3+, MySQL.

Я установил один блок персистентности под названием "loginPU" с использованием источника данных: "jdbc/loginDataSource" "jdbc/loginDataSource" подключается к MySQL с помощью "login1" (определено в mysql, user таблица) и имеет доступ только к customer, user а также customer, roles таблицы, только с избранными привилегиями.

Я создал 2 других источника данных "jdbc/admin" и "jdbc/staff" в Glassfish JDBC Resources и оба с разными привилегиями

Сценарий входа / аутентификации:

  1. Вход в систему с использованием аутентификации на основе формы (имя пользователя и пароль)
  2. Создайте EntityManageFactory с использованием модуля персистентности "loginPU" и "jdbc / loginDataSource"
  3. создать запрос для получения роли пользователя
  4. если роль пользователя - admin, подключитесь с использованием источника данных "jdbc/admin"
  5. если пользовательская роль - персонал, подключитесь с использованием источника данных "jdbc/staff"

Мой код для пункта 2 выше выглядит так:

Map properties = new HashMap(); 
properties.put(TRANSACTION_TYPE, "JTA");

// Configure the internal EclipseLink connection pool
properties.put(JDBC_DRIVER, "com.mysql.jdbc.Driver");
properties.put(JDBC_URL, "jdbc:mysql://localhost:3306/customer");
properties.put(JDBC_USER, "login1");
properties.put(JDBC_PASSWORD, "login1");
properties.put(JTA_DATASOURCE, "jdbc/loginDataSource");

EntityManageFactory emf = Persistence.createEntityManagerFactory("loginPU",properties);

Я даже храню свой EntityManagerFactory в атрибутах сеанса и извлекаю его в классе JpaController

//save into session
session.setAttribute("entityManagerFactory", emf);

//retrieved in JpaController
public EntityManagerFactory getEmf() {

        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
        HttpSession s = request.getSession(true);
        try {
            emf = (EntityManagerFactory) s.getAttribute("entityManagerFactory");
        } catch(NullPointerException ne){
            System.out.println("EMF Exception: "+ne);
        }

        return emf;
    }

Вопросы: Как мне достичь 4 или 5? Это возможно сделать? Можно ли назначить какой-либо источник данных в блок персистентности "loginPU"? Мне удается установить соединение, используя loginPU и jdbc / loginDataSource, а затем соединиться, используя источник данных jdbc / admin, но когда я обращаюсь к другим объектам, он выдает ошибку и по умолчанию jdbc / loginDataSource

Примечание. Я использую классы JpaController, созданные сетевыми компонентами, а также сессионные компоненты для управления объектами. Мои классы JpaController используют

@Resource private UserTransaction utx;
@PersistenceUnit private EntityManagerFactory emf;

Все мои сессионные компоненты - @Stateless, я пытался использовать @PersistenceContext с unitName и без unitName, но безуспешно

@PersistenceContext
private EntityManager em;

Я попытался использовать несколько модулей персистентности в файле persistence.xml, надеясь соединить пользователей, используя имя модуля персистентности в зависимости от роли, но при развертывании на сервере это выдает ошибку.

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

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

Спасибо за любые комментарии или предложения заранее.

[Решено]

  1. Сначала я определил свой файл persistence.xml следующим образом:

    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="mdbAdminPU" >
            <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
            <jta-data-source>jdbc/login</jta-data-source>
            <exclude-unlisted-classes>false</exclude-unlisted-classes>
        </persistence-unit>
    </persistence>
    
  2. Я не использую @PersistenceUnit или @PersistenceContext в своих сессионных компонентах (я использую NetBeans, и эти компоненты были созданы при создании страниц JSF из классов сущностей).

  3. Во всех сессионных компонентах они выглядят так:

    @Stateless
    public class UserFacade extends AbstractFacade<User> {
    
        @Override
        protected EntityManager getEntityManager() {
            HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
            EntityManagerFactory emf = (EntityManagerFactory) session.getAttribute("entityManagerFactory");
            EntityManager em = emf.createEntityManager(); 
            return em;
        }
    
        public UserFacade() {
            super(User.class);
        }
    }
    
  4. Сценарий входа в систему выше (5 элементов) стал 7:

  1. Вход в систему с использованием аутентификации на основе формы (имя пользователя и пароль)
  2. Создайте EntityManageFactory с использованием модуля персистентности "loginPU" и "jdbc / loginDataSource"
  3. создать запрос для получения роли пользователя
  4. если роль пользователя - admin, подключитесь с использованием источника данных "jdbc/admin"
  5. если пользовательская роль - персонал, подключитесь с использованием источника данных "jdbc/staff"

плюс

  1. удалить или очистить EntityManagerFactory, созданный в элементе 2, используя emf.close();
  2. Сохраните новый EntityManagerFactory, созданный в элементе 4 или 5 в HttpSession

1 ответ

Решение

Вероятно, лучше всего использовать три отдельных модуля персистентности в вашем файле persistence.xml, если вам нужны три разных входа. Или просто введите один логин с полным доступом и подтвердите безопасность в своем приложении (что, по-видимому, в любом случае вы делаете частично).

Какую ошибку вы получили при развертывании?

Вы можете сделать это с помощью одного модуля персистентности в EclipseLink, но он более сложен, и вы не можете использовать менеджеры управляемых объектов контейнеров. Вы бы внедрили @PersistenceUnit (EntityManagerFactory) вместо @PersistenceContext (EntityManager), а затем вам нужно будет передать новые параметры входа в createEntityManager(). Вам необходимо установить для свойства "eclipselink.jdbc.exclusive-connection.mode" значение "Always" (или "Isolated" и сделать защищенные данные изолированными).

См. http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing

Другие вопросы по тегам