Hi,
I would like to know what is the best way to get the data (initialize an object) from a key-many-to-one relationship. I found some problem to get data from an object in a many-to-one relationship using the key-many-to-one tag.
I have theses 2 tables linked by a many-to-one relationship:
AstAccountRetail have theses primary keys (composite-key) :
ossAccount,
astSubAccount and
ossPlanType.
and
AstAccount have theses primary keys:
ossAccount and
astSubAccount.
So, AstAccountRetail have a "many-to-one" relationship with AstAccount.
The artifact generator (from the Eclipse/Hibenate tools) generated a interesting mapping for the AstAccountRetail. It set AstAccount and ossPlanType as the primary keys.
Code:
<class
name="AstAccountRetail"
table="AstAccountRetail" schema="dbo" mutable="false">
<composite-id name="id" class="AstAccountRetailId">
<key-many-to-one name="astAccount" class="AstAccount">
<column name="ossAccount" scale="18" precision="0" not-null="false" />
<column name="astSubAccount" scale="10" precision="0" not-null="false" />
</key-many-to-one>
<key-property name="ossPlanType" type="TrimmedString">
<column name="ossPlanType" scale="2" precision="0" not-null="true" sql-type="char" />
</key-property>
</composite-id>
...
</class>
All my tests worked fine, but I still have difficulty to browse to the AstAccount (the parent) object from the AstAccountRetail (a child). I would like to know why this object is not automatically loaded and initialized by Hibernate when I try to access it.
Should I explicitly load the AstAccount from the DB?
This is the code I use to load my AstAccountRetail (in a Spring context). As you can see, I create a AstAccount object to be passed in the AstAccount loader. Should I load (session.load) the AstAccount explicitly here? instead of generating a "detached" object?
Code:
public AstAccountRetail findAstAccountRetailById(String ossAccount, String astSubAccount, String ossPlanType){
Session session = SessionFactoryUtils.getSession(getSessionFactory(), true);
AstAccountId accountId = new AstAccountId(ossAccount, astSubAccount);
AstAccount account = new AstAccount(accountId);
AstAccountRetail obj = (AstAccountRetail) session.load(AstAccountRetail.class, new AstAccountRetailId(account, ossPlanType));
return obj;
}
And this is my test:
Code:
public void testFindAstAccountRetailById() {
AstAccountRetail vo = DaoFinder.getAstAccountRetailDao().findAstAccountRetailById(ossAccount, astSubAccount, ossPlanType);
assertEquals(ossAccount, vo.getId().getAstAccount().getId().getOssAccount());
assertEquals(astSubAccount, vo.getId().getAstAccount().getId().getAstSubAccount());
assertEquals(ossPlanType, vo.getId().getOssPlanType());
assertEquals("SMITH", vo.getAstAccount().getAstLastName()); // HAVE A <NULL> VALUE HERE! TEST FAIL
}
And here the SQL generated by Hibernate, the AstAccount is never load (Hibernate usually would use an outer join):
Code:
select astaccount0_.ossAccount as ossAccount0_,
astaccount0_.astSubAccount as astSubAc2_0_,
astaccount0_.ossPlanType as ossPlanT3_0_,
astaccount0_.ossIsSpousal as ossIsSpo4_24_0_,
astaccount0_.ossIsLockedIn as ossIsLoc5_24_0_,
astaccount0_.ossIsPledge as ossIsPle6_24_0_,
astaccount0_.ossSpecialFee as ossSpeci7_24_0_,
astaccount0_.ossNonCalYearEnd as ossNonCa8_24_0_,
astaccount0_.ossEffectiveDate as ossEffec9_24_0_,
astaccount0_.ossEndDate as ossEndDate24_0_,
astaccount0_.ossBeneficiaryName as ossBene11_24_0_,
astaccount0_.ossBeneficiarySin as ossBene12_24_0_,
astaccount0_.ossBeneficiaryOther as ossBene13_24_0_,
astaccount0_.ossIsResp as ossIsResp24_0_,
astaccount0_.ossBeneficiaryNumber as ossBene15_24_0_,
astaccount0_.astLastMaintUser as astLast16_24_0_,
astaccount0_.astLastMaintType as astLast17_24_0_,
astaccount0_.astLastMaintJob as astLast18_24_0_,
astaccount0_.astLastMaintTime as astLast19_24_0_,
astaccount0_.astLastMaintDate as astLast20_24_0_
from dbo.AstAccountRetail astaccount0_ where astaccount0_.ossAccount=? and astaccount0_.astSubAccount=? and astaccount0_.ossPlanType=?
So the question I have is, should I session.load() the AstAccount explicitly before passing it in the id of AstAccountRetail? But I guess this code would "smell": I would not like to "load" an parent object because I need to load another one (the child).
Or is there a error in the way I get the AstAccountRetail?
Thanks for helping.
Etienne.