Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » EclipseLink » 3 table cascade reference @JoinFetch
3 table cascade reference @JoinFetch [message #1061197] Thu, 30 May 2013 13:36 Go to next message
alex alex is currently offline alex alex
Messages: 3
Registered: May 2013
Junior Member
Hi,
I have problem joining 3 tables in cascade reference Foreign key
I have 3 Entities for tables A,B an C

A OneToMany B ( B ManyToOne A )
B OneToMany C ( C ManyToOne B )

I have corrected generated the code and followed the following post

vard-lokkur.blogspot.it/2010/09/jpa-demystified-episode-1-onetomany-and.html

annotating the entities with @JoinFetch like in the example.

Now the problem:
I'd want retrieve the Object A and B and C all in ONE query,but the generated query ( logged and logged in the example too ) make a Join only from A and B.
I can have all 3 Entities retrieved in Join only if I retreive B ( like in the example ).

Is there a way to have a 3 level join query starting from root entity (A) without use a @NamedQuery?

thank you very much.





Re: 3 table cascade reference @JoinFetch [message #1061251 is a reply to message #1061197] Thu, 30 May 2013 18:53 Go to previous messageGo to next message
Chris Delahunt is currently offline Chris Delahunt
Messages: 1023
Registered: July 2009
Senior Member
Can you show how and where you added the @JoinFetch annotation, and the SQL that is generated?

You might want to try using batch fetching using @BatchFetch instead of a join over multiple 1:M and M:M relationships, as join fetching Bs and Cs in the same query could potentially be quite few results to parse for each A entity. It might be more efficient if you split it into 3 queries rather than returning NxM row results for each instance.
Re: 3 table cascade reference @JoinFetch [message #1061324 is a reply to message #1061251] Fri, 31 May 2013 08:31 Go to previous messageGo to next message
alex alex is currently offline alex alex
Messages: 3
Registered: May 2013
Junior Member
thanks for answer,

I have tried with @BatchFetch too but I have had less results,maybe I have make some mistake.

here's the generated query asking for find() on Entity A and the class code in @JoinFetch

SELECT DISTINCT t1.ID, t1.BUSINESS_NAME, t0.ID, t0.FIRST_NAME, t0.EMPLOYER_ID FROM employees t0, employers t1 WHERE ((t1.ID = ?) AND (t0.EMPLOYER_ID = t1.ID))

...ad you can see the Benefits table (Entity C ) as not been included in query

I'd want all the 3 entity in Join in one query....so I can make performance stress test to decide framework policy Smile
Then I can try with @BatchJoin too for performance test.

Thanks for help!!

here's the code:

Class EMPLOYERS ( Entity A )


import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.JoinFetchType;

@Entity
@Table(name = "employers")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Employers.findAll", query = "SELECT e FROM Employers e"),
@NamedQuery(name = "Employers.findById", query = "SELECT e FROM Employers e WHERE e.id = :id"),
@NamedQuery(name = "Employers.findByBusinessName", query = "SELECT e FROM Employers e WHERE e.businessName = :businessName")})
public class Employers implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Size(max = 128)
@Column(name = "BUSINESS_NAME")
private String businessName;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "employerId", fetch = FetchType.LAZY)
@JoinFetch(JoinFetchType.INNER)
//@BatchFetch(BatchFetchType.JOIN)
private List<Employees> employeesList;

public Employers() {
}

public Employers(Long id) {
this.id = id;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getBusinessName() {
return businessName;
}

public void setBusinessName(String businessName) {
this.businessName = businessName;
}

@XmlTransient
public List<Employees> getEmployeesList() {
return employeesList;
}

public void setEmployeesList(List<Employees> employeesList) {
this.employeesList = employeesList;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employers)) {
return false;
}
Employers other = (Employers) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "test.jpaperformance.entity.Employers[ id=" + id + " ]";
}

}







EMPLOYEES ( Entity B )


import java.io.Serializable;
import java.util.List;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.JoinFetchType;

@Entity
@Table(name = "employees")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Employees.findAll", query = "SELECT e FROM Employees e"),
@NamedQuery(name = "Employees.findById", query = "SELECT e FROM Employees e WHERE e.id = :id"),
@NamedQuery(name = "Employees.findByFirstName", query = "SELECT e FROM Employees e WHERE e.firstName = :firstName")})
public class Employees implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Size(max = 64)
@Column(name = "FIRST_NAME")
private String firstName;

@JoinFetch(JoinFetchType.OUTER)
//@BatchFetch(BatchFetchType.JOIN)
@OneToMany(cascade = CascadeType.ALL, mappedBy = "employeeId", fetch = FetchType.LAZY)
private List<Benefits> benefitsList;

@JoinColumn(name = "EMPLOYER_ID", referencedColumnName = "ID")
@JoinFetch(JoinFetchType.INNER)
//@BatchFetch(BatchFetchType.JOIN)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Employers employerId;

public Employees() {
}

public Employees(Long id) {
this.id = id;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

@XmlTransient
public List<Benefits> getBenefitsList() {
return benefitsList;
}

public void setBenefitsList(List<Benefits> benefitsList) {
this.benefitsList = benefitsList;
}

public Employers getEmployerId() {
return employerId;
}

public void setEmployerId(Employers employerId) {
this.employerId = employerId;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Employees)) {
return false;
}
Employees other = (Employees) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "test.jpaperformance.entity.Employees[ id=" + id + " ]";
}

}


BENEFITS ( Entity C )


import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.annotations.BatchFetch;
import org.eclipse.persistence.annotations.BatchFetchType;
import org.eclipse.persistence.annotations.JoinFetch;
import org.eclipse.persistence.annotations.JoinFetchType;

@Entity
@Table(name = "benefits")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Benefits.findAll", query = "SELECT b FROM Benefits b"),
@NamedQuery(name = "Benefits.findById", query = "SELECT b FROM Benefits b WHERE b.id = :id"),
@NamedQuery(name = "Benefits.findByBenefitType", query = "SELECT b FROM Benefits b WHERE b.benefitType = :benefitType"),
@NamedQuery(name = "Benefits.findByStartDate", query = "SELECT b FROM Benefits b WHERE b.startDate = :startDate"),
@NamedQuery(name = "Benefits.findByEndDate", query = "SELECT b FROM Benefits b WHERE b.endDate = :endDate"),
@NamedQuery(name = "Benefits.findByName", query = "SELECT b FROM Benefits b WHERE b.name = :name")})
public class Benefits implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "ID")
private Long id;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 64)
@Column(name = "BENEFIT_TYPE")
private String benefitType;
@Column(name = "START_DATE")
@Temporal(TemporalType.DATE)
private Date startDate;
@Column(name = "END_DATE")
@Temporal(TemporalType.DATE)
private Date endDate;
@Size(max = 128)
@Column(name = "NAME")
private String name;
@JoinColumn(name = "EMPLOYEE_ID", referencedColumnName = "ID")
@JoinFetch(JoinFetchType.INNER)
//@BatchFetch(BatchFetchType.JOIN)
@ManyToOne(optional = false, fetch = FetchType.LAZY)
private Employees employeeId;

public Benefits() {
}

public Benefits(Long id) {
this.id = id;
}

public Benefits(Long id, String benefitType) {
this.id = id;
this.benefitType = benefitType;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getBenefitType() {
return benefitType;
}

public void setBenefitType(String benefitType) {
this.benefitType = benefitType;
}

public Date getStartDate() {
return startDate;
}

public void setStartDate(Date startDate) {
this.startDate = startDate;
}

public Date getEndDate() {
return endDate;
}

public void setEndDate(Date endDate) {
this.endDate = endDate;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Employees getEmployeeId() {
return employeeId;
}

public void setEmployeeId(Employees employeeId) {
this.employeeId = employeeId;
}

@Override
public int hashCode() {
int hash = 0;
hash += (id != null ? id.hashCode() : 0);
return hash;
}

@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Benefits)) {
return false;
}
Benefits other = (Benefits) object;
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
return false;
}
return true;
}

@Override
public String toString() {
return "test.jpaperformance.entity.Benefits[ id=" + id + " ]";
}

}
Re: 3 table cascade reference @JoinFetch [message #1061877 is a reply to message #1061324] Tue, 04 June 2013 13:40 Go to previous messageGo to next message
James Sutherland is currently offline James Sutherland
Messages: 1939
Registered: July 2009
Location: Ottawa, Canada
Senior Member

The @JoinFetch annotation is only applied one level. To use nested join fetching, you need to use the "eclipselink.join-fetch" query hint, or JOIN FETCH in JPQL.

You could also try @BatchFetch which is applied nested.

See,
http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html


James : Wiki : Book : Blog : Twitter
Re: 3 table cascade reference @JoinFetch [message #1061907 is a reply to message #1061877] Tue, 04 June 2013 15:52 Go to previous message
alex alex is currently offline alex alex
Messages: 3
Registered: May 2013
Junior Member
yes it works!!

thank you very much
Previous Topic:Accesing Eclipselink DBWS
Next Topic:EclipseLink 2.5 schema generation
Goto Forum:
  


Current Time: Mon Sep 22 22:34:42 GMT 2014

Powered by FUDForum. Page generated in 0.06634 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software