我在项目中使用eclipselink和Oracle。
我正在使用基于注释的映射,如下所示。
@Entity
@Table(name="ASSIGNMENT", schema="service")
public class Assignment implements Serializable {
...
}
我有不同的模式,对应不同的国家/地区。表名是相同的。要求是在运行时选择模式名称。
是否可以使用基于注释的方法实现这一目标?
感谢。
答案 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
连接到多个数据库,但是不要混淆和混淆来自不同国家/地区的托管实体可能会很棘手,因此我建议您将此信息添加到每个实体类中以帮助您。
如果您的表格结构在不同国家/地区之间有所不同,那么您的实体类就需要弄明白。在这种情况下,一个可能的解决方案是定义Assignment
是FranceAssignment
和SpainAssignment
的超类,并且您可以根据国家/地区获得正确的子类。