Hi all,
Specific details are below but here's a description. We're using Hibernate along with the 2nd level caching for our read only app. Everything works fine the first time the app is started and the caches are populated (and persisted to disk).
However, if we bounce the app we get a nasty stack trace. This is for a new entity that we've included that uses a composite key, HistoricCreditRatingKey, for the entity HistoricCreditRating. Its the first time that we've used a composite key and so the first time we've hit this problem.
The issue appears to be that when we ask Hibernate to load the object it finds it in the cache (no SQL is generated so its not hitting the database) but fails to instantiate it with the ClassCastException, but the stack trace doesn't make much sense. We're now stuck and its killing our app!
PLEASE HELP.
Rob
Hibernate version:
Hibernate 3.05
Mapping documents:
Code:
<class
name="com.db.csa.domain.HistoricCreditRating"
table="DM_FI_ISSUER_RATING"
where="s_valid_from < sysdate and s_valid_to is null"
>
<composite-id name="key" class="com.db.csa.domain.HistoricCreditRatingKey">
<key-property
name="companyId"
column="ID_BB_COMPANY"
type="java.lang.String"
length="8"
/>
<key-property
name="ratingType"
column="RATING_TYP"
type="java.lang.String"
length="30"
/>
<key-property
name="ratingCompany"
column="RATING_AGENCY"
type="java.lang.String"
length="16"
/>
</composite-id>
<property
name="companyId"
column="ID_BB_COMPANY"
type="java.lang.String"
length="8"
insert="false"
update="false"
/>
<property
name="rating"
column="rating"
type="java.lang.String"
length="8"
/>
.
.
.
Here's the highlight of the HistoricCreditRating class. Each property has associated getter and setter values:
Code:
private HistoricCreditRatingKey key;
private String rating;
private String ratingChangeDirection;
private YearMonthDay startDate;
private YearMonthDay endDate;
private String companyId;
The key. The member variables have associated getters/setters and we've implemented the appropriate methods for the UserType interface:
Code:
public class HistoricCreditRatingKey implements UserType, Serializable{
private String companyId;
private String ratingType;
private String ratingCompany;
Code between sessionFactory.openSession() and session.close():Hmm, tricky one. We're using some batching stuff along with lazy objects. The method that kicks things off:
Code:
DataAccessSession session = new DataAccessSession();
for (Issuer issuer : session.getIssuerStore().getAllIssuers()) {
getBondsForIssuer(issuer, session);
}
session.close();
The method that is called is this:
Code:
public List<HistoricCreditRating> getCreditRatingsForIssuer(Issuer issuer) throws CsaDAOException {
String companyId = issuer.getIdBbCompany();
if (companyId != null) {
return ratingCollectionFactory.createObject(companyId);
}
return Collections.emptyList();
}
The code that does the batching and then calls the values:
Code:
Map<String, String> issuerTickers = new HashMap<String, String>(idList.size());
for (String identifier : idList){
issuerTickers.put(identifier, identifier);
}
Criteria query = session.createCriteria(HistoricCreditRating.class);
//query.setCacheable(true);
query.add(Restrictions.in("companyId", issuerTickers.keySet()));
query.addOrder(Order.asc("companyId"));
List<HistoricCreditRating> ratings = query.list();
Map<String, ArrayList<HistoricCreditRating>> companyRatingCollections = new HashMap<String, ArrayList<HistoricCreditRating>>(idList.size());
String currentIdentifier = null;
ArrayList<HistoricCreditRating> companyRatingCollection = null;
// Due to the ordering of the query we can assume that if a ticker changes from one bond to the
// next then we are looking at bonds for a new issuer
for (HistoricCreditRating historicCreditRating : ratings){
if (currentIdentifier == null || !historicCreditRating.getCompanyId().equals(currentIdentifier)){
//LOG.debug(companyBondCollection.toString());
currentIdentifier = issuerTickers.get(historicCreditRating.getCompanyId());
companyRatingCollection = new ArrayList<HistoricCreditRating>();
companyRatingCollections.put(currentIdentifier, companyRatingCollection);
}
companyRatingCollection.add(historicCreditRating);
}
LOG.debug(companyRatingCollections.toString());
return companyRatingCollections;
Full stack trace of any exception that occurs:Code:
2005-07-06 15:33:22,245 INFO org.hibernate.impl.SessionFactoryImpl - Checking 0 named queries
Exception in thread "main" com.db.csa.dao.core.CsaDAOException: Error searching for class java.util.ArrayList by hibernate id [825197]: exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) getter of com.db.csa.domain.HistoricCreditRatingKey.?
at com.db.csa.dao.database.CachingBatchingLazyCollectionFactory.getObjectFromHibernate(CachingBatchingLazyCollectionFactory.java:66)
at com.db.csa.dao.database.CachingBatchingLazyCollectionFactory.getObjectsFromHibernate(CachingBatchingLazyCollectionFactory.java:50)
at com.db.csa.dao.database.CachingBatchingLazyCollectionFactory.createObject(CachingBatchingLazyCollectionFactory.java:41)
at com.db.csa.dao.database.HistoricCreditRatingStoreSession.getCreditRatingsForIssuer(HistoricCreditRatingStoreSession.java:62)
at com.db.csa.dao.database.CSAPostLoadEventListener.injectIssuerCreditRatings(CSAPostLoadEventListener.java:120)
at com.db.csa.dao.database.CSAPostLoadEventListener.injectDependenciesIntoIssuer(CSAPostLoadEventListener.java:75)
at com.db.csa.dao.database.CSAPostLoadEventListener.onPostLoad(CSAPostLoadEventListener.java:49)
at org.hibernate.event.def.DefaultLoadEventListener.assembleCacheEntry(DefaultLoadEventListener.java:528)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromSecondLevelCache(DefaultLoadEventListener.java:460)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:314)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:113)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:167)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:79)
at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:655)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:261)
at org.hibernate.type.ManyToOneType.assemble(ManyToOneType.java:160)
at org.hibernate.cache.StandardQueryCache.get(StandardQueryCache.java:91)
at org.hibernate.loader.Loader.list(Loader.java:1549)
at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:111)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1322)
at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:300)
at com.db.csa.dao.database.IssuerStoreSession.getAllIssuers(IssuerStoreSession.java:59)
at com.db.csa.devtools.DumpCSABondsInDBIQ.main(DumpCSABondsInDBIQ.java:36)
Caused by: org.hibernate.PropertyAccessException: exception getting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) getter of com.db.csa.domain.HistoricCreditRatingKey.?
at org.hibernate.tuple.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:42)
at org.hibernate.type.ComponentType.getPropertyValues(ComponentType.java:257)
at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:158)
at org.hibernate.engine.EntityKey.getHashCode(EntityKey.java:68)
at org.hibernate.engine.EntityKey.<init>(EntityKey.java:41)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:69)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:621)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:614)
at com.db.csa.dao.database.CachingBatchingLazyCollectionFactory.getObjectFromHibernate(CachingBatchingLazyCollectionFactory.java:64)
... 22 more
Caused by: java.lang.ClassCastException: java.lang.String
at com.db.csa.domain.HistoricCreditRatingKey$$BulkBeanByCGLIB$$6aee0c2a.getPropertyValues(<generated>)
at net.sf.cglib.beans.BulkBean.getPropertyValues(BulkBean.java:48)
at org.hibernate.tuple.PojoComponentTuplizer.getPropertyValues(PojoComponentTuplizer.java:39)
... 30 more
Name and version of the database you are using:
Oracle 9i
The generated SQL (show_sql=true):
None generated