views:

65

answers:

1

In my Hibernated system, I have a class Picture that has some simple data, a list of Installations and some (huge) binary data. The list of Installations is implemented with a join table, as it's a ManyToMany relation, and it's defined on the Installation side:

@Entity
public class Picture {
  @Id
  private long pictureId;
  private String mimeType;
  @Lob
  @Basic(fetch=FetchType.LAZY) // Don't load all data unless required
  private byte[] picture;

  @ManyToMany(mappedBy= "images")
  private List<Installation> installations;

  /** This should be used only to load partial objects through PictureDao */
  public Picture(long pictureId, String mimeType, List<Installation> insts) {
    this.pictureId = pictureId;
    this.mimeType = mimeType;
    this.installations = insts;
  }
...
}

The constructor is there solely to allow partial selects.

@Entity
public class Installation {
  @Id
  private long id;
  @ManyToMany(cascade=CascadeType.PERSIST)
  @JoinTable(name="InstPicture",
     joinColumns={@JoinColumn(name="installationId")},
     inverseJoinColumns = {@JoinColumn(name="pictureId")})
  @OrderBy("pictureDate ASC")
  private List<Picture> images;
  ...
}

I'd like to be able to make a partial select that inlucdes the list of Installations, but not the picture data. I have tried the obvious solution:

Query q = em.createQuery("SELECT new Picture" +
  "(p.pictureId, p.mimeType, p.installations) " +
  " FROM Picture p WHERE p.pictureId = :id");

but it claims it cannot find the constructor. If I don't include the installations in the select, the field becomes null rather than a lazy loader for the list. I have also tried joining p.installations in, and it still can't find the constructor. Without the list of Installations, it works beautifully.

Is there a way to get a Collection into my partial select?

Thanks, -Lars

+1  A: 

You can't use a collection-valued path-expression in a constructor expression. Quoting the JPA 1.0 specification:

4.8 SELECT Clause

The SELECT clause denotes the query result. More than one value may be returned from the SELECT clause of a query.

The SELECT clause may contain one or more of the following elements: a single range variable or identification variable that ranges over an entity abstract schema type, a single-valued path expression, an aggregate select expression, a constructor expression.

The SELECT clause has the following syntax:

select_clause ::= SELECT [DISTINCT] select_expression {, select_expression}*
select_expression ::=
         single_valued_path_expression |
         aggregate_expression |
         identification_variable |
         OBJECT(identification_variable) |
         constructor_expression
constructor_expression ::=
         NEW constructor_name ( constructor_item {, constructor_item}* )
constructor_item ::= single_valued_path_expression | aggregate_expression
aggregate_expression ::=
         { AVG | MAX | MIN | SUM } ([DISTINCT] state_field_path_expression) |
         COUNT ([DISTINCT] identification_variable | state_field_path_expression |
                   single_valued_association_path_expression)

JPA 2.0 gives you a bit more of power for the constructor_item (see this answer) but, still, you won't be able to pass a collection-valued path-expression.

Pascal Thivent