1

我对 JPA 和 JSF 完全陌生,希望您能帮助我解决我的问题。我的应用程序是使用 JSF 2.0 框架构建的,使用在 Glassfish 3+、MySQL 上运行的 JPA 2.0/EclipseLink。

我使用数据源设置了一个名为“loginPU”的持久性单元:“jdbc/loginDataSource”“jdbc/loginDataSource”使用“login1”(在 .table 中定义)连接到 MySQL,mysql并且user只能访问customer. usercustomerroles表,只有选择权限。

我在 Glassfish JDBC 资源中创建了 2 个其他数据源“jdbc/admin”和“jdbc/staff”,并且都具有不同的权限

登录/认证场景是:

  1. 使用基于表单的身份验证(用户名和密码)的用户登录
  2. 使用持久性单元“loginPU”和“jdbc/loginDataSource”创建 EntityManageFactory
  3. 创建查询以检索用户角色
  4. 如果用户角色是管理员,则使用“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

注意:我使用由 netbeans 创建的 JpaController 类,以及会话 bean 来管理实体。我的 JpaController 类使用

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

我的会话 bean 都是 @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. 我的会话 bean 中没有使用任何 @PersistenceUnit 或 @PersistenceContext。(我使用的是 Netbeans,这些 bean 是在我从实体类创建 JSF 页面时创建的)

  3. 在所有会话 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);
        }
    }
    
  4. 上面的登录场景(5项)变成了7个:

  1. 使用基于表单的身份验证(用户名和密码)的用户登录
  2. 使用持久性单元“loginPU”和“jdbc/loginDataSource”创建 EntityManageFactory
  3. 创建查询以检索用户角色
  4. 如果用户角色是管理员,则使用“jdbc/admin”数据源进行连接
  5. 如果用户角色是人员,则使用“jdbc/staff”数据源进行连接

  1. 使用 emf.close() 删除或清除在第 2 项中创建的 EntityManagerFactory;
  2. 保持在 HttpSession 的第 4 项或第 5 项中创建的新 EntityManagerFactory
4

1 回答 1

0

如果您需要三个不同的登录名,您最好在 persistence.xml 中使用三个独立的持久性单元。或者只需一个具有完全访问权限的登录并验证您的应用程序中的安全性(无论如何您似乎都在做部分工作)。

你在部署时遇到了什么错误?

您可以使用 EclipseLink 中的一个持久性单元来完成此操作,但涉及更多,并且您不能使用容器管理的实体管理器。您将注入一个@PersistenceUnit (EntityManagerFactory) 而不是@PersistenceContext (EntityManager),然后您需要将新的登录参数传递给createEntityManager()。您需要将“eclipselink.jdbc.exclusive-connection.mode”属性设置为“始终”(或“隔离”并使安全数据隔离)。

见, http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing

于 2012-06-27T12:37:27.457 回答