Flux RSS

mercredi 10 mai 2006

Hibernate Annotations, MySQL et les LONGBLOB

Attention, je partage ici un un mémo personnel, car je pense qu'il peut être utile. Le vocabulaire n'est pas forcément académiquement correct, si vous trouvez des coquilles, vos commentaires sont les bienvenus. Pour comprendre ce qui suit, vous devez être familier avec Hibernate!

Pour stocker dans MySQL des gros blobs, jusqu'à 2Go, il faut utiliser les types LONGBLOB et LONGTEXT, car les blobs de base sont limités à 64ko.

Dans Hibernate Annotations, pour la définition d'un blob dans une entitée (@Entity), il ne faut donc pas utiliser l'annotation @Lob, mais à la place @Column(columnDefinition="LONGBLOB") pour du binaire, ou @Column(columnDefinition="LONGTEXT") pour du texte.

Par exemple:

  @Entity
  public class Revision implements Serializable {
     Long  id;
     Date creationDate = new Date ();
     String creationComment;
     byte  binaryContent;
     String textualContent;
     @Id
     @GeneratedValue
     public Long getId () {
        return id;
     }
     public void setId (Long id) {
        this.id = id;
     }
     @Temporal(TemporalType.TIMESTAMP)
     public Date getCreationDate () {
        return creationDate;
     }
     public void setCreationDate (Date creationDate) {
        this.creationDate = creationDate;
     }
     public String getCreationComment () {
        return creationComment;
     }
     public void setCreationComment (String creationComment) {
        this.creationComment = creationComment;
     }
     @Column(columnDefinition="LONGBLOB")
     public byte getBinaryContent () {
        return binaryContent;
     }
     public void setBinaryContent (byte binaryContent) {
        this.binaryContent = binaryContent;
     }
     @Column(columnDefinition="LONGTEXT")
     public String getTextualContent () {
        return textualContent;
     }
     public void setTextualContent (String textualContent) {
        this.textualContent = textualContent;
     }
  }

Quand une entitée est chargée par Hibernate, tous ses attributes sont récupérés depuis la base de données (Eager loading). Donc si cette entitée contient des blobs, tous les blobs seront lus. Inutile de vous dire que cela peut rapidement mettre à genou la base de données, même la rapide MySQL.

Pour corriger ce problème, il existe deux solutions. La première consiste à créer pour chaque blob un entitée, car le chargement des collections (les liens entre les objets, comme les pointeurs, vecteurs, etc etc) est dynamique (Lazy loading).

La seconde solution consiste à activer le chargement dynamique des attributs. Il faut pour cela spécifier ledits attributs par une annotation.

  ...
  @Basic(fetch=FetchType.LAZY)
  @Column(columnDefinition="LONGBLOB")
  ...
  @Basic(fetch=FetchType.LAZY)
  @Column(columnDefinition="LONGTEXT")
  ...

Mais cela ne suffit pas : si le code n'est pas instrumenté (=bytecode passé à une moulinette spéciale), l'annotation est SILENCIEUSEMENT IGNOREE. Pour l'instrumentation, une tâche Ant est fournie. Pour l'utiliser, par exemple:

  <target name="instrument">
     <taskdef name="instrument" classname="org.hibernate.tool.instrument.cglib.InstrumentTask">
        <classpath refid="l'id de la définition du classpath avec les .jar"/>
     </taskdef>
     <instrument verbose="true">
        <fileset dir="le dossier où sont les .class à instrumenter">
           <include name="*.class"/>
        </fileset>
     </instrument>
  </target>

Nota: Le MySQL de la Mandriva 2006 a un bug, il faut l'utiliser avec le driver JDBC Connector/J 3.0.17 et pas une version supérieure! (j'ai perdu une demi-journée avant de trouver le problème...)

Les aides à la création d'entreprise

La recherche et l'obtention des aides à la création et au développement d'entreprise, c'est ... galère. J'ai trouvé un peu par hasard une solution intéressante à ce problème : je vais passer par un consultant qui fait le job chiant et réverbératif pour une rémunération au résultat, avec un maximum de 15% des montants obtenus. Ce consultant a pour mission de rechercher les aides disponibles et de monter les dossiers nécessaires. Que de temps de gagné pour l'entrepreneur!

Si cette expérience est probante, je vous donnerais plus de détails.

Ikea est passé par là!

A force de bosser 10h par jour avec un siège trop bas (vérin hydraulique cassé), je me suis un peu abîmé : douleurs aux poignets, puis à l'avant bras, puis au bras, puis au dos et au cou! J'ai décidé d'agir avant d'être incapable d'utiliser une clavier. Je suis passé de ça (120 x 60 cm):

À ça (160 x 80 cm):

Le nouveau bureau est plus profond, ce qui me permet enfin de poser mes avant bras pour tapoter sur mon clavier. Mais aussi et surtout, ce bureau est réglable en hauteur: je l'ai réglé pour être un peu plus bas que la moyenne, ce qui est plus confortable. Je n'ai plus qu'à trouver un siège neuf qui me convient pour être un chouilla plus haut, et ce sera parfait.

Mais cette histoire de changement m'a aussi donné envie de zapper mon vaillant 17 pouces Sony Multiscan 200sx âge de huit ans (du très bon matériel) contre un écran LCD 20 pouces en 16/10°. Hélas, ce n'est financièrement pas raisonnable :-(