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 и оба с разными привилегиями
Сценарий входа / аутентификации:
- Вход в систему с использованием аутентификации на основе формы (имя пользователя и пароль)
- Создайте EntityManageFactory с использованием модуля персистентности "loginPU" и "jdbc / loginDataSource"
- создать запрос для получения роли пользователя
- если роль пользователя - admin, подключитесь с использованием источника данных "jdbc/admin"
- если пользовательская роль - персонал, подключитесь с использованием источника данных "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, надеясь соединить пользователей, используя имя модуля персистентности в зависимости от роли, но при развертывании на сервере это выдает ошибку.
Я читал об управляемой приложением персистентности и управляемой контейнером, я думаю, что я пытаюсь достичь использования управляемой приложениями, но не уверен, как это сделать.
Если я хочу использовать персистентность, управляемую контейнером, возможно ли использовать несколько источников данных? Любое предложение с благодарностью.
Спасибо за любые комментарии или предложения заранее.
[Решено]
Сначала я определил свой файл 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>
Я не использую @PersistenceUnit или @PersistenceContext в своих сессионных компонентах (я использую NetBeans, и эти компоненты были созданы при создании страниц JSF из классов сущностей).
Во всех сессионных компонентах они выглядят так:
@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); } }
Сценарий входа в систему выше (5 элементов) стал 7:
- Вход в систему с использованием аутентификации на основе формы (имя пользователя и пароль)
- Создайте EntityManageFactory с использованием модуля персистентности "loginPU" и "jdbc / loginDataSource"
- создать запрос для получения роли пользователя
- если роль пользователя - admin, подключитесь с использованием источника данных "jdbc/admin"
- если пользовательская роль - персонал, подключитесь с использованием источника данных "jdbc/staff"
плюс
- удалить или очистить EntityManagerFactory, созданный в элементе 2, используя emf.close();
- Сохраните новый 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