views:

83

answers:

2

Hello...

I write an application based on an already existing database (postgreSQL) using JPA and Hibernate. There is a int2-column (activeYN) in a table, which is used as a boolean (0 => false (inactive), not 0 => true (active)). In the Java application i want to use this attribute as a boolean. So i defined the attribute like this:

@Entity
public class ModelClass implements Serializable {    
  /*..... some Code .... */
  private boolean active; 

  @Column(name="activeYN")
  public boolean isActive() {
    return this.active; 
  }
 /* .... some other Code ... */

}

But there ist an exception because Hibernate expects an boolean database-field and not an int2. Can i do this mapping i any way while using a boolean in java??

I have a possible solution for this, but i don't really like it: My "hacky"-solution is the following:

@Entity
public class ModelClass implements Serializable {    
  /*..... some Code .... */
  private short active_USED_BY_JPA; //short because i need int2

  /**
   * @Deprecated this method is only used by JPA. Use the method isActive()
   */
  @Column(name="activeYN")
  public short getActive_USED_BY_JPA() {
    return this.active_USED_BY_JPA;
  }

  /**
   * @Deprecated this method is only used by JPA. 
   * Use the method setActive(boolean active)
   */
  public void setActive_USED_BY_JPA(short active) {
    this.active_USED_BY_JPA = active; 
  }

  @Transient //jpa will ignore transient marked methods
  public boolean isActive() {
    return getActive_USED_BY_JPA() != 0; 
  }

  @Transient
  public void setActive(boolean active) {
    this.setActive_USED_BY_JPA = active ? -1 : 0;
  }

 /* .... some other Code ... */

}

Are there any other solutions for this problem?

The "hibernate.hbm2ddl.auto"-value in the hibernate configuration is set to "validate".

(sorry, my english is not the best, i hope you understand it anyway)..

A: 

The solution is to use a custom value type.

Aaron Digulla
A: 

Well, the problem is that int2 is used store signed two-byte integer, regardless of how you use it and Hibernate doesn't have any knowledge of your logic to translate the value into a boolean at the Java level.

So you'll have to use your hacky solution (i.e. read the int2 column in a short and convert it in your entity) that you could maybe make things a bit sexier by moving annotations on attributes:

@Entity
public class ModelClass implements Serializable {    
  /*..... some Code .... */

  @Column(name="activeYN")
  private short active; 

  public boolean isActive() {
    return this.active!=0; 
  }
 /* .... some other Code ... */

}

Or, if using a JPA extension is not a problem (JPA dosen't support custom types), use a custom type that you declare with the @Type annotation:

@Entity
public class ModelClass implements Serializable {    
  /*..... some Code .... */
  private boolean active; 


  @org.hibernate.annotations.Type(type = "my.package.ShortToBooleanUserType")
  @Column(name="activeYN")
  public boolean isActive() {
    return this.active; 
  }
 /* .... some other Code ... */

}

Where ShortToBooleanUserType is a class that implements either org.hibernate.UserType or org.hibernate.CompositeUserType (refer to the documentation) and does the conversion in both direction.

Pascal Thivent
Thank you. I took your second solution, it worked well. I'm not totally pleased using hibernate specific annotations, but it's anyhow better than my "hacky" solution. And i will never replace hibernate with another framework based on the JPA... (hopefully)..Your first solution would have worked as well, but i don't like it, because hibernate is using reflections to set the attributes this way. And since i'm already done with the rest of the model classes (using the getter method), i don't want to change it. And you should not use both methods at the same time.
mg