JPA - 使用多个数据源来定义访问控制

时间:2012-06-27 02:47:49

标签: jpa glassfish eclipselink persistence-unit

我是JPA和JSF的新手,希望你能帮助我解决我的问题。 我的应用程序是使用JSF 2.0 Framework构建的,使用在Glassfish 3 +,MySQL上运行的JPA 2.0 / EclipseLink。

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

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

登录/身份验证方案是:

  1. 使用基于表单的身份验证(用户名和密码)进行用户登录
  2. 使用持久性单元“loginPU”和“jdbc / loginDataSource”创建EntityManageFactory
  3. 创建查询以检索用户角色
  4. 如果用户角色为admin,则使用“jdbc / admin”数据源进行连接
  5. 如果用户角色是职员,请使用“jdbc / staff”数据源进行连接
  6. 我上面第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,我试图使用带有unitName的@PersistenceContext而没有unitName但没有运气

    @PersistenceContext
    private EntityManager em;
    

    我尝试在persistence.xml中使用多个持久性单元,希望根据角色使用持久性单元名称连接用户,但是在部署到服务器时会出错。

    我读到application-managed persistencecontainer-managed,我认为我想要实现的是使用应用程序管理,但不知道该怎么做。

    如果我要使用容器管理的持久性,是否可以使用多个数据源?任何建议都非常感谢。

    提前感谢您提出任何意见或建议。

    [解决]

    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:

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

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

1 个答案:

答案 0 :(得分:0)

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

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

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

请参阅, http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing