我在我的项目中使用 eclipselink 和 Oracle。
我正在使用基于注释的映射,如下所示。
@Entity
@Table(name="ASSIGNMENT", schema="service")
public class Assignment implements Serializable {
...
}
我有不同的模式对应于不同的国家。表名相同。要求是在运行时选择模式名称。
是否可以使用基于注释的方法来实现这一点?
谢谢。
我在我的项目中使用 eclipselink 和 Oracle。
我正在使用基于注释的映射,如下所示。
@Entity
@Table(name="ASSIGNMENT", schema="service")
public class Assignment implements Serializable {
...
}
我有不同的模式对应于不同的国家。表名相同。要求是在运行时选择模式名称。
是否可以使用基于注释的方法来实现这一点?
谢谢。
EclipseLink 还允许使用 tableQualifier 设置模式,
请参阅,JPA - EclipseLink - 如何在运行时配置数据库模式名称
请注意,createEntityManagerFactory() 将为相同的持久性单元名称返回相同的工厂,除非您传递不同的属性(例如 url、user 或“eclipselink.session-name”)。
我假设您的模式不仅具有相同的表名,而且也具有相同的表结构。
您的应用程序的设计方式并不好。假设您在“法国”和“西班牙”模式中有 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
您可以根据国家/地区获得正确的子类。