I'm still investigating this and have some more diagnostics.
Firstly, when performing the eager find that's causing the problem, I was using a named-query as explained above. I've replaced that with an EntityManager.find( Class, id ), followed by a bunch of Hibernate.initialize() calls to see if that was causing the problem, but that's made no difference.
So, I inspected the SQL that Hibernate generates and found there is no difference between the SQL generated on the first call (which succeeds) and the last call (which returns the wrong type). For reference, here it is (note that the entity names don't match exactly with how I described it before - I previously shortened them for simplicity):
Code:
select playeracco0_.id as id13_1_,
playeracco0_.accountSystem_id as accountS6_13_1_,
playeracco0_.failedLoginAttemptCount as failedLo2_13_1_,
playeracco0_.locked as locked13_1_,
playeracco0_.preferredOutlet_id as preferre7_13_1_,
playeracco0_.suspended as suspended13_1_,
playeracco0_.username as username13_1_,
playeracco0_1_.nonWithdrawableBalance as nonWithd2_14_1_,
playeracco0_1_.withdrawableBalance as withdraw3_14_1_,
playeracco0_2_.accountNumber as accountN2_15_1_,
playeracco0_2_.accountSystemId as accountS3_15_1_,
playeracco0_2_.address_id as address21_15_1_,
playeracco0_2_.challengeAnswer as challeng4_15_1_,
playeracco0_2_.challengeQuestion_id as challen20_15_1_,
playeracco0_2_.contactableByOthers as contacta5_15_1_,
playeracco0_2_.contactableByUs as contacta6_15_1_,
playeracco0_2_.dob as dob15_1_,
playeracco0_2_.email as email15_1_,
playeracco0_2_.encPin as encPin15_1_,
playeracco0_2_.firstName as firstName15_1_,
playeracco0_2_.lastName as lastName15_1_,
playeracco0_2_.over18 as over12_15_1_,
playeracco0_2_.paymentCard_id as payment19_15_1_,
playeracco0_2_.pinIsOneShot as pinIsOn13_15_1_,
playeracco0_2_.registrationDate as registr14_15_1_,
playeracco0_2_.significantDate as signifi15_15_1_,
playeracco0_2_.telephone as telephone15_1_,
playeracco0_2_.termsAndCondsAccepted as termsAn17_15_1_,
playeracco0_2_.title as title15_1_,
case when playeracco0_2_.id is not null then 2
when playeracco0_1_.id is not null then 1
when playeracco0_.id is not null then 0 end as clazz_1_,
accountsys1_.id as id3_0_,
accountsys1_.adapterClass as adapterC2_3_0_,
accountsys1_.encAdapterClassConfigXml as encAdapt3_3_0_,
accountsys1_.internal as internal3_0_,
accountsys1_.name as name3_0_,
accountsys1_.supportsCashDeposits as supports6_3_0_,
accountsys1_.supportsReconciliation as supports7_3_0_,
accountsys1_.tag as tag3_0_
from PlayerAccount playeracco0_
left outer join WalletPlayerAccount playeracco0_1_ on playeracco0_.id=playeracco0_1_.id
left outer join InternalPlayerAccount playeracco0_2_ on playeracco0_.id=playeracco0_2_.id
inner join AccountSystem accountsys1_ on playeracco0_.accountSystem_id=accountsys1_.id
where playeracco0_.id=?
Next, I stepped through in the debugger...
1) the first find (an InternalPlayerAccount with ID=1) succeeded as before (repeated 5 times, no problem)
2) the next find (a WalletPlayerAccount with ID=2) succeeded as before (repeated 5 times, no problem)
3) the next find (the InternalPlayerAccount with ID=1 again) failed on the first attempt. (Actually, as explained previously, it doesn't *fail* but it returns an entity of type WalletPlayerAccount instead of InternalPlayerAccount.
Whilst in the debugger and immediately prior to step (3) above, I switched to a query tool and executed the SQL above to see if bad data was being returned (specifically whether nulls are returned for the InternalPlayerAccount columns), but everything looked good and valid data was returned from all three *Account tables.
In case it helps, here is the Hibernate log output. This first extract corresponds to step (1) in the list above, i.e. a successful find:
Code:
2007-05-17 10:40:59.265 FINE org.hibernate.SQL select playeracco0_.id as id13_1_, [snip - see SQL above]
2007-05-17 10:40:59.268 FINE org.hibernate.jdbc.AbstractBatcher about to open ResultSet (open ResultSets: 0, globally: 0)
2007-05-17 10:40:59.269 FINE org.hibernate.loader.Loader result set row: 0
2007-05-17 10:40:59.271 FINE org.hibernate.loader.Loader result row: EntityKey[com.evolvegaming.lgp.AccountSystem#1], EntityKey[com.evolvegaming.lgp.PlayerAccount#1]
2007-05-17 10:40:59.278 FINE org.hibernate.jdbc.AbstractBatcher about to close ResultSet (open ResultSets: 1, globally: 1)
2007-05-17 10:40:59.278 FINE org.hibernate.jdbc.AbstractBatcher about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2007-05-17 10:40:59.278 FINE org.hibernate.jdbc.ConnectionManager aggressively releasing JDBC connection
2007-05-17 10:40:59.279 FINE org.hibernate.jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2007-05-17 10:40:59.279 FINE org.hibernate.engine.TwoPhaseLoad resolving associations for [com.evolvegaming.lgp.AccountSystem#1]
2007-05-17 10:40:59.280 FINE org.hibernate.engine.TwoPhaseLoad done materializing entity [com.evolvegaming.lgp.AccountSystem#1]
2007-05-17 10:40:59.280 FINE org.hibernate.engine.TwoPhaseLoad resolving associations for [com.evolvegaming.lgp.InternalPlayerAccount#1]
2007-05-17 10:40:59.282 FINE org.hibernate.engine.TwoPhaseLoad done materializing entity [com.evolvegaming.lgp.InternalPlayerAccount#1]
2007-05-17 10:40:59.282 FINE org.hibernate.engine.StatefulPersistenceContext initializing non-lazy collections
2007-05-17 10:40:59.282 FINE org.hibernate.loader.Loader done entity load
2007-05-17 10:40:59.283 FINE org.hibernate.jdbc.ConnectionManager aggressively releasing JDBC connection
This second extract corresponds to step (3) in the list above, i.e. a find that returns an entity of the incorrect type.
Code:
2007-05-17 10:41:00.771 FINE org.hibernate.SQL select playeracco0_.id as id13_1_, [snip - see SQL above]
2007-05-17 10:41:00.773 FINE org.hibernate.jdbc.AbstractBatcher about to open ResultSet (open ResultSets: 0, globally: 0)
2007-05-17 10:41:00.774 FINE org.hibernate.loader.Loader result set row: 0
2007-05-17 10:41:00.774 FINE org.hibernate.loader.Loader result row: EntityKey[com.evolvegaming.lgp.AccountSystem#1], EntityKey[com.evolvegaming.lgp.PlayerAccount#1]
2007-05-17 10:41:00.777 FINE org.hibernate.jdbc.AbstractBatcher about to close ResultSet (open ResultSets: 1, globally: 1)
2007-05-17 10:41:00.778 FINE org.hibernate.jdbc.AbstractBatcher about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2007-05-17 10:41:00.778 FINE org.hibernate.jdbc.ConnectionManager aggressively releasing JDBC connection
2007-05-17 10:41:00.778 FINE org.hibernate.jdbc.ConnectionManager releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2007-05-17 10:41:00.779 FINE org.hibernate.engine.TwoPhaseLoad resolving associations for [com.evolvegaming.lgp.AccountSystem#1]
2007-05-17 10:41:00.779 FINE org.hibernate.engine.TwoPhaseLoad done materializing entity [com.evolvegaming.lgp.AccountSystem#1]
2007-05-17 10:41:00.780 FINE org.hibernate.engine.TwoPhaseLoad resolving associations for [com.evolvegaming.lgp.WalletPlayerAccount#1]
2007-05-17 10:41:00.781 FINE org.hibernate.engine.TwoPhaseLoad done materializing entity [com.evolvegaming.lgp.WalletPlayerAccount#1]
2007-05-17 10:41:00.781 FINE org.hibernate.engine.StatefulPersistenceContext initializing non-lazy collections
2007-05-17 10:41:00.781 FINE org.hibernate.loader.Loader done entity load
2007-05-17 10:41:00.781 FINE org.hibernate.jdbc.ConnectionManager aggressively releasing JDBC connection
The most interesting bits to my mind are the last two org.hibernate.engine.TwoPhaseLoad entries in each extract - in the first extract it resolves/materializes com.evolvegaming.lgp.InternalPlayerAccount and in the second extract com.evolvegaming.lgp.WalletPlayerAccount
I'm going to continue investigating, but if this is ringing bells for anyone, I'd really appreciate any thoughts/comments/suggestions.
Darren