Pregunta

Una cosa continuamente he encontrado muy confuso sobre el uso de una base de datos de objetos como db4o es la forma de se supone que deben manejar las migraciones complejas que normalmente serían manejadas por SQL / PL-SQL.

Por ejemplo imaginar que tenía una tabla en una base de datos relacional llamada my_users. Originalmente se tenía una columna llamada "FULL_NAME", ahora que su software está en V2 que desea eliminar esta columna, dividir los nombres completos en un espacio en blanco y poner la primera parte en una columna denominada "nombre apellido" y la segunda en una columna last_name llamado. En SQL yo simplemente llenar las columnas "first_name" "" second_name luego retire la columna original llamado "FULL_NAME".

¿Cómo puedo hacer esto en algo así como db4o? Cómo puedo escribir un programa Java que los scripts mirando hacia arriba todos los objetos de User.class, el establecimiento de FULL_NAME a nula, mientras que el establecimiento de nombre apellido y last_name? Cuando hago mis próximos SVN no habrá campo / frijol propiedad correspondiente a FULL_NAME, esto sería un problema? Parece como si usarlo en una aplicación de producción donde mis cambios "esquema" Me gustaría escribir una secuencia de comandos para migrar los datos de la versión X a la versión X + 1 y luego en la versión x + 2 elimina realmente las propiedades que estoy tratando de deshacerse de la versión x + 1 ya que no puedo escribir un script de Java para modificar las propiedades que ya no son parte de mi tipo.

Parece que parte del problema es que un RDBMS resuelve lo que el objeto que se está refiriendo a la base de un nombre basado en cadena insensible caso simple, en un lenguaje como la tipificación de Java es más complicado que esto, no se puede hacer referencia a una propiedad si el / colocador / campo de captador no son un miembro de la clase cargado en tiempo de ejecución por lo que básicamente necesita tener 2 versiones de su código en el mismo guión (hmm, cargadores de clases personalizados suenan como un dolor), tienen la nueva versión de su clase almacena pertenecer a otro paquete (suena desordenado), o utilizar la versión x 1 x 2 + estrategia + he mencionado (requiere mucha más planificación). Tal vez hay alguna solución obvia que nunca espigué de los documentos db4o.

¿Alguna idea? Espero que esto tiene algún sentido.

¿Fue útil?

Solución

En primer lugar, db4o se encarga de la 'simple' escenarios como la adición o eliminación de un campo automáticamente . Al añadir el campo, todo objeto existente tiene el valor predeterminado almacenado. Cuando se elimina un campo, los datos de objeto existente se encuentra todavía en la base de datos y todavía se puede acceder a él. Cambiar el nombre de campo, etc son especial '-llamadas refactoring' .

Ahora el escenario que haría algo como esto:

  1. Eliminar el campo 'FULL_NAME', añada 'nombre' y los nuevos campos 'second_name'
  2. iterar sobre todos los 'Address'-objetos
  3. Acceso al campo de edad a través de la 'StoredClass'-API
  4. Split, cambiar, actualizar el valor etc. Establecer los nuevos valores en el nuevo campo y almacenar el objeto.

Supongamos que tenemos un 'Address' clase. El campo 'FULL_NAME' se ha eliminado. Ahora nos wa no para copiarlo en el 'Nombre' y "apellido. Entonces podría ir como esto (Java):

    ObjectSet<Address> addresses = db.query(Address.class);
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
    for (Address address : addresses) {
        String fullName = (String)metaInfoOfField.get(address);
        String[] splitName = fullName.split(" ");
        address.setFirstname(splitName[0]);
        address.setSurname(splitName[1]);
        db.store(address);
    }

Como se sugirió, podría escribir la migración de código para cada versión de golpe. Es un campo que no es parte de su clase más, usted tiene que acceder a ella con 'StoredField'-API como la de arriba.

Puede obtener una lista de todas las clases '' almacenados con ObjectContainer.ext().storedClasses(). Con StoredClass.getStoredFields() se puede obtener una lista de todos los campos de la tienda, sin Mather es el campo ya no existe en su clase. Si una clase ya no existe, todavía puede obtener los objetos y acceder a ella a través de 'GenericObject' clase.

Actualización:. Para los escenarios complexer en una base de datos necesita para migrar a través de múltiples pasos-versión-

Por ejemplo, en la versión v3 la dirección a objetos es completamente diferente. Por lo que la 'migración-script' de v1 a v2 no ha conseguido los campos más se requiere (nombre y surename en mi ejemplo). Creo que hay múltiples posibilidades para el manejo de este.

  1. (Suponiendo Java para esta idea. Ciertamente hay un equivalente en .NET). Se podría hacer la migración a paso un Groovy-script . Por lo que cada que cada secuencia de comandos no interfiere con otro. A continuación, defina 'clases' las clases necesarias para la migración allí. Así que cada uno tiene sus propias migración migración-clases. Con alias que uniría sus groovy-migración-clases a las clases java-reales.
  2. Creación de refactorización-clases para escenarios complejos. También se unen estas clases con alias .

Otros consejos

Me estoy tomando un poco de un tiro salvaje aquí, porque no refactorizar demasiados datos en mi vida.

Usted está haciendo una comparación extraña: Si quería 'hot-migrar' el PP, lo que probablemente tiene que hacer el x+1, enfoque x+2 de versiones que usted describe, pero no se sabe muy bien - me wouldn' t saber cómo hacer esto con SQL o bien ya que no soy un experto en dB.

Si está migrando 'frío', sin embargo, sólo podría hacerlo en un solo paso creando una instancia de un nuevo objeto a partir de los datos antiguos, almacenar el nuevo objeto, eliminar el objeto de edad para cada objeto en el almacén. Ver db4o referencia.

Pero, honestamente: el mismo proceso en un RDBMS es complicado, también, ya que tendrá para desactivar las comprobaciones de restricciones (y posiblemente disparadores, etc.) para llevar a cabo la operación en realidad - tal vez no en el ejemplo que nos ha facilitado, pero para la mayoría de los casos de la vida real. Después de todo, la escisión de cadena es tan fácil que habrá poca ganancia.

  

En SQL yo simplemente llenar "nombre apellido" y "second_name" columnas

Sí, con un sencilla operación de cadena de división, puede sólo hacer eso. Pero los objetos en un escenario típico refactorización, estás re-estructuración en base a conjuntos grandes y complicados de reglas que no podría expresarse fácilmente en SQL, puede ser que necesite cálculo complejo, o fuentes de datos externas.

Para hacer eso, usted tendría que escribir el código, también.

Después de todo, no veo mucha diferencia en los dos procesos. Usted siempre tiene que tener cuidado con los datos en tiempo real, y que sin duda hacer una copia de seguridad en ambos casos. Refactoring es divertido, pero la persistencia es complicado por lo que la sincronización es un desafío en cualquier caso.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top