Durante el ciclo de vida de una aplicaci贸n Java EE es com煤n que se despliegue en diferentes entornos antes de llegar al entorno de producci贸n. No s贸lo var铆an las m谩quinas en las que se despliega la aplicaci贸n, sino tambi茅n los servidores de bases de datos.
Si nuestra aplicaci贸n web o enterprise usa el API JPA para el acceso a datos, es posible que en algunas circunstancias sea necesario especificar el cat谩logo o el esquema de base de datos en la anotaci贸n @Table de nuestras entidades.
驴La raz贸n? En ciertas bases de datos, como por ejemplo Oracle, el usuario que utilizamos para la conexi贸n no es el propietario del esquema. Por esta raz贸n, al generar las consultas SQL es preciso especificar un 芦qualifier禄 para referirnos al cat谩logo o al esquema al que pertenecen las tablas.
La siguiente consulta en una base de datos Oracle funciona s贸lo si el usuario con el que realizamos la consulta es el propietario del esquema:
select id, name from customer;
Para realizar la misma consulta con un usuario diferente (con permisos de lectura), debemos especificar el nombre del esquema:
select id, name from mycrm.customer;
A la hora de definir nuestra entidad JPA, podemos indicar el nombre del esquema:
@Entity
@Table(name = "customer", schema = "mycrm")
public class Customer implements Serializable {
De esta forma, el problema queda corregido… en principio.
Recientemente, en uno de nuestros clientes nos hemos encontrado con el siguiente problema: existen tres entornos y en cada entorno, aunque las tablas son las mismas, el nombre del esquema var铆a, por lo que la soluci贸n anterior no es v谩lida. Llegados a este punto existen varias soluciones:
- Generar un archivo de despliegue por cada entorno: no es una soluci贸n demasiado buena. Obliga a modificar la propiedad 芦schema禄 en la anotaci贸n @Table antes de generar el archivo de despligue para cada entorno.
- Obtener el nombre del esquema mediante un archivo de propiedades y establecerlo en tiempo de ejecuci贸n. No existe una soluci贸n est谩ndar para esto y depende de la implementaci贸n de JPA que usemos.
Si la implementaci贸n que usamos es EclipseLink, la soluci贸n consiste en implementar el interfaz SessionCustomizer, mediante la cual es posible modificar los metadatos de una unidad de persistencia.
public class MySessionCustomizer implements SessionCustomizer {
聽聽聽 private final String schema;
聽聽 聽
聽聽聽 public MySessionCustomizer() {
聽聽聽聽聽聽聽 schema = <obtener el nombre del esquema de un archivo de propiedades>;
聽聽聽 }
聽聽 聽
聽聽聽 @Override
聽聽聽 public void customize(Session session) throws Exception {
聽聽聽聽聽聽聽 session.getLogin().setTableQualifier(schema);
聽聽聽 }
聽聽 聽
}
El 煤ltimo paso consiste en a帽adir una propiedad en nuestra unidad de persistencia indicando que se usar谩 nuestro SessionCustomizer:
<properties>
<property name="eclipselink.session.customizer" value="com.cygnussource.MySessionCustomizer"/>
</properties>
Si decidimos usar esta soluci贸n, ya no es necesario especificar el esquema en las entidades:
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
Es necesario recordar que esta soluci贸n s贸lo aplica cuando usamos EclipseLink. En el caso de Hibernate, tambi茅n existe una soluci贸n, aunque es distinta. Hablaremos de ella en futuras entradas.