chaitu chaitu
asked on
how to write queries in parent -child relationships using hibernate
Below is the mapping files for parnet and child tables;
Parent
*****
ID NAME
1 STEVEN
2 JOHNSON
Child
*****
ID FIRSTNAME LASTNAME PID
1 XXX AAA 1
2 YYYY LLL 1
3 GGGG JJJJ 2
4 JJJJ BJB 1
5 HGHH JUIU 2
i have 2 qustions in this..
1.Using hibernate how to retrieve child records by passing corresponding parentid(pid);i want to know how to use hibernate in a good way?
2.how to write below queries in Hibernate??
select * from parent p,child c where p.id=c.pid and c.pid=1
Parent.hbm.xml
**********
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.dao.Parent" table="PARENT" schema="SCOTT">
<id name="pid" type="java.lang.Long">
<column name="PID" precision="6" scale="0" />
<generator class="increment" />
</id>
<property name="pname" type="java.lang.String">
<column name="PNAME" length="50" />
</property>
<set name="childs" inverse="true">
<key>
<column name="PID" precision="6" scale="0" />
</key>
<one-to-many class="com.dao.Child" />
</set>
</class>
</hibernate-mapping>
Child.hbm.xml
************
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.dao.Child" table="CHILD" schema="SCOTT">
<id name="cid" type="java.lang.Long">
<column name="CID" precision="6" scale="0" />
<generator class="increment" />
</id>
<many-to-one name="parent" class="com.dao.Parent" fetch="select">
<column name="PID" precision="6" scale="0" />
</many-to-one>
<property name="firstname" type="java.lang.String">
<column name="FIRSTNAME" length="12" />
</property>
<property name="lastname" type="java.lang.String">
<column name="LASTNAME" length="12" />
</property>
</class>
</hibernate-mapping>
Parent
*****
ID NAME
1 STEVEN
2 JOHNSON
Child
*****
ID FIRSTNAME LASTNAME PID
1 XXX AAA 1
2 YYYY LLL 1
3 GGGG JJJJ 2
4 JJJJ BJB 1
5 HGHH JUIU 2
i have 2 qustions in this..
1.Using hibernate how to retrieve child records by passing corresponding parentid(pid);i want to know how to use hibernate in a good way?
2.how to write below queries in Hibernate??
select * from parent p,child c where p.id=c.pid and c.pid=1
Parent.hbm.xml
**********
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.dao.Parent" table="PARENT" schema="SCOTT">
<id name="pid" type="java.lang.Long">
<column name="PID" precision="6" scale="0" />
<generator class="increment" />
</id>
<property name="pname" type="java.lang.String">
<column name="PNAME" length="50" />
</property>
<set name="childs" inverse="true">
<key>
<column name="PID" precision="6" scale="0" />
</key>
<one-to-many class="com.dao.Child" />
</set>
</class>
</hibernate-mapping>
Child.hbm.xml
************
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.dao.Child" table="CHILD" schema="SCOTT">
<id name="cid" type="java.lang.Long">
<column name="CID" precision="6" scale="0" />
<generator class="increment" />
</id>
<many-to-one name="parent" class="com.dao.Parent" fetch="select">
<column name="PID" precision="6" scale="0" />
</many-to-one>
<property name="firstname" type="java.lang.String">
<column name="FIRSTNAME" length="12" />
</property>
<property name="lastname" type="java.lang.String">
<column name="LASTNAME" length="12" />
</property>
</class>
</hibernate-mapping>
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
what is meaning of this --- ("childs","childs")
well
in your hbm you defined a one-to-many relationship
<one-to-many class="com.dao.Child" />
so, hibernate will understand your child table
c.createAlias("childs","ch ilds"); is just like "select * from Parent parent, Child childs"
and after that you can access all its fields by using the alias "childs", for example, "childs.firstName"
-----
for outer join, I am not sure but I think you should use this
c.createAlias("childs","ch ilds",Crit eria.LEFT_ JOIN); or
c.createAlias("childs","ch ilds",Crit eria.FULL_ JOIN);
in your hbm you defined a one-to-many relationship
<one-to-many class="com.dao.Child" />
so, hibernate will understand your child table
c.createAlias("childs","ch
and after that you can access all its fields by using the alias "childs", for example, "childs.firstName"
-----
for outer join, I am not sure but I think you should use this
c.createAlias("childs","ch
c.createAlias("childs","ch
ASKER
Criteria c = getSession().createCriteri a(Parent.c lass);
System.out.println("aaaaaa aaaaa11111 ");
c.createAlias("childs","ch ilds");
System.out.println("aaaaaa aaaaa22222 2");
c.add(Expression.eq("paren t.pid",1)) ;
List results = c.list();
WHEN I execute i am getting below exception
aaaaaaaaaaa11111
aaaaaaaaaaa222222
Exception in thread "main" org.hibernate.QueryExcepti on: could not resolve property: parent of: com.dao.Parent
at org.hibernate.persister.en tity.Abstr actPropert yMapping.t hrowProper tyExceptio n(Abstract PropertyMa pping.java :43)
at org.hibernate.persister.en tity.Abstr actPropert yMapping.t oType(Abst ractProper tyMapping. java:37)
at org.hibernate.persister.en tity.Abstr actEntityP ersister.g etSubclass PropertyTa bleNumber( AbstractEn tityPersis ter.java:1 282)
at org.hibernate.persister.en tity.Basic EntityProp ertyMappin g.toColumn s(BasicEnt ityPropert yMapping.j ava:31)
at org.hibernate.persister.en tity.Abstr actEntityP ersister.t oColumns(A bstractEnt ityPersist er.java:12 57)
at org.hibernate.loader.crite ria.Criter iaQueryTra nslator.ge tColumns(C riteriaQue ryTranslat or.java:43 3)
at org.hibernate.loader.crite ria.Criter iaQueryTra nslator.ge tColumnsUs ingProject ion(Criter iaQueryTra nslator.ja va:393)
at org.hibernate.criterion.Si mpleExpres sion.toSql String(Sim pleExpress ion.java:4 5)
at org.hibernate.loader.crite ria.Criter iaQueryTra nslator.ge tWhereCond ition(Crit eriaQueryT ranslator. java:333)
at org.hibernate.loader.crite ria.Criter iaJoinWalk er.<init>( CriteriaJo inWalker.j ava:82)
at org.hibernate.loader.crite ria.Criter iaLoader.< init>(Crit eriaLoader .java:67)
this is my Parent.java class
************************** ***
public class Parent implements java.io.Serializable {
// Fields
private Long pid;
private String pname;
private Set childs = new HashSet(0);
// Constructors
/** default constructor */
public Parent() {
}
/** full constructor */
public Parent(String pname, Set childs) {
this.pname = pname;
this.childs = childs;
}
// Property accessors
public Long getPid() {
return this.pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getPname() {
return this.pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Set getChilds() {
return this.childs;
}
public void setChilds(Set childs) {
this.childs = childs;
}
}
System.out.println("aaaaaa
c.createAlias("childs","ch
System.out.println("aaaaaa
c.add(Expression.eq("paren
List results = c.list();
WHEN I execute i am getting below exception
aaaaaaaaaaa11111
aaaaaaaaaaa222222
Exception in thread "main" org.hibernate.QueryExcepti
at org.hibernate.persister.en
at org.hibernate.persister.en
at org.hibernate.persister.en
at org.hibernate.persister.en
at org.hibernate.persister.en
at org.hibernate.loader.crite
at org.hibernate.loader.crite
at org.hibernate.criterion.Si
at org.hibernate.loader.crite
at org.hibernate.loader.crite
at org.hibernate.loader.crite
this is my Parent.java class
**************************
public class Parent implements java.io.Serializable {
// Fields
private Long pid;
private String pname;
private Set childs = new HashSet(0);
// Constructors
/** default constructor */
public Parent() {
}
/** full constructor */
public Parent(String pname, Set childs) {
this.pname = pname;
this.childs = childs;
}
// Property accessors
public Long getPid() {
return this.pid;
}
public void setPid(Long pid) {
this.pid = pid;
}
public String getPname() {
return this.pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public Set getChilds() {
return this.childs;
}
public void setChilds(Set childs) {
this.childs = childs;
}
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
sorry
please change this line
c.add(Expression.eq("paren t.pid",1)) ;
to
c.add(Expression.eq("pid", 1));
please show your Child class
please change this line
c.add(Expression.eq("paren
to
c.add(Expression.eq("pid",
please show your Child class
ASKER
jaax,
i removed Hibernate.initialize in my code its working fine;what is the use of Hibernate.initialize ??
mnrz,
if i changed it to c.add(Expression.eq("pid", new Long(1))); its working fine.
i removed Hibernate.initialize in my code its working fine;what is the use of Hibernate.initialize ??
mnrz,
if i changed it to c.add(Expression.eq("pid",
Do you mean to say that with Hibernate.initialize , your code fails - i.e; throws some kind of Hibernate Exception ?
Hibernate.initialize() initializes the entities on demand and not beforehand, thus improving performance.
If you had specified lazy="false" in your hbm file, hibernate would load all the objects in the object graph and that would consume memory but accords the client, the luxury to use any of the objects at its whim. On the other hand, specifying lazy="true", postpones loading of the entity until actually it is needed (by specifying Hibernate.initialize()) and thus economizes on memory. But on the flip-side, the clinet should be careful to use only those objects in the graph that have been initialized.
Hibernate.initialize() initializes the entities on demand and not beforehand, thus improving performance.
If you had specified lazy="false" in your hbm file, hibernate would load all the objects in the object graph and that would consume memory but accords the client, the luxury to use any of the objects at its whim. On the other hand, specifying lazy="true", postpones loading of the entity until actually it is needed (by specifying Hibernate.initialize()) and thus economizes on memory. But on the flip-side, the clinet should be careful to use only those objects in the graph that have been initialized.
ASKER
i observed two things by writing in both forms.
Parent parent = (Parent)getSessionFactory(
Hibernate.initialize(paren
if(parent .getChildren() != null){
Iterator iter = parent .getChildren().iterator();
while(iter.hasNext()){
Hibernate.initialize(iter.
}
}
from writing above code actually it execting two queries like
select parent0_.PID as PID0_0_, parent0_.PNAME as PNAME0_0_ from PARENT parent0_ where parent0_.PID=?
select childs0_.PID as PID1_, childs0_.CID as CID1_, childs0_.CID as CID1_0_, childs0_.PID as PID1_0_, childs0_.FIRSTNAME as FIRSTNAME1_0_, childs0_.LASTNAME as LASTNAME1_0_ from CHILD childs0_ where childs0_.PID=?
**************************
but the below code executes only one query by joining two tables like....thus improving performace.
select this_.PID as PID0_1_, this_.PNAME as PNAME0_1_, childs1_.CID as CID1_0_, childs1_.PID as PID1_0_, childs1_.FIRSTNAME as FIRSTNAME1_0_, childs1_.LASTNAME as LASTNAME1_0_ from PARENT this_ inner join CHILD childs1_ on this_.PID=childs1_.PID where this_.PID=?
Criteria c = getSession().createCriteri
c.createAlias("childs","ch
c.add(Expression.eq("pid",
List results = c.list();
for (Iterator iter = results.iterator(); iter.hasNext();) {
Child element = (Child) iter.next();
System.out.println("Parent
}
Exception in thread "main" java.lang.ClassCastExcepti
but my problem is how to get only child information ;if i type cast with Parent object its working fine...but i want child objects ..
so you can create your criteria with Child, check this:
List result = session.createCriteria(Chi ld.class).
createAlias("parent","pare nt").
add(Expression.eq("parent. pid",new Long(1))).
list();
this will return a list of type "Child"
List result = session.createCriteria(Chi
createAlias("parent","pare
add(Expression.eq("parent.
list();
this will return a list of type "Child"
After you have done this :
Parent parent = (Parent)getSessionFactory( ).openSess ion().get( com.dao.Pa rent.class , parentId);
Hibernate.initialize(paren t .getChildren());
if(parent .getChildren() != null){
Iterator iter = parent .getChildren().iterator();
while(iter.hasNext()){
Hibernate.initialize(iter. next());
}
Iterator iter = parent .getChildren().iterator();
while(iter.hasNext()){
Child child = (Child)iter.next();
//Do what you like with child entity
}
}
}
Parent parent = (Parent)getSessionFactory(
Hibernate.initialize(paren
if(parent .getChildren() != null){
Iterator iter = parent .getChildren().iterator();
while(iter.hasNext()){
Hibernate.initialize(iter.
}
Iterator iter = parent .getChildren().iterator();
while(iter.hasNext()){
Child child = (Child)iter.next();
//Do what you like with child entity
}
}
}
ASKER
final question for both of you which approach is better ;my personnel view is mnrz is said is better one because its executing only query gives us better performance what do you say Jaax..
In my opinion, the performance in both of them is alike, but with Criteria you have many options and features you may need in the future
The choice should be on the requirement. Load is useful when you are querying via PRIMARY KEY and when you are damn sure that it will result in only one record.
Criteria is mainly used for SEARCHING and as mnrz has maintained, additional search attributes can be added or removed as you like. Criteria is the Object oriented way of dealing with DB search. However, Criteria is restricted in certain aspects - like you cannot specify SQL functions and limited flexibility with joins.
To summarize:
1.If you want to load only one record based on primary key go for load or get
2.If you want to search and are expecting multiple outputs, then opt for Criteria or HQL
The choice between Criteria and HQL should be based on flexibility in terms of using advanced SQL features (HQL) and using Object oriented way of searching
Criteria is mainly used for SEARCHING and as mnrz has maintained, additional search attributes can be added or removed as you like. Criteria is the Object oriented way of dealing with DB search. However, Criteria is restricted in certain aspects - like you cannot specify SQL functions and limited flexibility with joins.
To summarize:
1.If you want to load only one record based on primary key go for load or get
2.If you want to search and are expecting multiple outputs, then opt for Criteria or HQL
The choice between Criteria and HQL should be based on flexibility in terms of using advanced SQL features (HQL) and using Object oriented way of searching
ASKER
what will it do?it will automatically join parent and child tables??
if i want outjoin on child table what should i do??