title: Lazy fetching single column (class attribute) with Hibernate
body: <p>I have an old table that I'm working with, which looks like this:</p>
  
  <pre><code>+------------------+--------------+------+-----+---------+-------+
  | Field            | Type         | Null | Key | Default | Extra |
  +------------------+--------------+------+-----+---------+-------+
  | BINARY_DATA_ID   | varchar(255) | NO   | PRI |         |       |
  | BINARY_DATA      | longblob     | YES  |     | NULL    |       |
  | BINARY_DATA_NAME | varchar(255) | YES  |     | NULL    |       |
  +------------------+--------------+------+-----+---------+-------+
  </code></pre>
  
  <p>The main problem with this is that the <code>BinaryData</code> Java class loads the <code>BINARY_DATA</code> column, even if I only require the <code>BINARY_DATA_NAME</code>. I know that the best way to architect this is to split the data from the meta-data (like the file name) so they live in separate tables. From there it's trivial to make the data lazy-loaded. This is how it should have been done in the first place.</p>
  
  <p>Unfortunately it may not be possible for me to do the above due to organizational constraints. As a workaround, is it possible to make that column lazy-loaded using some annotations instead of splitting things out into separate tables? I've modified the <code>BinaryData</code> class so that it has an inner static <code>BinaryDataData</code> class which is <code>@Embedded</code> and the attribute is <code>@Basic(fetch=FetchType.LAZY)</code>:</p>
  
  <pre><code>@Entity
  @Table
  @Proxy(lazy=false)
  @Inheritance(strategy=InheritanceType.JOINED)
  public class BinaryData implements Serializable, Persistable&lt;BinaryData&gt;, Cloneable {
  
      private static final long serialVersionUID = /** blah */;
  
      @Id @Column @GeneratedValue(generator="uuid") @GenericGenerator(name="uuid", strategy="uuid")
      private String id;
  
      @Column
      private String binaryDataName;
  
      @Embedded
      @Basic(fetch = FetchType.LAZY)
      private BinaryDataData binaryData;
  
      @Transient
      private String cacheId;
  
      /**
       * Hibernate constructor
       */
      public BinaryData() { /* Creates a new instance of Attachment. */}
  
      public BinaryData(byte[] binaryData, String binaryDataName) {
          this.binaryData = new BinaryDataData(ArrayUtils.clone(binaryData));
          this.binaryDataName = binaryDataName;
      }
  
      /**
       * Returns the BinaryData byte stream.
       *
       * @return binaryData byte stream
       */
      @Embedded
      @Basic(fetch = FetchType.LAZY)
      public byte[] getBinaryData() {
          if (this.binaryData == null) {
              return new byte[0];
          }
          return binaryData.getActualData();
      }
  
      @Embeddable
      public static class BinaryDataData implements Serializable {
          @Column(length=32*1024*1024, columnDefinition="longblob", name="BINARY_DATA") @Lob
          private byte[] actualData;
  
          public BinaryDataData() { }
  
          public BinaryDataData(byte[] data) {
              this.actualData = data;
          }
  
          public byte[] getActualData() {
              if (this.actualData == null) {
                  return new byte[0];
              }
              return this.actualData;
          }
  
          public void setBinaryData(byte[] newData) {
              this.actualData = newData;
          }
  
          @Override public boolean equals(Object obj) {
              if (this == obj) {
                  return true;
              }
              if (obj == null) {
                  return false;
              }
              if (!(obj instanceof BinaryDataData)) {
                  return false;
              }
              final BinaryDataData other = (BinaryDataData) obj;
              if (!Arrays.equals(actualData, other.actualData)) {
                  return false;
              }
              return true;
          }
      }
  
      /** onwards... */
  </code></pre>
  
  <p>Unfortunately this doesn't work. The SQL that I'm seeing still shows a complete fetch of the object even if the binary data isn't requested:</p>
  
  <pre><code>select ideaattach0_.BINARY_DATA_ID as BINARY1_9_, ideaattach0_1_.BINARY_DATA as BINARY2_9_, ideaattach0_1_.BINARY_DATA_NAME as BINARY3_9_, ideaattach0_.IDEA_BUCKET_ID as IDEA2_136_ from IDEA_ATTACHMENT ideaattach0_ inner join BINARY_DATA ideaattach0_1_ on ideaattach0_.BINARY_DATA_ID=ideaattach0_1_.BINARY_DATA_ID where ideaattach0_.BINARY_DATA_ID=?
  </code></pre>
  
  <p>Any ideas? Thank you.</p>