views:

35

answers:

2

How to create mapping in hibernate that depends on the type property, insert/retrieve the data into/from proper column.

Structure:

TABLE COLUMNS:

|TYPE | CHARACTER | DATE | TIME | NUMERIC|

POJO:

class Pojo {

 private int type;
 private Object data;

 ...

}

Examples:

  • Insert/Update
    If the type is 1 we input the value to column CHARACTER

  • Select
    If the type is 2 we get the value from column NUMERIC

TIP: The structure where we have two columns and we PIVOT the result is not a option for this case.

+1  A: 

This kind of behavior is accomplished by using encapsulation. For instance, i have a String (Y/N) column in database (INSERT/UPDATE) which is encapsulated by a boolean (SELECT) as follows

public class SomeEntity {

    private boolean checked;

    private boolean isChecked() {
        return this.checked;
    }

    public void setChecked(boolean checked) {
        this.checked = checked;
    }

    public String getCheckedAsString() {
        return checked ? "Y" : "N";
    }

    public void setCheckedAsString(String checked) {
        this.checked = checked.equals("Y") ? true : false;
    }

}

Your mapping goes here

<property name="checkedAsString" type="string" column="CHECKED"/>

This strategy is explained here I have used, besides conversion, as a workaround To allow String Java keywords To be used as Enum. See here

Arthur Ronald F D Garcia
@Arthur Ronald F D Garcia: Close but this do not entirety solve my problem. As solution i have choose the table per class hierarchy mapping with integer discriminator. That is some extend version of the encapsulation.
Vash
+1  A: 

The solution that i have choose for this is table per class hierarchy mapping with an integer discriminator.

I have created a base abstract generic class that store the object

 public abstract class ValueBase<T> {

   private Long id; 
   private int valueType;
   private T value;

   public T getValue(){
     return value;
   }

   public void setValue(T value){
     this.value = value;
   }

   protected void setValueType(int valueType) {
      this.valueType = valueType;
   }

   public int getValueType(){
     return this.valueType;
   }

   private void setID(Long id) {
      this.id = id;
   }

   public int getID(){
     return this.id;
   }


 }

For Type management i have created and interface, but there is possible to enumeration using the encapsulation presented by Arthur.

public interface IValueTypes() {

 public static final int NONE = -1;
 public static final int NUMERIC = 0;
 public static final int CHARACTER = 1;
 public static final int DATE = 2;
 public static final int TIME = 3;
 public static final int BOOLEAN = 4;

}

The for each type I have created class

 public class NumericType extedns ValueBase<BigDecinal> {

    public NumericType(){
      super();
      setValueType(IValueTypes.NUMERIC);
    }

 }

 public class CharacterType extedns ValueBase<String> {

    public NumericType(){
      super();
      setValueType(IValueTypes.CHARACTER);
    }

 }

TIP: To allow use the a number as discriminator value we need to specify it first for the class that we are mapping, because by default is used class name [String] and i we try to use the numeric discriminator for subclass mapping we will get a hibernate error say that there is some type mismatch.

<class name="TestValue" table="TestValues" schema="TEST" abstract="true" discriminator-value="-1"> 
  <id name="id" type="java.lang.Long">
    <column name="VALUE_ID" precision="22" scale="0" />
    <generator class="native"/>
  </id>

  <discriminator column="TYPE_VALUE" not-null="false" type="integer"/> 

  <subclass discriminator-value="0" name="NumericType">
    <property name="value" type="java.math.BigDecimal" column="NUMERIC" not-null="false"/>
  </subclass>   

  <subclass discriminator-value="1" name="CharacterType">
    <property name="value" type="java.lang.String" column="CHARACTER" not-null="false"/>
  </subclass>   

</class>

While we retrieve the object from database is always in given typed class that we can operate easily on it, and we use one place to save them by saving the base class.

Vash
@Vash Thank you for providing your solution (+1)
Arthur Ronald F D Garcia