¡La versión 2.0 de Play ya está lista! Ayúdanos a traducir la documentación de la útlima versión y sigue nuestro progreso.

Manuales, tutoriales & referencias

Consulte

Contenidos

Elija la versión

Buscar

Busque con google

Libros

Administrando las actualizaciones de la base de datos

Cuando utiliza una base de datos relacional, necesita de alguna manera monitorear y organizar las actualizaciones del esquema de su base de datos. Normalmente existen varias situaciones donde usted necesita una forma más sofisticada de monitorear los cambios del esquema de su base de datos, tales como:

  • Cuando trabaja dentro de un equipo de desarrolladores, cada persona necesita estar al tanto de cualquier cambio en el esquema.
  • Cuando poner en producción una nueva versión de su aplicación, usted debe tener un método robusto de actualizar el esquema de su base de datos.
  • Si trabaja en varias computadoras, necesita mantener todos los esquemas de base de datos sincronizados.

Si usted trabaja con JPA, Hibernate puede manejar por usted las actualizaciones de la base de datos de forma automática. Los scrips de evolución son útiles si no usa JPA o si prefiere encargarse del esquema de su base datos de forma manual para un ajuste más fino.

Scripts de evolución

Play registra las actualizaciones de su base de datos utilizando varios scripts de evolución. Estos scripts se escriben en el conocido SQL plano y deberíann guardarse en el directorio db/evolutions de su aplicación.

Al primer script se le coloca el nombre 1.sql, al segundo 2.sql, y así sucesivamente…

Cada script contiene dos partes:

  • La parte Ups (dar de alta) que describe las transformaciones necesarias para pasar de una versión del esquema de datos a la siquiente.
  • La parte Downs (dar de baja) que describe como revertir esas transformaciones.

Por ejemplo, observe el primer script de evolución de una aplicación básica:

# Esquema de datos de Usuarios
 
# --- !Ups
 
CREATE TABLE User (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    email varchar(255) NOT NULL,
    password varchar(255) NOT NULL,
    fullname varchar(255) NOT NULL,
    isAdmin boolean NOT NULL,
    PRIMARY KEY (id)
);
 
# --- !Downs
 
DROP TABLE User; 

Como puede ver, usted tiene que delimitar las dos secciones Ups y Downs usando comentarios en su script SQL.

Las evoluciones son activadas automáticamente cuando una base de datos está configurada en el archivo application.conf y los script de evolución están presentes. Puede desactivarlas asignando el valor false a la clave evolutions.enabled. Por ejemplo, si las pruebas cuentan con su propia base de datos puede desactivar las evoluciones para el entorno de pruebas.

Cuando las evoluciones están activadas, Play revisará el estado del esquema de su base de datos antes de cada petición en el modo DEV, o antes de iniciar la aplicación en modo PROD. En modo DEV, si el esquema de su base de datos no está actualizado, una página de error le sugerirá que lo sincronice ejecutando el script SQL apropiado.

Si está conforme con el script SQL, puede aplicarlo directamente haciendo clic en el botón ‘Apply evolutions’.

Si usa una base de datos en memoria (db=mem), Play ejecutará automáticamente todos los scripts de evolución si su base de datos está vacía.

Sincronizando cambios concurrentes

Ahora imaginemos que tenemos dos desarrolladores trabajando en un mismo proyecto. El Desarrollador A trabajará en una funcionalidad que requiere una nueva tabla en la base de datos. Por lo tanto creará el siguiente script de evolución 2.sql:

# Add Post
 
# --- !Ups
CREATE TABLE Post (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    title varchar(255) NOT NULL,
    content text NOT NULL,
    postedAt date NOT NULL,
    author_id bigint(20) NOT NULL,
    FOREIGN KEY (author_id) REFERENCES User(id),
    PRIMARY KEY (id)
);
 
# --- !Downs
DROP TABLE Post;

Play aplicacará este script de evolución a la base de datos del Desarrollador A.

Por otro lado, el desarrollador B trabajará en una funcionalidad que requiere alterar la tabla User. Por lo que él también creará el siguiente script de evolución 2.sql:

# Update User
 
# --- !Ups
ALTER TABLE User ADD age INT;
 
# --- !Downs
ALTER TABLE User DROP age;

El Desarrollador B termina su trabajo y lo graba (commit, supongamos que están usando Git). Ahora el desarrollador A debe unir (merge) el trabajo de su colega antes de continuar, así que ejecutará el comando git pull, y al hacerlo se encontrará con el siguiente conflicto:

Auto-merging db/evolutions/2.sql
CONFLICT (add/add): Merge conflict in db/evolutions/2.sql
Automatic merge failed; fix conflicts and then commit the result.

Cada desarrollador ha creado un script de evolución 2.sql. Por lo tanto el desarrollador A tendrá que unir (merge) el contenido de estos archivos:

<<<<<<< HEAD
# Add Post
 
# --- !Ups
CREATE TABLE Post (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    title varchar(255) NOT NULL,
    content text NOT NULL,
    postedAt date NOT NULL,
    author_id bigint(20) NOT NULL,
    FOREIGN KEY (author_id) REFERENCES User(id),
    PRIMARY KEY (id)
);
 
# --- !Downs
DROP TABLE Post;
=======
# Update User
 
# --- !Ups
ALTER TABLE User ADD age INT;
 
# --- !Downs
ALTER TABLE User DROP age;
>>>>>>> devB

En realidad la unión es fácil de hacer:

# Add Post and update User
 
# --- !Ups
ALTER TABLE User ADD age INT;
 
CREATE TABLE Post (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    title varchar(255) NOT NULL,
    content text NOT NULL,
    postedAt date NOT NULL,
    author_id bigint(20) NOT NULL,
    FOREIGN KEY (author_id) REFERENCES User(id),
    PRIMARY KEY (id)
);
 
# --- !Downs
ALTER TABLE User DROP age;
 
DROP TABLE Post;

Este script de evolución representa la nueva versión 2 de la base de datos, que es diferente de la versión 2 anterior que el desarrollador A habia aplicado con anterioridad.

Play detectará esta nueva versión, y le pedirá al desarrollador A que sincronice su base de datos primero revirtiendo la antigua versión 2 ya aplicada, y luego aplicando el nuevo script versión 2:

Estados inconsistentes

Es probable que en algún momento cometa algún error en sus scripts de evolución, y la misma fallará. En ese caso, Play marcará su esquema de base de datos como inconsistente y le pedirá que resuelva manualmente el problema antes de continuar.

Por ejemplo, el script Ups de está evolución 3.sql tiene un error:

# Add another column to User
  
# --- !Ups
ALTER TABLE Userxxx ADD company varchar(255);
 
# --- !Downs
ALTER TABLE User DROP company;

Por lo que el intento de aplicar esta evolución fallará, y Play marcará el esquema de su base de datos como inconsistente:

Antes de continuar usted tiene que arreglar la inconsistencia. Así que ejecute el comando SQL correcto:

ALTER TABLE User ADD company varchar(255);

… y después marque este problema como resuelto manualmente haciendo clic en el botón.

Pero debido a que su script de evolución tiene errores, probablemente usted quiera corregirlos. Así que modifique el script 3.sql:

# Add another column to User
  
# --- !Ups
ALTER TABLE User ADD company varchar(255);
 
# --- !Downs
ALTER TABLE User DROP company;

Play detectará esta nueva evolución que reemplaza la versión 3 previa, y ejecutará el siguiente script:

Ahora todo está arreglado, y usted puede continuar con su trabajo.

Sin embargo, en modo de desarrollo suele ser más fácil borrar su base de datos de desarrollo y volver a aplicar todas las evoluciones desde el principio.

Comandos de evolución

Las evoluciones se ejecutan interactivamente en modo DEV. Sin embargo en modo PROD tendrá que utilizar el comando evolutions para ajustar el esquema de su base de datos antes de iniciar su aplicación.

Si intenta ejecutar una apliación en modo producción con una base de datos no actualizada, la aplicación no se iniciará.

~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! master-localbuild, http://www.playframework.org
~ framework ID is prod
~
~ Ctrl+C to stop
~ 
13:33:22 INFO  ~ Starting ~/test
13:33:22 INFO  ~ Precompiling ...
13:33:24 INFO  ~ Connected to jdbc:mysql://localhost
13:33:24 WARN  ~ 
13:33:24 WARN  ~ Your database is not up to date.
13:33:24 WARN  ~ Use `play evolutions` command to manage database evolutions.
13:33:24 ERROR ~ 
 
@662c6n234
Can't start in PROD mode with errors
 
Your database needs evolution!
An SQL script will be run on your database.
 
play.db.Evolutions$InvalidDatabaseRevision
    at play.db.Evolutions.checkEvolutionsState(Evolutions.java:323)
    at play.db.Evolutions.onApplicationStart(Evolutions.java:197)
    at play.Play.start(Play.java:452)
    at play.Play.init(Play.java:298)
    at play.server.Server.main(Server.java:141)
Exception in thread "main" play.db.Evolutions$InvalidDatabaseRevision
    at play.db.Evolutions.checkEvolutionsState(Evolutions.java:323)
    at play.db.Evolutions.onApplicationStart(Evolutions.java:197)
    at play.Play.start(Play.java:452)
    at play.Play.init(Play.java:298)
    at play.server.Server.main(Server.java:141)

El mensaje de error le dice que ejecute el comando play evolutions:

$ play evolutions
~        _            _ 
~  _ __ | | __ _ _  _| |
~ | '_ \| |/ _' | || |_|
~ |  __/|_|\____|\__ (_)
~ |_|            |__/   
~
~ play! master-localbuild, http://www.playframework.org
~ framework ID is gbo
~
~ Connected to jdbc:mysql://localhost
~ Application revision is 3 [15ed3f5] and Database revision is 0 [da39a3e]
~
~ Your database needs evolutions!
 
# ----------------------------------------------------------------------------
 
# --- Rev:1,Ups - 6b21167
 
CREATE TABLE User (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    email varchar(255) NOT NULL,
    password varchar(255) NOT NULL,
    fullname varchar(255) NOT NULL,
    isAdmin boolean NOT NULL,
    PRIMARY KEY (id)
);
 
# --- Rev:2,Ups - 9cf7e12
  
ALTER TABLE User ADD age INT;
CREATE TABLE Post (
    id bigint(20) NOT NULL AUTO_INCREMENT,
    title varchar(255) NOT NULL,
    content text NOT NULL,
    postedAt date NOT NULL,
    author_id bigint(20) NOT NULL,
    FOREIGN KEY (author_id) REFERENCES User(id),
    PRIMARY KEY (id)
);
 
# --- Rev:3,Ups - 15ed3f5
 
ALTER TABLE User ADD company varchar(255);
 
# ----------------------------------------------------------------------------
 
~ Run `play evolutions:apply` to automatically apply this script to the db
~ or apply it yourself and mark it done using `play evolutions:markApplied`
~

Si desea que Play aplique automáticamente esta evolución por usted, entonces ejecute el comando:

$ play evolutions:apply

Si prefiere ejecutar este script manualmente en su base de datos de producción, luego debe decirle a Play que su base de datos fue actualizada ejecutando el comando:

$ play evolutions:markApplied

Si hay algún error mientras ejecuta automáticamente los scripts de evolución, como en el modo DEV, debe resolverlo manualmente, y luego marcar el esquema de su base de datos como corregida, ejecutando el comando:

$ play evolutions:resolve

Próximos Pasos

Aprenda cómo configurar el Logging.