samedi 11 décembre 2010

iBatis dans un contexte multi-utilisateur grâce à la technique Optimistic locking

Dans les logiciels en réseau, dont l'utilisation est soumise à de nombreux utilisateurs l'utilisant en même temps, sauvant le problème d’accès concurrent est évoqué.
Dans cet article je vais vous montrer comment implémenter un tel mécanisme en iBatis, dont il n y a pas de standard comme le cas d'hibernate, alors il faut l’implémenter par soit même comme suite :
  • Implémenter son propre OptimisticLockException qui doit dérivé RuntimeException ou réutiliser celui du Package JPA : javax.persistence.
  • Ajouter une colonne nommée version de type numérique non nulle dans la table et définir sa default value à 1.
  • Ajouter un champs nommé version à la classe de type int.
  • Modifier l'interface DAO pour déclencher une OptimisticLockException comme suite :
      public interface EntityDao {
           void createEntity(Entity entity);
           Entity selectEntryById(Long id);
           void updateEntity(Entity entity) throws OptimisticLockException;
           void deleteEntity(Entity entity);
     }
  • Modifier la classe DAO pour traiter les champs version

   public class EntityDaoImpl extends SqlMapClientDaoSupport implements EntityDao {

     @Override
     public void createEntity(final Entity entity) {
         getSqlMapClientTemplate().insert("insertEntity", entity);
         entity.setVersion(1);
     }


     @Override
     public Entity selectEntryById(final Long id) {
        return (Entity) getSqlMapClientTemplate().queryForObject("findEntityById", id);
     }


    @Override
    public void updateEntity(final Entity entity) throws OptimisticLockException {
        final int oldVersion = entity.getVersion();
        final int newVersion = oldVersion + 1;

        final Map params = new HashMap();
        params.put("entity", entity);
        params.put("oldVersion", oldVersion);
        params.put("newVersion", newVersion);

        int updateCount = getSqlMapClientTemplate().update("updateEntity", params);

        if (updateCount == 0) {
             throw new OptimisticLockException("Erreur lors de la mise à jour, un autre utilisateur est entrai de modifier cet enregistrement, veuillez valider vos modification plus tard ");
        }

        entity.setVersion(newVersion);
    }


    @Override
    public void deleteEntity(Entity entity) {
        getSqlMapClientTemplate().delete("deleteEntity", entity);
    }
  }

  • Modifier le fichier de configuration d'iBatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap>

 <typeAlias alias="Entity" type="votrePackage.domain.Entity"/>

 <resultMap id="EntityMap" class="Entity">
     <result column="id" property="id"/>
     <result column="value" property="value"/>
     <result column="version" property="version"/>
 </resultMap>

 <insert id="insertEntity" parameterClass="Entity">
     INSERT INTO entity (id, value, version) VALUES (#id#, #value#, 1)
 </insert>

 <select id="findEntityById" parameterClass="java.lang.Long" resultClass="Entity" resultMap="EntityMap">
         SELECT id, value, version FROM entity WHERE id=#value#
 </select>

 <update id="updateEntity" parameterClass="java.util.Map">
     UPDATE entity
     SET
         value=#entity.value#
         version=#newVersion#
     WHERE
         id=#entity.id#
         AND version=#oldVersion#
 </update>

 <delete id="deleteEntity" parameterClass="Entity">
     DELETE FROM entity WHERE id=#id#
 </delete>

</sqlMap>

Et voilà votre entité est prête à être utiliser dans un contexte multi urilisateur.

N'hésitez pas à me laisser vos commentaires.

Aucun commentaire:

Enregistrer un commentaire