Flux RSS

mardi 30 mai 2006

DV et Linux, ça marche!

J'ai branché en Firewire un camescope DV sur mon PC, j'ai lancé kino, et .. magie, tout a fonctionné du premier coup! L'acquisition du contenu de la casette DV ou d'un live est parfaite, aucune trame n'est perdue.

Par contre, pour le montage, c'est bien plus galère. Kino est fâché avec ma version des mjpegtools et de ffmpeg : je ne peux pas exporter un montage! Je n'ai trouvé qu'une application propriétaire qui fonctionne bien, MainActor.

MAJ: J'ai recompilé ffmpeg et kino, tout fonctionne à présent.

mardi 16 mai 2006

Apple MacBook

Ça y est, Apple a enfin dévoilé le successeur de l'iBook, le MacBook. Avec les options nécessaires (Core Duo à 2GHz, 1Go de RAM, 80Go de disque), le geek s'en sort avec un total de 1500 € TTC.

C'est le portable que j'achèterais pour ma future entreprise. Pourquoi ? Tout d'abord parce qu'il est classe et que pour les démonstrations, ça compte; mais surtout parce que ayant un Mac, je vais pouvoir porter les logiciels de l'entreprise dessus (aussi bien la partie cliente que la partie serveur).

Maj: L'écran glossy, pas glop.

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...)