Is it possible to make @Formula annotation lazily loaded?

Yes . Just annotating the fields/getter of the @Formula property by @Basic(fetch=FetchType.LAZY) and use this ant task provided by hibernate to do the bytecode instrumentation for the entity class. Otherwise , LAZY loading for the @Formula property is silently ignored.

The documentation contains the info on how to use this ant task to do bytecode instrumentation.


I tried with BytecodeEnhancement (Maven Plugin) but doesnt work. So I made this:

  1. Create a Class (FooFormula.java), map it to the table with two field, one for the @id and other for the @Formula.

     @Entity
     @Table(name = "BAR_TABLE")
     public class FooFormula implements Serializable {
    
      private Long idBarTable;
      private Long formula;
    
      public FooFormula() {
        super();
      }
    
      public FooFormula(String idBarTable) {
          super();
          this.idBarTable = idBarTable;
      }    
    
      @Id
      @Column(name = "ID_BAR_TABLE", unique = true, nullable = false, length = 20)
      public Long getIdBarTable() {
          return this.sitidBarTableCodigo;
      }
    
      public void setIdBarTable(Long idBarTable) {
          this.idBarTable = idBarTable;
      }
    
      @Formula("(SELECT 1 from DUAL)")
      public Long getFormula() {
        return formula;
      }
    
      public void setFormula(Long formula) {
        this.formula = formula;
      }
    }
    
  2. Add this new class (FooFormula.java) as a field to your Entity with @ManyToOne and @JoinColumn

     @Entity
     @Table(name = "BAR_TABLE")
     public class Bar implements Serializable {
    
      private Long idBarTable;
      private Long somOtherColumn;
      private FooFormula fooFormula;
    
      public Bar() {
        super();
      }
    
      public Bar(String idBarTable) {
          super();
          this.idBarTable = idBarTable;
      }    
    
      @Id
      @Column(name = "ID_BAR_TABLE", unique = true, nullable = false, length = 20)
      public Long getIdBarTable() {
          return this.sitidBarTableCodigo;
      }
    
      public void setIdBarTable(Long idBarTable) {
          this.idBarTable = idBarTable;
      }
    
      @ManyToOne(fetch = FetchType.LAZY)
      @JoinColumn(name = "ID_BAR_TABLE", nullable = false, insertable=false, updatable=false)
      public FooFormula getFooFormula() {
        return fooFormula;
      }
    
      public void setFooFormula(FooFormula fooFormula) {
        this.fooFormula = fooFormula;
      }
    }
    

I saw in the comment that you would like to achieve this without bytecode instrumentation. This can be achieved by implementing the FieldHandled interface and by modifying the getters and setters for the lazy field.

HBM

<property name="deletable" type="true_false" lazy="true">
  <formula>(select something from other tables and such....)</formula>
</property>

JAVA

import org.hibernate.bytecode.javassist.FieldHandled;
import org.hibernate.bytecode.javassist.FieldHandler;
public class Person implements FieldHandled {

/* allows lazy formulas without hibernate bytecode instrumentation */
private FieldHandler fieldHandler;
public FieldHandler getFieldHandler() { return fieldHandler; }
public void setFieldHandler(FieldHandler fieldHandler) { this.fieldHandler = fieldHandler; }


private Boolean deletable;

public void setDeletable(Boolean deletable) {
    if(fieldHandler!=null)
        fieldHandler.writeObject(this, "deletable", this.deletable, deletable);
    this.deletable = deletable;
}

public Boolean getDeletable() {
    if(fieldHandler!=null)
        return (Boolean)fieldHandler.readObject(this, "deletable", deletable);
    return deletable;
}
}

Another example can be found here. But that is lazy loading a one-to-one relationship.