Search code examples
hibernatejpajpqlnamed-query

JPA2 (Hibernate) how to query 2 tables (joined) but only need certains properties from 2nd table


I am using JPA2 with hibernate as provider in java ee6 environment.

I have a one to many relationship and when getting all the rows for the one side to display in a JSF page, I want to display some of the many side's properties, ** but not all ** and even avoid loading those properties them when populating the many side entities and I am not sure how to do that.

here is a snippet

I want to get all rows for table A and display them in jsf table, when displaying rows for table A, I want to also display some properties from table B in same jsf table, and ideally not even retrieve/store the unused properties from table B

TBL_A
________________
int     ID
varchar FIRSTNAME
varchar LASTNAME

and the second is

TBL_B
___________
int      ID
varchar  VERSION  // display on jsf page
varchar  XML_DATA //large, don't want to load when getting results for A/B join
int      A_ID     

and my JPA2 associated class's are like so

@Entity
@Table(name = "TBL_A")
@NamedQueries // not sure what sql to create to accomplish this?
({ @NamedQuery(name = "A_and_B.findAll", query = "SELECT a FROM EntityA a") })

public class EntityA implements Serializable 
{    
   @Id
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   @NotNull
   @Column(name = "ID", nullable = false)
   private Integer id;
.

@Column(name = "FIRSTNAME")
private String firstname;
.
@Column(name = "LASTNAME")
private String lastname;
.
@OneToMany(mappedBy = "entityA", fetch = FetchType.EAGER)
private List<EntityB> entityBList;

and my TBL_B associated entity is

@Entity
@Table(name = "TBL_B")  
public class EntityB implements Serializable 
{ 
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@NotNull
@Column(name = "ID", nullable = false)
private Integer id;
.        
@Column(name = "VERSION")
private String version;
.
@Column(name = "XML_DATA")
private String xmlData;
.
@JoinColumn(name = "A_ID", referencedColumnName = "ID")
@ManyToOne
private EntityA entityA;    

I have a JSF page that displays a datatable/list of TBL_A entries and also the VERSION column from TBL_B, when getting all the rows for TBL_A.

I had to use the fetch type of EAGER to avoid hibernate lazy instatiation error to do that. hope thats the correct way to do it.

when loading all the TBL_B entities I guess I don't mind eagerly loading all TBL_B rows in entityBList, but I don't want the list of EntityB beans to have thier xmlData property loaded cause it is significantly large.

can someone explain how I can do this?

how can i make this happen with my named query

public List<EntityA> findAll_A_Entities() 
{
   return em.createNamedQuery("A_and_B.findAll", EntityA.class).getResultList();
}

Solution

  • One solution is to make the property lazy - but that requires additional build configuration - refer to the doc.

    The other option is to move the xmlData Field to a derived class and use hibernate inheritance support.

    If you were querying EntityB directly you can use projection query to selected only the required fields. When it is in a collection association that is not possible.