eclipselink中的动态模式选择

时间:2013-07-09 17:21:00

标签: jpa annotations eclipselink database-schema

我在项目中使用eclipselink和Oracle。

我正在使用基于注释的映射,如下所示。

@Entity
@Table(name="ASSIGNMENT", schema="service")
public class Assignment implements Serializable {
...
}

我有不同的模式,对应不同的国家/地区。表名是相同的。要求是在运行时选择模式名称。

是否可以使用基于注释的方法实现这一目标?

感谢。

2 个答案:

答案 0 :(得分:1)

EclipseLink还允许使用tableQualifier

设置模式

JPA - EclipseLink - How to configure Database Schema name at runtime

请注意,createEntityManagerFactory()将为相同的持久性单元名称返回相同的工厂,除非您传递的属性不同(例如url,user或“”eclipselink.session-name“)。

答案 1 :(得分:0)

我假设您的模式不仅具有相同的表名,而且具有相同的表结构。

您的应用程序设计方式并不好。假设您在模式“france”和“spain”中有ASSIGNMENT表。这显然是一个糟糕的设计决策,因为有一个描述该国家的专栏会好得多。因此,JPA并不是为这个功能设计的,这并不奇怪。

除此之外,您仍然可以使用JPA处理这种情况。您需要查看EntityManagerFactory。如果您使用的是JavaSE,请在javax.persistence.Persistence类中专门搜索此方法:

public static EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties);

对于javax.persistence.EntityManagerFactory界面中的此方法:

public EntityManager createEntityManager(Map properties);

诀窍在地图上。复制并调整this page中的一些代码,您可以执行以下操作:

import static org.eclipse.persistence.config.PersistenceUnitProperties.*;
...

public final class Connector {
    private static final Map<Country, EntityManagerFactory> factoriesByCountry =
        new HashMap<>();

    private Connector() {}

    public static synchronized EntityManagerFactory getEntityManagerFactory(Country country) {
        EntityManagerFactory emf = factoriesByCountry.get(country);
        if (emf == null) {
            emf = createEntityManagerFactory(country);
            factoriesByCountry.put(country, emf);
        }
        return emf;
    }

    private static EntityManagerFactory createEntityManagerFactory(Country country) {
        Map<Object, Object> properties = new HashMap<>();

        // Ensure RESOURCE_LOCAL transactions is used.
        properties.put(TRANSACTION_TYPE,
            PersistenceUnitTransactionType.RESOURCE_LOCAL.name());

        // Configure the internal EclipseLink connection pool.
        // TODO: Personalize your connection and schema accordingly to the given Country.
        properties.put(JDBC_DRIVER, "oracle.jdbc.OracleDriver");
        properties.put(JDBC_URL,
            "jdbc:oracle:thin:@" + country.getHost() + ":1521:" + country.getSchema());
        properties.put(JDBC_USER, country.getUser());
        properties.put(JDBC_PASSWORD, country.getPassword());

        // Configure logging. FINE ensures all SQL is shown
        properties.put(LOGGING_LEVEL, "FINE");
        properties.put(LOGGING_TIMESTAMP, "false");
        properties.put(LOGGING_THREAD, "false");
        properties.put(LOGGING_SESSION, "false");

        // Ensure that no server-platform is configured
        properties.put(TARGET_SERVER, TargetServer.None);

        // Now the EntityManagerFactory can be instantiated:
        return Persistence.createEntityManagerFactory(country.getUnitName(), properties);
    }
}

如果您使用的是JavaEE,那么它将强烈依赖于您的容器,但您需要执行与上述类似的操作。

显然,在创建EntityManagerFactory之后,您需要获取EntityManager,可能会传递其他一些属性。此外,您需要在任何地方跟踪正确的Country。您甚至可以使用多个EntityManagerFactories连接到多个数据库,但是不要混淆和混淆来自不同国家/地区的托管实体可能会很棘手,因此我建议您将此信息添加到每个实体类中以帮助您。

如果您的表格结构在不同国家/地区之间有所不同,那么您的实体类就需要弄明白。在这种情况下,一个可能的解决方案是定义AssignmentFranceAssignmentSpainAssignment的超类,并且您可以根据国家/地区获得正确的子类。