Hi all,
We are using the @Cache annotation on our reference model to avoid some useless roundtrips to the database, with mixed results. Following is the source code for our model: a Grappe that has 0 or 1 target Store, many sub-Grappes and dependent Grappes; the Store also maintains the inverse relationship to its owning Grappe, if present. This information practically never changes.
What we expect:
1- loading a Store by its ID should be done only once, then retrieved from the cache; same for Grappe
2- loading a Grappe's target Store should be done only once, then retrieved from the cache
3- loading a Grappe's sub-Grappes should be done only once, then retrieved from the cache
4- loading a Grappe's dependent Grappes should be done only once, then retrieved from the cache
5- loading a Store's owning Grappe should be done only once, then retrieved from the cache
What we see:
- points 1 to 4 work fine
- point 5 doesn't seem to work; with org.hibernate.SQL=debug we keep seeing queries like the following:
Code:
select grappe0_.id as id1_6_, grappe0_.code as code1_6_, grappe0_.name as name1_6_, grappe0_.status as status1_6_, grappe0_.TARGET_STORE_ID as TARGET6_1_6_, grappe0_.PARENT_ID as PARENT5_1_6_, grappe0_.LOGISTICS_PARENT_ID as LOGISTICS7_1_6_, store1_.id as id2_0_, store1_.LOGALI_NUMBER as LOGALI2_2_0_, store1_.code as code2_0_, store1_.name as name2_0_, assortment2_.id as id0_1_, assortment2_.code as code0_1_, assortment2_.name as name0_1_, assortment2_.status as status0_1_, assortment2_.PARENT_ID as PARENT6_0_1_, assortment2_.LOGISTICS_PARENT_ID as LOGISTICS5_0_1_, assortment2_.TARGET_STORE_ID as TARGET7_0_1_, subassortm3_.PARENT_ID as PARENT6_8_, subassortm3_.id as id8_, subassortm3_.id as id0_2_, subassortm3_.code as code0_2_, subassortm3_.name as name0_2_, subassortm3_.status as status0_2_, subassortm3_.PARENT_ID as PARENT6_0_2_, subassortm3_.LOGISTICS_PARENT_ID as LOGISTICS5_0_2_, subassortm3_.TARGET_STORE_ID as TARGET7_0_2_, logisticsd4_.LOGISTICS_PARENT_ID as LOGISTICS5_9_, logisticsd4_.id as id9_, logisticsd4_.id as id0_3_, logisticsd4_.code as code0_3_, logisticsd4_.name as name0_3_, logisticsd4_.status as status0_3_, logisticsd4_.PARENT_ID as PARENT6_0_3_, logisticsd4_.LOGISTICS_PARENT_ID as LOGISTICS5_0_3_, logisticsd4_.TARGET_STORE_ID as TARGET7_0_3_, subgrappes5_.PARENT_ID as PARENT5_10_, subgrappes5_.id as id10_, subgrappes5_.id as id1_4_, subgrappes5_.code as code1_4_, subgrappes5_.name as name1_4_, subgrappes5_.status as status1_4_, subgrappes5_.TARGET_STORE_ID as TARGET6_1_4_, subgrappes5_.PARENT_ID as PARENT5_1_4_, subgrappes5_.LOGISTICS_PARENT_ID as LOGISTICS7_1_4_, logisticsd6_.LOGISTICS_PARENT_ID as LOGISTICS7_11_, logisticsd6_.id as id11_, logisticsd6_.id as id1_5_, logisticsd6_.code as code1_5_, logisticsd6_.name as name1_5_, logisticsd6_.status as status1_5_, logisticsd6_.TARGET_STORE_ID as TARGET6_1_5_, logisticsd6_.PARENT_ID as PARENT5_1_5_, logisticsd6_.LOGISTICS_PARENT_ID as LOGISTICS7_1_5_ from GRAPPE grappe0_ left outer join STORE store1_ on grappe0_.TARGET_STORE_ID=store1_.id left outer join ASSORTMENT assortment2_ on store1_.id=assortment2_.TARGET_STORE_ID left outer join ASSORTMENT subassortm3_ on assortment2_.id=subassortm3_.PARENT_ID left outer join ASSORTMENT logisticsd4_ on subassortm3_.id=logisticsd4_.LOGISTICS_PARENT_ID left outer join GRAPPE subgrappes5_ on grappe0_.id=subgrappes5_.PARENT_ID left outer join GRAPPE logisticsd6_ on subgrappes5_.id=logisticsd6_.LOGISTICS_PARENT_ID where grappe0_.TARGET_STORE_ID=?
Hibernate version: Hibernate Core 3.2.0 GA
Hibernate EntityManager 3.2.0 GA
Hibernate Annotations 3.2.0 GA
Mapping documents:Code:
@Entity(name = "STORE")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "storeCache")
public class Store implements Serializable, Identifiable {
@Id
@SequenceGenerator(name = "MAINSEQ", sequenceName = "SQ$MAIN")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MAINSEQ")
private long id;
@Column(name = "LOGALI_NUMBER")
private long number;
private String code;
private String name;
@OneToOne(mappedBy = "targetStore", optional = true, fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
private Grappe grappe;
public Store() {}
...
}
Code:
@Entity
@Table(name = "GRAPPE")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "grappeCache")
public class Grappe implements Serializable, RegionalAccess {
@Id
@SequenceGenerator(name = "MAINSEQ", sequenceName = "SQ$MAIN")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MAINSEQ")
private long id;
private String code;
private String name;
private boolean status = true;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TARGET_STORE_ID")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "grappeStoreCache")
private Store targetStore = null;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "subGrappesCache")
private Set<Grappe> subGrappes = new HashSet<Grappe>();
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.EAGER)
@JoinColumn(name = "PARENT_ID")
private Grappe parent = null;
@OneToMany(mappedBy = "logisticsParent", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "grappeLogDependentsCache")
private Set<Grappe> logisticsDependents = new HashSet<Grappe>();
@ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH }, fetch = FetchType.EAGER)
@JoinColumn(name = "LOGISTICS_PARENT_ID")
private Grappe logisticsParent = null;
public Grappe() {}
...
}
Code between sessionFactory.openSession() and session.close():Seems to happen when executing the following:
Code:
grappeDao.loadGrappeById(grappeId);
Full stack trace of any exception that occurs:
No exception
Name and version of the database you are using:
Oracle 9.2
The generated SQL (show_sql=true):
Seen above
Debug level Hibernate log excerpt:
Above
Does anyone have any idea why this query is being sent time and again, even though the Grappe class is marked as being Cached?
Thanks a bunch!