3 Replies Latest reply on Dec 15, 2008 10:57 AM by Julien Kronegg

    Hibernate yes_no for char(1) vs seam-gen

    Valerie Griffin Newbie
      I added the following code to my project's seam-gen.reveng.xml expecting it to let my CHAR(1) Y/N flags be mapped appropriately.

        <type-mapping>

          <sql-type jdbc-type="CHAR" length='1' hibernate-type="yes_no" />

        </type-mapping>

      It helped, but wasn't quite perfect.

      One of my new booleans was art of a composite key. The isDefinedId method included code like:

         if (getTblId().getFlag() == 0) return false;

      Because "flag" was my new boolean, that line didn't exactly compile. I looked at seam-gen/src/EntityHomne.java.ftl and found a test under isDefinedId where that code was generated if it thought the type was a primitive. After other experimentation, I think it might have corrected itself if I had removed and rebuilt the project, but I removed the "else" and its generated code because I want to permit zero values by default. (Initially, I just wanted to protect booleans against that compare.)

      Once I was past the compilation error, I ran into another problem. This one seems to be a reported issue with hibernate. I got an error message for the first one of these booleans it found in my database. The message indicated that a smallint was expected. I wandered over to the hibernate forum and did a little exploring. The entity declaration is supposed to include a line:

          @Type(type = "yes_no")

      but hibernate doesn't insert the line. I found an issue under hibernate tools. The workaround described included a change to hibernate's templates/pojo/Ejb3PropertyGetAnnotation.ftl file.

      I couldn't find that file on my system. I did find seam-gen/pojo/GetPropertyAnnotation.ftl which looked like a good place to change.

      I added the following lines at the end:

      <#if pojo.getJavaTypeName(property, jdk5)="Boolean">
          @${pojo.importType("org.hibernate.annotations.Type")}(type="yes_no")
      </#if>

      This code marks all Booleans as hibernate yes_no types. It will work for us, but is not a general solution. The real solution should occur whenever hibernate gets fixed.

      I'm using ICEFaces so the files are really under icefaces-staging.
      Having done all of that, seam-gen gives me something that's close, but has a peculiarity all its own.

      I've got an entity with two booleans.

      In lists, the booleans are shown as true or false. When I request Edit, I get nice little checkboxes for my booleans, both of which are marked as required. (The database requires Y or N.) Ir I press Save without checking either one, or if I check either one, each one displays a message:
          length must be between 0 and 1

      That message seems supremely inappropriate for a checkbox! At this time, I have no idea how to enter data using my nifty little checkbox.

      If I figure anything out, I'll post it. In the meantime, any suggestions???
        • 1. Re: Hibernate yes_no for char(1) vs seam-gen
          Francisco Jose Peredo Noguez Master

          Please post the generated code in the .xhtml file for your checkboxes.

          • 2. Re: Hibernate yes_no for char(1) vs seam-gen
            Valerie Griffin Newbie
            I solved the problem, but thanks for offering to help.

            I figured out that hibernate validation was being a little too enthusiastic. The entity included a decoration of:
              @Length(max = 1)

            for my column. I removed the @Length annotations and it worked.

            For my next trick, I made another change to the GetPropertyAnnotation.ftl file. That file adds the @Length annotation. I changed the line:

              <#if !c2h.isManyToOne(property) && !c2h.isTemporalValue(property) && column.length!=255 && property.type.name!="character">

            to:

              <#if !c2h.isManyToOne(property) && !c2h.isTemporalValue(property) && column.length!=255 && property.type.name!="character" && pojo.getJavaTypeName(property, jdk5)!="Boolean">
             
            Generating again gives me exactly the annotations I want.

            There's still a minor outstanding issue, though, and I'm not sure what the "real" best answer is. The Boolean is not initialized by code. Because I've set the database column to NotNull, the fields are marked as "required." Checkboxes are initialized to false, but the * indicating that the field is required is displayed. Unless the checkbox can truly be displayed as an uninitialized (typically gray) value, it shouldn't be marked as required. (I do agree that the generated code correctly marks the value as required. This is more of a point with the checkbox control designers.)