I'm using Hibernate Core 3.2.2 and Annotation/EntityManager 3.2.1 with JPA for my web app powered by Tomcat and mySQL.
The problem I'm having is that a single page load can run over 190 queries with only a few things in my tables. I'd like to figure out how to reduce this. It seems that Hibernate is just doing 1+n queries instead of joining them, but I can't find out what I need to use to make them join. Here's a many-to-many relationship that I'm trying to reduce:
Code:
@Entity
public class Affiliate implements Serializable {
private int id;
private List<Product> product = new ArrayList<Product>();
/** Creates a new instance of Affiliate */
public Affiliate() {
}
@GeneratedValue
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
name="Product_Affiliate",
joinColumns={@JoinColumn(name="affiliate_id")},
inverseJoinColumns={@JoinColumn(name="product_id")}
)
@Fetch(value=FetchMode.JOIN)
public List<Product> getProduct() {
return product;
}
public void setProduct(List<Product> product) {
this.product = product;
}
}
@Entity
public class Product implements Serializable {
private List<Affiliate> affiliates = new ArrayList<Affiliate>();
private Set<Schedule> schedule = new HashSet<Schedule>();
private int id;
private String title;
private double price;
private int capacity;
private boolean active;
/** Creates a new instance of Product */
public Product() {
}
@GeneratedValue
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToMany(mappedBy = "product")
public List<Affiliate> getAffiliates() {
return affiliates;
}
public void setAffiliates(List<Affiliate> affiliates) {
this.affiliates = affiliates;
}
@OneToMany(cascade=javax.persistence.CascadeType.ALL, mappedBy="product",fetch=FetchType.EAGER)
@Fetch(value=FetchMode.JOIN)
public Set<Schedule> getSchedule() {
return schedule;
}
public void setSchedule(Set<Schedule> schedule) {
this.schedule = schedule;
}
}
@Entity
public class Schedule implements Serializable {
private int id;
private Date date;
private Product product;
/** Creates a new instance of Schedule */
public Schedule() {
}
@GeneratedValue
@Id
public int getId() {
return id;
}
protected void setId(int id) {
this.id = id;
}
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="product_id", nullable=false)
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
}
These have a few fields pruned to save length. Then I'm calling this to eagerly fetch all Affiliates with their associated Products:
Code:
EntityManager em = emf.createEntityManager();
Collection<Affiliate> colx = em.createQuery("select obj from Affiliate obj").getResultList();
em.close();
emf.close();
And it ends up generating a whole mess of queries. It's doing one query to fetch all the affiliates, then running n queries to fetch the products from each affiliate. It also runs one query for each Schedule.
With 6 Affiliates, 6 Products, and 2 Schedules, Hibernate ends up running all this, when executing: em.createQuery("select obj from Affiliate obj").getResultList();
Code:
Hibernate: select affiliate0_.id as id4_, affiliate0_.contact as contact4_, affiliate0_.main as main4_, affiliate0_.title as title4_ from Affiliate affiliate0_
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select schedule0_.product_id as product3_1_, schedule0_.id as id1_, schedule0_.id as id2_0_, schedule0_.product_id as product3_2_0_, schedule0_.coursedate as coursedate2_0_ from Schedule schedule0_ where schedule0_.product_id=?
Hibernate: select product0_.affiliate_id as affiliate1_1_, product0_.product_id as product2_1_, product1_.id as id0_0_, product1_.price as price0_0_, product1_.capacity as capacity0_0_, product1_.active as active0_0_, product1_.title as title0_0_ from Product_Affiliate product0_ left outer join Product product1_ on product0_.product_id=product1_.id where product0_.affiliate_id=?
This seems so excessive. Is there some way to reduce this? Have I screwed up my annotations/mapping somehow?[/code]