1

我在我的项目中使用 eclipselink 和 Oracle。

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

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

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

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

谢谢。

4

2 回答 2

1

EclipseLink 还允许使用 tableQualifier 设置模式,

请参阅,JPA - EclipseLink - 如何在运行时配置数据库模式名称

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

于 2013-07-10T14:11:14.387 回答
0

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

您的应用程序的设计方式并不好。假设您在“法国”和“西班牙”模式中有 ASSIGNMENT 表。这显然是一个糟糕的设计决定,因为最好有一个描述国家的专栏。因此,JPA 并非完全针对此功能而设计也就不足为奇了。

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

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

对于javax.persistence.EntityManagerFactory接口中的这​​个方法:

public EntityManager createEntityManager(Map properties);

诀窍在于地图。从这个页面复制和修改一些代码,你会做这样的事情:

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任何地方跟踪正确的。您甚至可以使用 multiple 连接到多个数据库EntityManagerFactories,尽管不混合和混淆来自不同国家/地区的托管实体可能会很棘手,因此我建议您将此信息添加到每个实体类中以帮助您。

如果您的表结构因国家/地区而异,那么您的实体类将需要弄清楚这一点。在这种情况下,一种可能的解决方案是定义它Assignment是两者的超类,FranceAssignment并且SpainAssignment您可以根据国家/地区获得正确的子类。

于 2013-07-09T21:19:08.237 回答