views:

22

answers:

1

Hi, I have an entity

@Entity
@NamedQueries({
    @NamedQuery(name = "Item.findAll", query = "select i from Item i"),
})
public class Item implements Serializable, WithId, WithNameDescription {
    @Lob
    byte[] photo;
    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
    TextualInfo english = new TextualInfo();
// more entry field, getters and setters
}

When I call the Query Item.findAll, I assume that all the bytes[] get into memory. But I won't use it. So I don't want to fetch it. Is there a way, how to specify the fact that I want lazily load the photo in the jpql query?

A: 

By default, persistent properties are loaded eagerly and you can't control this from JPQL. However, you can try to change the default behavior and make the photo lazy with the Basic annotation. From the JPA specification:

9.1.18 Basic Annotation

The Basic annotation is the simplest type of mapping to a database column. The Basic annotation can be applied to a persistent property or instance variable of any of the following types: Java primitive types, wrappers of the primitive types, java.lang.String, java.math.BigInteger, java.math.BigDecimal, java.util.Date, java.util.Calendar, java.sql.Date, java.sql.Time, java.sql.Timestamp, byte[], Byte[], char[], Character[], enums, and any other type that implements Serializable. As described in Section 2.1.6, the use of the Basic annotation is optional for persistent fields and properties of these types.

@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Basic {
FetchType fetch() default EAGER;
boolean optional() default true;

The FetchType enum defines strategies for fetching data from the database:

public enum FetchType { LAZY, EAGER };

The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified. In particular, lazy fetching might only be available for Basic mappings for which property-based access is used.

Something like this:

@Lob @Basic(fetch=LAZY)
public byte[] getPhoto() { return photo; }

But as mentioned in the spec, this is just a hint and might not be supported. In that case, an alternative would be to use a lazy loaded mandatory one-to-one association with another entity (holding the blob).

References

  • JPA 1.0 specification
    • Section 9.1.18 "Basic Annotation"
    • Section 9.1.19 "Lob Annotation"
Pascal Thivent
So basically, it's not possible with jpql?
coubeatczech
@coubeatczech No, this is not possible without modifying the code, this is not something you can control from JPQL. I clarified my answer.
Pascal Thivent