javahibernatejpainheritancelongtext

Hibernate: Additional annotation to Column from inheritance


I have a class

@MappedSuperclass
public abstract class MyAbstractProperty <T extends Object>{

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    @Column(name="defaultValue")
    protected T defaultValue;

//...

}

Which is basis for sub classes like class MyLongProperty extends MyAbstractProperty<Long>{}. This works fine. The problem arises when I want to store Text in the class class MyStringProperty extends MyAbstractProperty<String>{}.

I have learned that hibernate per default stores Strings only with max 255 chars (see: JPA: "Data too long for column" does not change). Therefore my defaultValuewould need an additional annotation like:

@Entity
class MyStringProperty extends MyAbstractProperty<String>{

    @Type(type="org.hibernate.type.StringClobType")
    @Column(name="defaultValue")
    protected String defaultValue; // problem since defaultValue is already defined in MyAbstractProperty<>.
}

How can I ensure this since the defaultvalue is already defined in MyAbstractProperty? I don't think it is ok to move the type annotation to MyAbstractProperty since this might have side effects on other classes like MyLongProperty.

For example when I was setting @Lob in MyAbstractProperty the SQL definition of MyStringProperty included DEFAULTVALUE BLOB(255) instead of DEFAULTVALUE BIGINT.

Additional question: There seem to be different options for defining the column as text data (e.g. @Type(type="org.hibernate.type.StringClobType"), @Lob) Where are the maijor differences in these options. What best to take. (My main database is HyperSQL, but I also target for SQLite, MariaDB and MySQL).

Edit

Based on the recent feedback it seems like the solution might be abstract getters/setter. I have to check what are the implications on this on my code.

I had an alternative - not finished - idea, which might cause less modifictions of my code. Is it possible to define a class

class MyText extendes String; 

such as that all instances of MyText are automatically stored as @Lob? Than I would just have to modify MyAbstractProperty<String> to MyAbstractProperty<MyText>.


Solution

  • You could leave only an abstract getter in the superclass, and define the field in subclasses:

    @MappedSuperclass
    public abstract class MyAbstractProperty<T extends Object>{
    
        @Id
        @GeneratedValue(strategy = GenerationType.TABLE)
        private Long id;
    
        public abstract T getDefaultValue();
    }
    
    @Entity
    class MyStringProperty extends MyAbstractProperty<String>{
    
        @Type(type="org.hibernate.type.StringClobType")
        @Column(name="defaultValue")
        protected String defaultValue;
    
        @Override
        public String getDefaultValue() {
            return defaultValue;
        }
    }
    

    In order to avoid boilerplate for all other cases which don't require special treatment, you can simply create another abstract class which contains default mapping, and then extend other entities from it:

    @MappedSuperclass
    public abstract class MyDefaultProperty<T> extends MyAbstractProperty<T extends Object> {
    
        @Column(name="defaultValue")
        protected T defaultValue;
    
        @Override
        public T getDefaultValue() {
            return defaultValue;
        }
    }