CodeGym /Cursos Java /Módulo 5. Spring /Inicializando DataSource en primavera

Inicializando DataSource en primavera

Módulo 5. Spring
Nivel 7 , Lección 5
Disponible

El paquete org.springframework.jdbc.datasource.init proporciona soporte para inicializar un DataSource existente. Las herramientas de soporte de bases de datos integradas brindan una opción para crear e inicializar un DataSource para una aplicación. Sin embargo, a veces es posible que necesites inicializar una instancia que se está ejecutando en un servidor.

Inicialización de base de datos usando Spring XML

Si necesita inicializar una base de datos y es posible especificar un enlace al bean DataSource, puede usar la etiqueta initialize-database en el archivo spring-jdbc espacio de nombres >:

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/>
    <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/>
</jdbc:initialize-database>

El ejemplo anterior ejecuta los dos scripts especificados en la base de datos. El primer script crea el esquema y el segundo completa las tablas con el conjunto de datos de control. Las ubicaciones de los scripts también pueden tener comodines en el estilo Ant habitual utilizado para los recursos en Spring (por ejemplo, classpath*:/com/foo/**/sql/*-data.sql). Si utiliza una plantilla, los scripts se ejecutan en el orden léxico de su URL o nombre de archivo.

La lógica predeterminada del inicializador de la base de datos es ejecutar incondicionalmente los scripts especificados. Esto no siempre es lo que se requiere; por ejemplo, si los scripts se ejecutan en una base de datos que ya tiene datos de auditoría. La probabilidad de eliminar datos accidentalmente se reduce siguiendo el patrón común (mostrado anteriormente): primero crear tablas y luego insertar datos. El primer paso fallará si las tablas ya existen.

Sin embargo, para brindarle más control sobre la creación y eliminación de datos existentes, el espacio de nombres XML proporciona varias capacidades adicionales. La primera es una bandera para activar y desactivar la inicialización. Puede configurarlo según su entorno (por ejemplo, extraer un valor booleano de las propiedades del sistema o de un bean de entorno). En el siguiente ejemplo, el valor se obtiene de una propiedad del sistema:

<jdbc:initialize-database data-source="dataSource"
    enabled="#{systemProperties.INITIALIZE_DATABASE}"> 
    <jdbc:script location="..."/>
</jdbc:initialize-database>
  1. Obtenga el valor de enabled de la propiedad del sistema INITIALIZE_DATABASE.

La segunda opción para controlar lo que sucede con los datos existentes es ser más resiliente ante los fallos. Para hacer esto, puede controlar la capacidad del inicializador para ignorar ciertos errores en el SQL que ejecuta desde los scripts, como se muestra en el siguiente ejemplo:

<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
    <jdbc:script location="..."/>
</jdbc:initialize-database>

En el ejemplo anterior, decimos que esperamos que a veces los scripts se ejecuten en una base de datos vacía, y esos scripts tienen algunas declaraciones DROP que, por lo tanto, no se ejecutarán. Por lo tanto, las consultas SQL DROP con errores se ignorarán, pero otras fallas generarán una excepción. Esto es útil si el dialecto SQL no admite DROP ... IF EXISTS (o similar), pero necesita eliminar incondicionalmente todos los datos de control antes de volver a crear. En este caso, el primer script suele ser un conjunto de declaraciones DROP, seguido de un conjunto de declaraciones CREATE.

El parámetro ignore-failures se puede establecer en NONE (predeterminado), DROPS (ignora DROP erróneos). declaraciones) o ALL (ignorar todos los errores).

Cada instrucción debe estar separada por un carácter ; o una nueva línea si el carácter ; no está presente en el script. Puedes controlar esto globalmente o mediante script, como se muestra en el siguiente ejemplo:

<jdbc:initialize-database data-source="dataSource" separator="@@"> 
    <jdbc:script location="classpath:com/myapp/sql/db-schema.sql" separator=";"/> 
    <jdbc:script location="classpath:com/myapp/sql/db-test-data-1.sql"/>
    <jdbc:script location="classpath:com/myapp/sql/db-test-data-2.sql"/>
</jdbc:initialize-database>
  1. Instalar scripts separadores en @@.
  2. Establezca el separador para db-schema.sql en ;.

En este ejemplo, dos scripts test-data usan @@ como delimitadores de declaraciones, y solo db-schema.sql usa ;. Esta configuración establece que el delimitador predeterminado sea @@ y anula este valor para el script db-schema.

Si desea tener más control que usar un espacio de nombres XML, puede usar DataSourceInitializer directamente y definirlo como un componente en su aplicación.

Inicialización de otros componentes dependientes de la base de datos

Una gran clase de aplicaciones (aquellas que no usan una base de datos antes de iniciar el contexto en Spring) pueden usar el inicializador de la base de datos sin obstáculos adicionales. Si su aplicación no es una de estas, es posible que deba leer el resto de esta sección.

El inicializador de la base de datos depende de la instancia DataSource y ejecuta los scripts proporcionados en la devolución de llamada de inicialización (similar al init-method en la definición del bean XML, un método con la anotación @PostConstruct en un componente o el método afterPropertiesSet() en un componente que implementa InitializingBean). Si otros beans dependen de la misma fuente de datos y utilizan la fuente de datos en la devolución de llamada de inicialización, puede ocurrir un problema porque los datos aún no se han inicializado. Un ejemplo común es un caché que se inicializa sin demora y carga datos de la base de datos cuando se inicia la aplicación.

Para solucionar este problema, hay dos formas: cambiar la estrategia de inicialización de la caché a una etapa posterior o asegurarse de que el inicializador de la base de datos se inicialice primero.

Cambiar la estrategia de inicialización de la caché puede ser fácil si la aplicación está bajo su control y no de otra manera. Algunas sugerencias sobre cómo lograr esto:

  • Haga que el caché se inicialice más tarde en el primer uso, lo que mejorará el tiempo de inicio de la aplicación.

  • Deje que su caché, o un componente separado que inicialice el caché, implemente Lifecycle o SmartLifecycle. Cuando se inicia un contexto de aplicación, puede iniciar SmartLifecycle automáticamente configurando su indicador autoStartup y puede iniciar Lifecycle manualmente llamando a ConfigurableApplicationContext.start() para el contexto adjunto.

  • Utilice ApplicationEvent de Spring o un mecanismo de observador personalizado similar para activar la inicialización de la caché. ContextRefreshedEvent siempre lo publica el contexto cuando está listo para usarse (después de que se hayan inicializado todos los beans), por lo que este suele ser un método útil (así es como funciona SmartLifecycle por defecto).

También es fácil asegurarse de que el inicializador de la base de datos se inicialice primero. Algunas ideas sobre cómo hacer esto:

  • Utilizará la lógica BeanFactory predeterminada de Spring, que consiste en que los beans se inicializan en el orden en que se registran. Esto se puede hacer fácilmente adoptando la práctica común de utilizar un conjunto de elementos <import/> en la configuración XML que organizan los módulos de su aplicación y garantizan que la base de datos y la inicialización de la base de datos aparezcan en primer lugar.

  • Separe el DataSource de los componentes empresariales que lo utilizan y controle el orden en el que se ejecutan colocándolos en instancias ApplicationContext separadas (por ejemplo, el contexto principal contiene el DataSource, y el hijo son los componentes comerciales). Esta estructura es común en las aplicaciones web Spring, pero se puede utilizar más ampliamente.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION