Can’t create table (errno: 150)

Este error es tan típico, que una vez que se ya has sufrido estos fallos, se intentan evitar teniendo un poco de cuidado al crear las tablas. Muchos ya lo conocéis y hay mil páginas…. pero he querido completarlo con algún detalle! Ahí van!

  1. Opción:  Estás añadiendo una clave foránea cuyo tipo no coincide al tipo que hace referencia.

OJO! con INT(11) VS INT(10) : algunas herramientas que hacen de interfaz de bases de datos crean PRIMARY_KEY como INT(11) y el resto de campos de tipo numérico como INT(10).

OJO! con UNSIGNED. Si recibes código heredado y te estás volviendo loco puede que esté indicado como UNSIGNED.

OJO! que la clave foránea sea pueda ser NULL, no influye. Ejemplo:

`modified_by` INT(11) NULL DEFAULT NULL.

 

  1. Opción: Estás añadiendo una clave foránea y el campo al que estás haciendo referencia no existe con ese valor.

Es decir. Imaginemos que a la clave ‘modified_by’ lo tienes inicializado a 5. Te has dado cuenta que has añadido el campo, pero no has añadido la propiedad de que es una foreing key a la tabla de usuarios! Si luego al poner que modified_by es fk te sale este error, comprueba que el usuario 5 existe en la tabla de usuarios.

OJO! Cuando modifiques una tabla con un campo existente ‘modified_by’ que es nulo y pongas que la foreing key no puede ser nulo. Ejemplo:

`modified_by` INT(11) NOT NULL.

No te va a dejar modificar la tabla a no ser de que le pongas un valor inicializado y que sea correcto. Tendrás que actualizar el campo modified_by por un valor correcto y luego crear la tabla. (el mismo caso que antes, pero ahora con NULL).

 

  1. Opción: Si pones “On Delete Set Null” pero el campo está definido como NOT NULL.

OJO! Te contradices más que el programa electoral de Rajoy!

 

Ejemplo CASE MySQL

Sabemos la secuencia de la teoría. ¿Pero cómo manejamos una secuencia CASE con un tipo de dato ENUM como value?

CASE value

WHEN [compare-value]

THEN result [WHEN [compare-value] THEN result ...]

[ELSE result] END,

CASE WHEN [condition]

THEN result

[WHEN [condition]THEN result ...]

[ELSE result]

END

Adjunto un ejemplo de secuencia CASE en MySQL, ya que en su día cuando busqué, no encontré un ejemplo claro.

Primero vamos a suponer que tenemos la siguiente base de datos en MySQL centrándonos en los datos que importan: PK y ENUM.

catalog_filter_id —>  la clave (PK)
article_status —> tipo ENUM.
El resto son date, string, etc.

‘article_status’  que es de tipo ENUM está definido de la siguiente forma:

 

ENUM {‘all’,’operative’,’no_operative’}

 

Al ser un enum, article_status puede ser 1, 2, 3.

Si en lugar de 1, 2, 3 como resultado de la búsqueda queremos que devuelva  ‘Todos’, ‘En vigor’ y ‘Sin vigor’:

“En caso de ser 1 muestra ‘Todos’,

En caso de ser 2 muestra ‘En vigor’,

En caso de ser 3 muestra ‘Sin vigor'”

Entonces la secuencia con CASE queda:

SELECT

catalog_filter_id,

family_from,

family_to,

article_from,

article_to,

case article_status  when 1 then 'Todos'  when 2 then 'En vigor'  when 3 then 'Sin vigor'  end as article_status,

bu.name

FROM catalogs_filters cf  left join business_units bu on cf.business_unit_id=bu.business_unit_id


WHERE

cf.catalog_id = ? and

cf.deleted_date is null



Por si no se ve bien en la misma línea tenemos:

case article_status  
  when 1 then 'Todos'  
  when 2 then 'En vigor'  
  when 3 then 'Sin vigor'  
end as article_status

¿Qué conseguimos?

Que se muestren las cadenas ‘Todos’, ‘En vigor’ y ‘Sin vigor’ del CASE en lugar de los números ‘1’, ‘2’, ‘3’ de article_status.

Conclusión: Los ejemplos me liaban si la sentencia ‘case’ va con ‘end’, hay ‘;’ etc. Con este ejemplo si lo utilizas parecido… tiene que funcionar 😉

Fedback, comentarios, pegas, mejoras, compartir y vivir are welcome

Gracias!!

Cuándo utilizar el tipo de dato ENUM en bases de datos MySQL

Hasta hace poco. No acostumbraba a utilizar el campo ENUM como tipo de dato en una tabla.

La duda que planeo queda clara en el siguiente ejemplo:

//SIN ENUM


create table 'usuarios'(
          usuario_id INT,
          nombre VARCHAR(100),
          usuario_tipo_id INT
        ) TYPE=innodb;</code>
)

(Siendo usuario_tipo_id una fk a usuario_tipo_id de la tabla inferior).


create table 'usuarios_tipos'(

usuario_tipo_id INT,

descripcion VARCHAR(200)

)

ó


// CON ENUM

create table 'usuarios'(

          usuario_id INT,
          nombre VARCHAR(100),
          tipo ENUM 
        ) TYPE=innodb;</code>
)

¿Cuándo tomar una decisión u otra?

Decisión 1:

  1. El tipo de usuarios es gestionado desde la aplicación.
  2. El tipo de usuarios puede crecer o es incierto
  3. Cuando existe un gran número de tipo de usuarios.
  4. El dato lo muestro por pantalla y es sensible a que el sitio cambie de idioma.

Decisión 2:

  1. Existe un número limitado de tipos de usuario y siempre es el mismo.
  2. Nuestra base de datos ya es suficientemente grande y se nos está complicando bastante.
  3. Cuando no voy a filtrar por ese tipo (por ejemplo porque los voy a mostrar en ventanas diferentes y con una gestión independiente).
  4. Si queremos utilizarlo a estilo booleano, para que no nos olvidemos cual es el verdadero o cuál es el falso (ejemplo:  active ENUM (‘no_active’,’active’)

Cómo iniciar e interpretar el visor de Caché de Java

Muchos desconocen el visor de caché de java o nunca lo han utilizado. Recomiendo su utilización por los siguientes motivos:

  • Podemos ver todas las aplicaciones descargadas.
  • Podemos ver si están activadas las actualizaciones automáticas
  • Podemos actualizar la versión del java
  • Podemos configurar los parámetros de java de nuestro ordenador.
  • Podemos visualizar el jnlp

Y esto para qué es útil?

En mi caso, estoy desplegando una aplicación a distintas máquinas. Cada aplicación tiene una configuración distinta.  Para realizar las pruebas finales, estoy instalando en mi ordenador la aplicación que he desplegado en su servidor  (por VPN) en mi escritorio.

Cuando sólo tenemos una, es útil para saber si nos ha pillado bien el vpn o las conexiones automáticas activadas o desactivadas. Pero cuando queremos controlar más de una aplicación con el mismo nombre es útil saber a qué máquina apunta, qué conexión tiene, etc. Ya que sino… puede ser un caos total!!

En windows:

Abrir el programa “ejecutar”

Escribir

javaws -viewer

Cuando tengamos la consola podremos ver las aplicaciones activas:

Estado: Si el estado está en verde la aplicación se actualizará automáticamente.

Desinstalar: si pulsamos con el botón derecho podemos seleccionar la opción de desinstalar.

Botón verde superior ejecutar: arranca la aplicación que estás seleccionando en el menú.

En MAC o Linux, si tenemos configurado Java desde el PATH, simplemente hay que ejecutar el comando javaws -viewer desde el terminal.

Unix Top Command

Mi trending topic de unix commands 🙂

rm -rf * <nombre de la carpeta> Borrar recursivamente directorios y ficheros
tar czvf archivo.tar.gz /archivo/mayo/* Empaquetar y comprimir
tar xzvf archivo.tar.gz Desempaquetar y descomprimir
scp root@192.168.X.X:/root/fichero.ejemplo . Copia ficheros por scp de una máquina a otra. En el ejemplo de la máquina 192.168.X.X lo copia en la máquina en la que estamos ejecutando el comando y lo guarda con el mismo nombre, en la ruta en la que estamos.
svn co http://192.168.X.X/svn/carpeta-ejemplo/ url-ejemplo/ Descarga ficheros del svn. En el ejemplo copia la carpeta del svn en la url que le indicamos.
cp -r /var/www/asist-telecare.com/ /var/www/pruebas Copia recursivamente incluido la carpeta ‘asist-telecare.com’ en la dirección /var/www/pruebas
grep -r ‘contenido a buscar’ * Buscar recursivamente desde la dirección donde se pone el comando las ocurrencias de la cadena ‘contenido a buscar’ dentro de los ficheros
find -name ‘nombre del fichero’ Buscar recursivamente desde la dirección donde se pone el comando el nombre del fichero ‘nombre del fichero’
find /root -name ‘*[extension]’ Buscar recursivamente desde la dirección donde se pone el comando el nombre un fichero con extensión [extension]
wc -l panama_config.txt Cuenta palabras, líneas, etc.
svn remove http://192.168.X.X/svn/carpeta-ejemplo/ -m ‘borramos de ejemplo’ Borramos la carpeta del svn carpeta-ejemplo

Error en ejecución MySQL

Cuando estamos desesperados, cuando sabemos que algo oscuro está haciendo MySQL, cuando sospechamos que hay algunas tablas bloqueadas o algún error de memoria en MySQL, en estos casos, aconsejo leer el log de MySQL.

Para ello hace falta ir al servidor donde tenemos instalado mysql.

Entrar en la misma consola de Mysql mediante:

mysql -p

Y activar el log.

set global general_log=ON

desc mysql.general_log;

Para desactivarlo hace falta poner

set global general_log=OFF

En mi caso me fue de gran utilidad!! suerte!!

 

 

 

 

Cómo hacer que una aplicación java se actualice al arrancar en el .jnlp

Esto que parece muy sencillo, puede llevar muchos quebraderos de cabeza.

Bien!! Empecemos!!!

Tenemos nuestro .jnlp desplegado en el lugar donde lo hemos instalado.
Las palabras mágicas para que se actualice es poner :

<shortcut online="false">
          <desktop/>
          <menu submenu="AsisT"/>
        </shortcut>
&nbsp;

De esta forma cuando se haga dobleclik en el icono del escritorio, se actualizarán los cambios del jnlp.

Para entenderlo mejor, adjunto la estructura del jnlp.

<jnlp spec="1.5+" codebase="http://192.168.X.X/" href="http://192.168.X.X/eljnlp.jnlp>

 <information>
        <title>AsisT - DEMO</title>
        <vendor>Ibernex SL</vendor>
        <icon href="images/icono.png"/>
        <shortcut online="false">
          <desktop/>
          <menu submenu="AsisT"/>
        </shortcut>
    </information>
 <security>
      <all-permissions/>
    </security>
  <resources>
...
  </resources>
</jnlp>

Agregar argumentos para cumplir la ley de protección de datos en una tabla de MySQL

Antes créala y añadimos estos campos

ALTER TABLE `mitabla`
ADD COLUMN `created_by` INT(11) NOT NULL,
ADD COLUMN `creation_date` DATETIME NOT NULL AFTER `created_by`,
ADD COLUMN `modified_by` INT(11) NULL AFTER `creation_date`,
ADD COLUMN `modification_date` DATETIME NULL AFTER `modified_by`,
ADD COLUMN `deleted_by` INT(11) NULL AFTER `modification_date`,
	ADD COLUMN `deleted_date` DATETIME NULL AFTER `deleted_by`;

# En caso de que la tabla no esté vacía, será necesario actualizar los siguientes 
# campos cuyo contenido no puede ser nulo
update mitabla set created_by = 1;

update mitabla set creation_date = now();


ALTER TABLE `mitabla`
 ADD CONSTRAINT `table_fk01` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`),
 ADD CONSTRAINT `table_fk02` FOREIGN KEY (`modified_by`) REFERENCES `users` (`user_id`),
 ADD CONSTRAINT `table_fk03` FOREIGN KEY (`deleted_by`) REFERENCES `users` (`user_id`);

Cómo utilizar el patrón Facade (Fachada) en bases de datos

¿Cuándo utilizar el patrón Facade para bases de datos?

En proyectos grandes que queremos adaptarlos a diferentes entornos o instalaciones.

¿Porqué utilizar el patrón Facade?

Como su propia traducción indica, este patrón actúa de Fachada. Lo que conseguimos es abstraer una capa de otra, de forma que si una capa cambia… no hace falta cambiar la otra!

¿Cómo debe estar estructurado?

  1. Organizaremos todas las funciones que tengan que ver con una funcionalidad en las llamadas Facade. Ejemplo: UsersFacade, podremos funcionalidad al estilo loginUser, loadUsers, saveUsers, addRolToUser, etc.
  2. Estás contendrán llamadas a los DAOs (Véase Patrón de diseño DAO) que tiene la interacción con la base de datos
  3. Cuando iniciemos la aplicación, seleccionaremos la fachada o Facade que queramos en función de la instalación (por ejemplo: una empresa dispone de MySQL y otra quiere Oracle!! no tienes que cambiar toda la aplicación sino implementar Facades distintas y cargar la fachada que quieras utilizar al principio.

Pon un ejemplo porque no lo pillo

Las clases Facade quedan de la siguiente forma:

public class UsersFacade {

public User loginUser(String userName, String password, Integer company_id) throws Exception {

UsersDAO usersDAO = new UsersDAO();
User user = usersDAO.getUserByLoginPassword(userName, password, company_id);
return user;

}

public User loadUser(int id) throws Exception{
UsersDAO usersDAO = new UsersDAO();
User user = usersDAO.getUserById(id);
return user;
}

Cuando necesites utilizar alguna de estas funciones deberás hacer:

UsersFacade uf = new UsersFacade();
uf.loadUser(this.view.getSelectedUser().getUserId());

Cómo crear un EntityManager en persistencia para que cumpla la ley de protección de datos LPD

EntityManager es la clase que pilota toda la persistencia. Para más detalles pregunta a google!!

En este capítulo voy a explicar como crear tu propio EntityManager para que cumpla la LPD…. sin tener que arrastrarlo a todos! Esta es una solución… aunque puede que no sea la mejor!  Se agradece cualquier comentario comentando otras soluciones.


QUÉ QUEREMOS CONSEGUIR

  • Evitar tener que registrar todas las veces que utilizamos persistencia con cualquier objeto la actualización de los campos de las tablas de la base de datos: “creado_por” , “modificado_por” o “borrado_por” junto a las fechas correspondientes “fecha_creacion”, “fecha_borrado”, “fecha_modificacion”.

CÓMO LO HACEMOS

  • Crearemos nuestra nueva clase que extiende de EntityManager

public class EntityManagerWrapper implements EntityManager {

private EntityManager entityManager = null;

  • Ahora tendremos que implementar y sobrescribir todos los métodos menos “persist” y “delete”
  1. Los que sobrescribimos quedarán del estilo:

@Override
public <T> T merge(T t) {
return this.entityManager.merge(t);
}

  1. Persist quedará:
@Override
public void persist(Object o) {
try{
//seteando traza de usuario
User user = (User)ApplicationContext.getInstance().getFromSession("user");
Method method = o.getClass().getMethod("getCreatedBy", (Class&lt;?&gt;[]) null);
Object createdBy = method.invoke(o, (Object[]) null);
if(createdBy == null){
method = o.getClass().getMethod("setCreatedBy", new Class[]{ Integer.class });
method.invoke(o, new Object[]{ user.getUserId() });
method = o.getClass().getMethod("setCreationDate", new Class[]{ Date.class });
method.invoke(o, new Object[]{ new Date() });
}
method = o.getClass().getMethod("setModifiedBy", new Class[]{ Integer.class });
method.invoke(o, new Object[]{ user.getUserId() });
method = o.getClass().getMethod("setModificationDate", new Class[]{ Date.class });
method.invoke(o, new Object[]{ new Date() });

} catch (Exception ex) {
//ErrorManager.showExceptionDialog(ex);
}

this.entityManager.persist(o);
lastEntity = o;
}
<ol>
	<li>Delete nos quedará</li>
</ol>
public void delete(Object o) {
try {

//seteando traza de usuario
User user = (User)ApplicationContext.getInstance().getFromSession("user");
Method method = o.getClass().getMethod("setDeletedBy", new Class[]{ Integer.class });
method.invoke(o, new Object[]{ user.getUserId() });
method = o.getClass().getMethod("setDeletedDate", new Class[]{ Date.class });
method.invoke(o, new Object[]{ new Date() });

} catch (Exception ex) {
ErrorManager.showExceptionDialog(ex);
}

this.entityManager.persist(o);
lastEntity = o;
}

SUERTE!!!