Archivos Mensuales: septiembre 2012

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’)
Anuncios

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!!! 

Anotaciones en JPA para sobrevivir a una primera persistenica

 

En este apartado, voy a dar por hecho.

  1. Sabéis qué es persistencia
  2. Sabéis qué son las anotaciones
  3. Sabéis qué es JPA
  4. Tenéis paciencia conmigo.

En la persistencia se crean entidades (ejemplo entidad “Usuario”) y cada entidad tiene sus atributos o propiedades que están enlazados por arte de magia de la persistencia en la base de datos (ejemplo private Integer usuario_id).

Las anotaciones o announces permiten definir la persistencia de forma fácil, bonita y barata.

Estas son las anotaciones que he destacado para sobrevivir en este mundo:

@Entity Especifica que voy a crear una entidad. Se coloca al inicio de la definición de la clase.

@Entity
@Table(name=”users”)
public class User implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name=”user_id”, nullable=false)
private Integer userId = null;

 

@Id Primary key de la entidad.

 

@Entity
@Table(name=”users”)
public class User implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name=”user_id”, nullable=false)
private Integer userId = null;


@GeneratedValue  Indica que esa clave se auto genera por medio de auto increment


@Colulmn
Sirve para especificar que la clave está asociada a un atributo de la tabla. Aprovecharemos para indicar si  puede ser nulo, si existe un límite de caracteres, etc.

@Column (name=”code”, nullable=false, length=50, unique=true)
private String code = null;


@Temporal
Se usa normalmente en fechas.

Si definimos un elemento de tipo Date, deberemos indicarle en temporal que el tipo es timestamp..

@Column(name=”modification_date”)
@Temporal(TemporalType.TIMESTAMP)
private Date modificationDate = null;

o de tipo date si no queremos obtener la hora

   @Column (name=”analysis_date”)
@Temporal(TemporalType.DATE)
private Date analysisDate = null;

@OneToMany.  Indicar una relación unidireccional de muchos a uno.

Ejemplo User N – N Roles

Entity user

@OneToMany(cascade = CascadeType.ALL, mappedBy = “user”)
private List<UserRole> userRoles = null;

Entity users_roles

JoinColumn(name = “user_id”, referencedColumnName = “user_id”, insertable=false, updatable=false)
@ManyToOne(optional = false)
private User user = null;

Con mappedBy estamos indicando quién es el dueño de la relación. En este caso…. está claro, no? ¿Dónde quiero tener guardado los roles del usuario? Tiene sentido que se guarden en el usuario por si se quieren obtener desde esa misma entidad.

@JoinColumn Indicamos la tabla con la que queremos hacer relación. Ver los ejemplos anteriores.

 

@ManyToOne Podemos indicar  desde users_rols que una relación de esta entidad tiene muchas entidades de usuarios y muchas entidades de roles. En este caso utilizaremos:

@JoinColumn(name = “user_id”, referencedColumnName = “user_id”, insertable=false, updatable=false)
@ManyToOne(optional = false)
private User user = null;

@JoinColumn(name = “role_id”, referencedColumnName = “role_id”, insertable=false, updatable=false)
@ManyToOne(optional = false)
private Role role = null;

 

Para que quede claro el ejemplo: 1 usuario – n roles necesitaremos hacer

  1. Definir el listado de roles dentro de “user” e indicar la relación OneToMany
  2. En “users_roles” indicar la relación ManyToOne con respecto a usuarios y ManyToOne a roles
  3. En “rol” indicar… nada! no se entera de nada!

 

@ManyToMany y @OneToOne 

OneToOne podría utilizarse para indicar que un usuario tiene una dirección dentro.

ManyToMany… recomiendo no utilizarlo.

 

Muchas gracias!! se agradece puntualizar cualquier error cometido! a parte claro está de mis lacarrismos.