【问题标题】:Can I set the schema before creating the EntityManager?我可以在创建 EntityManager 之前设置架构吗?
【发布时间】:2016-03-14 18:25:19
【问题描述】:

我需要使用具有不同属性的多重持久性单元(在我的例子中是 MySQL 和 Oracle 数据库)。在persistence.xml 中,我定义了两个不同的“persistence-unit”并只列出了那里的实体类。

可以在 persitence.xml 中设置属性

<properties> <property name="..." value="..." /> ...

我在创建 EntityManager 之前在 java 类中执行此操作,因为我必须使用不同的属性(我之前读过):

        EntityManagerFactory factory;
        ...
        HashMap<String, String> dbProperties = new HashMap<String, String>();
        dbProperties.put("javax.persistence.jdbc.driver", driver);
        dbProperties.put("javax.persistence.jdbc.url", url);
        dbProperties.put("javax.persistence.jdbc.user", user);
        dbProperties.put("javax.persistence.jdbc.password", password);
        dbProperties.put("eclipselink.ddl-generation", "none");
        dbProperties.put("eclipselink.ddl-generation.output-mode", "database");

        factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, dbProperties);
        EntityManager em = factory.createEntityManager();
        ...

对于 Oracle,我需要动态设置架构(如果可能),而不是在每个实体类的 @Table 注释中硬编码。

现在我使用的是一个常量(意味着它不是动态的)

@Table(name="MYTABLE", schema = Constants.ORACLE_SCHEMA)

我想用

@Table(name="MYTABLE")

并将架构设置为属性

dbProperties.put(...)

有这样的属性吗?

在我的搜索中,我发现了一种可以提供帮助的语法

ALTER SESSION SET CURRENT_SCHEMA=MYSCHEMA

但我不知道如何将它与EntityManager结合起来。

我已经询问了所有可用的属性here,但还没有找到任何东西。

提前谢谢你。

【问题讨论】:

    标签: java oracle jpa eclipselink entitymanager


    【解决方案1】:

    我在这篇文章的帮助下找到了解决方案:https://community.oracle.com/thread/2270534?tstart=0

    可以在 EntityManager 创建后通过查询来完成:

            ...
            EntityManager em = factory.createEntityManager();
            Query query;
    
            em.getTransaction().begin();
            query = em.createNativeQuery("ALTER SESSION SET CURRENT_SCHEMA="+schemaName);
            query.executeUpdate();
            em.getTransaction().commit();
    

    检查当前架构:

            query = em.createNativeQuery("SELECT SYS_CONTEXT('USERENV','SESSION_SCHEMA') FROM DUAL");
            System.out.println("Current schema: " + query.getResultList());
    

    【讨论】:

    • 您不能也将架构与用户绑定,然后根据您要使用的架构选择用户吗?
    • 也许这确实解决了这个问题,但是在 Tomcat 和 Weblogic 中有一个叫做“InitSql”的东西,它允许您在检查数据库连接后运行一些 SQL。然后解决方案是将模式绑定到 jdbc 池。希望对你有帮助
    • @Chris 您可以在每次需要更改架构时运行查询 ALTER SESSION SET CURRENT_SCHEMA(因为它在创建 EntityManager 后工作)或为每个用户创建不同的 EntityManager(?)。
    • @rjdkolb 感谢您的回复。我正在使用带有 EclipseLink 的独立 Java 程序。如果您有服务器(Tomcat/Weblogic 或其他)的示例/解决方案,我也将不胜感激。
    • @Andreas L. - 您可以对会话事件 stackoverflow.com/questions/15100698/… 执行相同的操作,并从应用程序中隐藏查询,但不应动态更改它,因为 JPA 维护缓存并执行在 entityManager 上的本地查询实际上取决于提供者如何使用和汇集这些连接的内部结构。如果将方案绑定到数据库中的用户,则无需更改连接上的模式,而是可以将用户指定为属性。
    【解决方案2】:

    我不确定这是否能解决您的问题,但一些应用服务器供应商可能会使用称为 InitSql 的东西。

    这是一个 SQL 语句,在每次成功建立数据库连接时都会运行。

    • 在 Weblogic 12c 中,这称为 InitSql
    • 在 Tomcat 7 中,这也称为 InitSql

    我在 Java SE 中找不到类似 EclipseLink 的东西,但也许有一个 post checkout SQL 可以像 InitSql 一样运行

    就像 Andreas L. 的回答一样,这可以让你运行类似的命令。

    ALTER SESSION SET CURRENT_SCHEMA=xxx
    

    【讨论】:

      猜你喜欢
      • 2019-01-28
      • 1970-01-01
      • 2014-09-12
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2012-07-22
      相关资源
      最近更新 更多