我是JPA和JSF的新手,希望你能帮助我解决我的问题。我的应用程序是使用 JSF 2.0 框架构建的,使用 JPA 2.0/EclipseLink 运行在 Glassfish 3+, MySQL 上。
我使用数据源设置了一个名为"loginPU"的持久性单元:"jdbc/loginDataSource"jdbc/loginDataSource"使用"login1"(在mysql
中定义)连接到MySQL。user
表),并且只能访问customer
。user
和customer
.roles
表,仅具有选择权限。
我在 Glassfish JDBC Resources 中创建了另外 2 个数据源"jdbc/admin"和"jdbc/staff",两者都具有不同的权限
登录/身份验证方案为:
- 使用基于表单的身份验证(用户名和密码)进行用户登录
- 使用持久性单元"loginPU"和"jdbc/loginDataSource"创建实体管理工厂
- 创建查询以检索用户角色
- 如果用户角色为管理员,请使用"JDBC/管理员"数据源进行连接
- 如果用户角色为员工,请使用"JDBC/员工"数据源进行连接
上面第 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?有没有可能 男孩是否可以将任一数据源分配给"登录PU" 持久性单元?我设法使用 loginPU 和 jdbc/loginDataSource 建立连接 然后使用 JDBC/管理员数据源进行连接,但是当我访问其他 实体,它抛出错误并默认为 JDBC/login数据源
注意:我正在使用由netbeans创建的JpaController类,以及会话bean来管理实体。我的 JpaController 类使用
@Resource private UserTransaction utx;
@PersistenceUnit private EntityManagerFactory emf;
我的会话豆都是@Stateless的,我试图使用带有单位名称和没有单位名称的@PersistenceContext,但没有运气
@PersistenceContext
private EntityManager em;
我尝试在持久性.xml中使用多个持久性单元,希望根据角色使用持久性单元名称连接用户,但在部署到服务器时出错。
我读过有关应用程序管理的持久性和容器管理的持久性,我认为我想要实现的是使用应用程序管理的,但不确定如何做到这一点。
如果要使用容器管理的持久性,是否可以使用多个数据源?任何建议将不胜感激。
提前感谢您的任何意见或建议。
[已解决]
首先,我定义了我的坚持.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,这些 bean 是在我从实体类创建 JSF 页面时创建的)
在所有会话 bean 中,它们看起来像这样:
@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 项:
- 使用基于表单的身份验证(用户名和密码)进行用户登录
- 使用持久性单元"loginPU"和"jdbc/loginDataSource"创建实体管理工厂
- 创建查询以检索用户角色
- 如果用户角色为管理员,请使用"JDBC/管理员"数据源进行连接
- 如果用户角色为员工,请使用"JDBC/员工"数据源进行连接
加
- 删除或清除在项目 2 中创建的实体管理器工厂 emf.close();
- 保留在第 4 项或第 5 项中创建的新实体管理器工厂 HttpSession
三个不同的登录名.xml最好在持久性中使用三个单独的持久性单元。 或者只需一个具有完全访问权限的登录名,并验证应用程序中的安全性(无论如何,您似乎正在部分执行此操作)。
您在部署时遇到什么错误?
您可以在 EclipseLink 中使用一个持久性单元来执行此操作,但它涉及更多,并且不能使用容器管理的实体管理器。 您将注入一个@PersistenceUnit(EntityManagerFactory)而不是一个@PersistenceContext(EntityManager),然后您需要将新的登录参数传递给createEntityManager()。 您需要将"eclipselink.jdbc.exclusive-connection.mode"属性设置为"始终"(或"隔离"并使安全数据隔离)。
看http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing