Hibernate Association &
Collection Mapping
Also a Bit on Lazy Loading and
Fetching Strategies
Topics
• Object types in Hibernate
• Collection types in Hibernate
• Scrutinizing 1-2-Many Collections
• Fetching Strategies
2
Object Types in Hibernate
Entity Type Object
• Has its own DB
identity (i.e. PK).
• Can exist
independently of
any other entity.
• Has its own life
cycle.
Value Type Object
• Doesn’t have own DB
identity.
• Existence is dependent
on its owning entity.
• Lifespan is bounded by
the lifespan of the
owning entity.
3
Collection Types in Hibernate
Set: [java.util.HashSet]
• Unique Elements
• Unordered
List: [java.util.ArrayList]
• Duplicate Elements
• Ordered
Sorted Set:
[java.util.TreeSet]
• Unique Elements
• Ordered
Bag: [java.util.List]
• Unordered
• Duplicate Elements
Map: [java.util.Map]
• Unordered Unique Keys
• Duplicate Values
Sorted Map:
[java.util.TreeMap]
• Ordered Keys
• Duplicate Values
4
Unidirectional 1-2-Many Between Entities
class A {
int id;
String name;
List<B> bList;
...
@OneToMany
public List<B> getBList() {
return bList;
}
}
class B {
int id;
String name;
...
}
5
Unidirectional 1-2-Many Between Entities...
Resulting DB:
Conlusion:
By default Hibernate creates one-to many with join table.
This is same as:
@OneToMany
@JoinTable(name="A_B"
joinColumns=@JoinColumn(name="A_id"),
inverseJoinColumns=JoinColumn(name="bList_id")
)
6
Unidirectional 1-2-Many Between Entities...
For 1-2-Many without join table, use:
@OneToMany
@JoinColumn(name="a_id")
Resulting DB:
7
Unidirectional 1-2-Many Between Entities...
Nullable Effect in Join Column
• For the previous code, the join column is by
default nullable.
• Hence, deletion would cause Hibernate to
update row in B setting a_id = null.
• It’s the same as defining as follows:
@OneToMany
@JoinColumn(name="a_id", nullable="true")
8
Unidirectional 1-2-Many Between Entities...
Nullable Effect in Join Column (contd.)
• To set the join column NOT to be null, use:
@OneToMany
@JoinColumn(name="a_id", nullable="false")
• In that case, deletion would cause no effect in
Hibernate.
• To force delete child row when the parent is
removed, use:
@OneToMany(orphanRemoval=true)
@JoinColumn(name="a_id", nullable="false")
9
Unidirectional 1-2-Many Between Entities...
(List Semantics)
• By default, List collections are considered to be bags.
• To enforce List semantics, specify the index column:
@OneToMany
@JoinColumn(name="a_id", nullable="false")
@IndexColumn(name="idx")
A B
Id name Id a_id Name idx
1 A1 1 1 B1 0
2 1 B2 1
3 1 B3 2
10
Unidirectional 1-2-Many Between Entities...
(List Semantics)
INSERT operation
Let, a new row at idx = 1 position is to be inserted.
1. If join column is nullable, then
1 update query for deletion (i.e., set idx = null) of rows with idx ≥ 1.
2. 1 update query for updating of rows with idx ≥ 1.
3. 1 update query for insertion of new rows.
A B
Id name Id a_id Name idx
1 A1 1 1 B1 0
2 1 B2 1
3 1 B3 2
11
Unidirectional 1-2-Many Between Entities...
(List Semantics)
DELETE operation
Let, row with idx = 1 is to be deleted.
1. 1 update query for updating of rows with idx > 1.
2. If orphanRemoval = true, then
1 delete query for deleting the row with idx = 1.
Note: If join column is not nullable and orphanRemoval = false, the row
with idx = 1 will remain, hence, there will be two rows with idx = 1.
A B
Id name Id a_id Name idx
1 A1 1 1 B1 0
2 1 B2 1
3 1 B3 2
12
Unidirectional 1-2-Many Between Entities...
(List Semantics)
Lazy Loading with LazyCollectionOption.EXTRA
• Calling size() wouldn’t cause collection to
load.
• Calling get(idx) would cause only one row
with the idx value to load.
A B
Id name Id a_id Name idx
1 A1 1 1 B1 0
2 1 B2 1
3 1 B3 2
13
Unidirectional 1-2-Many Between Entities...
(Set Semantics)
Lazy Loading with LazyCollectionOption.EXTRA
• Calling size() wouldn’t cause collection to
load.
• Calling iterator.next() would cause
the entire collection to load.
A B
Id name Id a_id Name
1 A1 1 1 B1
2 1 B2
3 1 B3
14
Unidirectional 1-2-Many Between Entities...
(Set Semantics)
INSERT operation
1 update query for setting the newly added
element’s a_id.
A B
Id name Id a_id Name
1 A1 1 1 B1
2 1 B2
3 1 B3
15
Unidirectional 1-2-Many Between Entities...
(Set Semantics)
DELETE operation
If join column is nullable,
1 update query for setting a_id = null.
Else
If orphanRemoval = false
No changes would be made.
Else
Completely delete the row in B.
A B
Id name Id a_id Name
1 A1 1 1 B1
2 1 B2
3 1 B3
16
Unidirectional 1-2-Many Between Entities...
(Bag Semantics)
Similar to SET semantics...
A B
Id name Id a_id Name
1 A1 1 1 B1
2 1 B2
3 1 B3
17
Unidirectional 1-2-Many With Value Type
(Bag Semantics)
INSERT, DELETE, UPDATE operations
1. Select * from B.
2. Delete * from B where a_id = 1.
3. Insert into B all rows – along with new rows (in
case of INSERT), or except rows to be delete (in
case of DELETE).
A B
Id name a_id Name
1 A1 1 B1
1 B2
1 B3
18
Unidirectional 1-2-Many With Value Type
(Set Semantics)
INSERT operation
1. Select * from B.
2. Insert into B the new rows to be added.
A B
Id name a_id Name
1 A1 1 B1
1 B2
1 B3
19
Unidirectional 1-2-Many With Value Type
(Set Semantics)
DELETE operation
1. Select * from B.
2. Delete from B where a_id = 1 and name = ?
A B
Id name a_id Name
1 A1 1 B1
1 B2
1 B3
20
Unidirectional 1-2-Many With Value Type
(Set Semantics)
UPDATE operation
1. Select * from B.
2. Delete the row to be updated.
3. Insert the newly updated object.
A B
Id name a_id Name
1 A1 1 B1
1 B2
1 B3
21
Unidirectional 1-2-Many With Value Type
(List Semantics)
INSERT operation
1. Select * from B.
2. Update idx values in B.
3. Insert the new object.
A B
Id name a_id Name idx
1 A1 1 B1 0
1 B2 1
1 B3 2
22
Unidirectional 1-2-Many With Value Type
(List Semantics)
DELETE operation
1. Select * from B.
2. Delete from B where idx = ?
3. Update the idx of other rows.
A B
Id name a_id Name idx
1 A1 1 B1 0
1 B2 1
1 B3 2
23
Unidirectional 1-2-Many With Value Type
(List Semantics)
UPDATE operation
Doesn’t seem to work!!!
A B
Id name a_id Name idx
1 A1 1 B1 0
1 B2 1
1 B3 2
24
Unidirectional 1-2-1 Between Entities
@OneToOne
• Defaults to eager fetching.
• To force lazy loading, use:
@OneToOne(fetch=FetchType.LAZY)
A B
Id name b_id id Name
1 A1 1 1 B1
25
Fetch Modes
SELECT FETCH (Default)
• Force lazy loading.
JOIN FETCH
• If join column nullable, then outer join,
otherwise inner join.
• Force eager fetching.
BATCH-SIZE N
• Doesn’t define how many records inside in the collections are
loaded. Instead, it defines how many collections should be loaded.
• Nice for nested tree node loading.
SUBSELECT
• Not only loads this collection in the second SELECT (either lazy or
non-lazy), but also all other collections for all "owning" entities
loaded in the first SELECT.
26
Fetch Modes...
BATCH-SIZE N Example
List<A> aList = getList();
for (A a : aList) {
List<B> bList = a.getbList();
}
In Batch-size = 5, the select query would be:
select ...
from B
where a_id in (?, ?, ?, ?, ?)
A B
id name a_id Name
1 A1 1 B1
2 A2 1 B2
2 B3
27
Fetch Modes...
SUBSELECT Example
List<A> aList = getList();
for (A a : aList) {
List<B> bList = a.getbList();
}
In subselect, the select query would be:
select ...
from B
where a_id in (select id from A)
A B
id name a_id Name
1 A1 1 B1
2 A2 1 B2
2 B3
28
References
• A Short Primer On Fetching Strategies:
https://community.jboss.org/wiki/AShortPrimerO
nFetchingStrategies
• Hibernate – fetching strategies examples
http://www.mkyong.com/hibernate/hibernate-
fetching-strategies-examples/
• Bag is recommended over set:
http://stackoverflow.com/questions/1505874/hib
ernate-best-collection-type-to-use-bag-idbag-set-
list-map
29

Hibernate collection & association mapping

  • 1.
    Hibernate Association & CollectionMapping Also a Bit on Lazy Loading and Fetching Strategies
  • 2.
    Topics • Object typesin Hibernate • Collection types in Hibernate • Scrutinizing 1-2-Many Collections • Fetching Strategies 2
  • 3.
    Object Types inHibernate Entity Type Object • Has its own DB identity (i.e. PK). • Can exist independently of any other entity. • Has its own life cycle. Value Type Object • Doesn’t have own DB identity. • Existence is dependent on its owning entity. • Lifespan is bounded by the lifespan of the owning entity. 3
  • 4.
    Collection Types inHibernate Set: [java.util.HashSet] • Unique Elements • Unordered List: [java.util.ArrayList] • Duplicate Elements • Ordered Sorted Set: [java.util.TreeSet] • Unique Elements • Ordered Bag: [java.util.List] • Unordered • Duplicate Elements Map: [java.util.Map] • Unordered Unique Keys • Duplicate Values Sorted Map: [java.util.TreeMap] • Ordered Keys • Duplicate Values 4
  • 5.
    Unidirectional 1-2-Many BetweenEntities class A { int id; String name; List<B> bList; ... @OneToMany public List<B> getBList() { return bList; } } class B { int id; String name; ... } 5
  • 6.
    Unidirectional 1-2-Many BetweenEntities... Resulting DB: Conlusion: By default Hibernate creates one-to many with join table. This is same as: @OneToMany @JoinTable(name="A_B" joinColumns=@JoinColumn(name="A_id"), inverseJoinColumns=JoinColumn(name="bList_id") ) 6
  • 7.
    Unidirectional 1-2-Many BetweenEntities... For 1-2-Many without join table, use: @OneToMany @JoinColumn(name="a_id") Resulting DB: 7
  • 8.
    Unidirectional 1-2-Many BetweenEntities... Nullable Effect in Join Column • For the previous code, the join column is by default nullable. • Hence, deletion would cause Hibernate to update row in B setting a_id = null. • It’s the same as defining as follows: @OneToMany @JoinColumn(name="a_id", nullable="true") 8
  • 9.
    Unidirectional 1-2-Many BetweenEntities... Nullable Effect in Join Column (contd.) • To set the join column NOT to be null, use: @OneToMany @JoinColumn(name="a_id", nullable="false") • In that case, deletion would cause no effect in Hibernate. • To force delete child row when the parent is removed, use: @OneToMany(orphanRemoval=true) @JoinColumn(name="a_id", nullable="false") 9
  • 10.
    Unidirectional 1-2-Many BetweenEntities... (List Semantics) • By default, List collections are considered to be bags. • To enforce List semantics, specify the index column: @OneToMany @JoinColumn(name="a_id", nullable="false") @IndexColumn(name="idx") A B Id name Id a_id Name idx 1 A1 1 1 B1 0 2 1 B2 1 3 1 B3 2 10
  • 11.
    Unidirectional 1-2-Many BetweenEntities... (List Semantics) INSERT operation Let, a new row at idx = 1 position is to be inserted. 1. If join column is nullable, then 1 update query for deletion (i.e., set idx = null) of rows with idx ≥ 1. 2. 1 update query for updating of rows with idx ≥ 1. 3. 1 update query for insertion of new rows. A B Id name Id a_id Name idx 1 A1 1 1 B1 0 2 1 B2 1 3 1 B3 2 11
  • 12.
    Unidirectional 1-2-Many BetweenEntities... (List Semantics) DELETE operation Let, row with idx = 1 is to be deleted. 1. 1 update query for updating of rows with idx > 1. 2. If orphanRemoval = true, then 1 delete query for deleting the row with idx = 1. Note: If join column is not nullable and orphanRemoval = false, the row with idx = 1 will remain, hence, there will be two rows with idx = 1. A B Id name Id a_id Name idx 1 A1 1 1 B1 0 2 1 B2 1 3 1 B3 2 12
  • 13.
    Unidirectional 1-2-Many BetweenEntities... (List Semantics) Lazy Loading with LazyCollectionOption.EXTRA • Calling size() wouldn’t cause collection to load. • Calling get(idx) would cause only one row with the idx value to load. A B Id name Id a_id Name idx 1 A1 1 1 B1 0 2 1 B2 1 3 1 B3 2 13
  • 14.
    Unidirectional 1-2-Many BetweenEntities... (Set Semantics) Lazy Loading with LazyCollectionOption.EXTRA • Calling size() wouldn’t cause collection to load. • Calling iterator.next() would cause the entire collection to load. A B Id name Id a_id Name 1 A1 1 1 B1 2 1 B2 3 1 B3 14
  • 15.
    Unidirectional 1-2-Many BetweenEntities... (Set Semantics) INSERT operation 1 update query for setting the newly added element’s a_id. A B Id name Id a_id Name 1 A1 1 1 B1 2 1 B2 3 1 B3 15
  • 16.
    Unidirectional 1-2-Many BetweenEntities... (Set Semantics) DELETE operation If join column is nullable, 1 update query for setting a_id = null. Else If orphanRemoval = false No changes would be made. Else Completely delete the row in B. A B Id name Id a_id Name 1 A1 1 1 B1 2 1 B2 3 1 B3 16
  • 17.
    Unidirectional 1-2-Many BetweenEntities... (Bag Semantics) Similar to SET semantics... A B Id name Id a_id Name 1 A1 1 1 B1 2 1 B2 3 1 B3 17
  • 18.
    Unidirectional 1-2-Many WithValue Type (Bag Semantics) INSERT, DELETE, UPDATE operations 1. Select * from B. 2. Delete * from B where a_id = 1. 3. Insert into B all rows – along with new rows (in case of INSERT), or except rows to be delete (in case of DELETE). A B Id name a_id Name 1 A1 1 B1 1 B2 1 B3 18
  • 19.
    Unidirectional 1-2-Many WithValue Type (Set Semantics) INSERT operation 1. Select * from B. 2. Insert into B the new rows to be added. A B Id name a_id Name 1 A1 1 B1 1 B2 1 B3 19
  • 20.
    Unidirectional 1-2-Many WithValue Type (Set Semantics) DELETE operation 1. Select * from B. 2. Delete from B where a_id = 1 and name = ? A B Id name a_id Name 1 A1 1 B1 1 B2 1 B3 20
  • 21.
    Unidirectional 1-2-Many WithValue Type (Set Semantics) UPDATE operation 1. Select * from B. 2. Delete the row to be updated. 3. Insert the newly updated object. A B Id name a_id Name 1 A1 1 B1 1 B2 1 B3 21
  • 22.
    Unidirectional 1-2-Many WithValue Type (List Semantics) INSERT operation 1. Select * from B. 2. Update idx values in B. 3. Insert the new object. A B Id name a_id Name idx 1 A1 1 B1 0 1 B2 1 1 B3 2 22
  • 23.
    Unidirectional 1-2-Many WithValue Type (List Semantics) DELETE operation 1. Select * from B. 2. Delete from B where idx = ? 3. Update the idx of other rows. A B Id name a_id Name idx 1 A1 1 B1 0 1 B2 1 1 B3 2 23
  • 24.
    Unidirectional 1-2-Many WithValue Type (List Semantics) UPDATE operation Doesn’t seem to work!!! A B Id name a_id Name idx 1 A1 1 B1 0 1 B2 1 1 B3 2 24
  • 25.
    Unidirectional 1-2-1 BetweenEntities @OneToOne • Defaults to eager fetching. • To force lazy loading, use: @OneToOne(fetch=FetchType.LAZY) A B Id name b_id id Name 1 A1 1 1 B1 25
  • 26.
    Fetch Modes SELECT FETCH(Default) • Force lazy loading. JOIN FETCH • If join column nullable, then outer join, otherwise inner join. • Force eager fetching. BATCH-SIZE N • Doesn’t define how many records inside in the collections are loaded. Instead, it defines how many collections should be loaded. • Nice for nested tree node loading. SUBSELECT • Not only loads this collection in the second SELECT (either lazy or non-lazy), but also all other collections for all "owning" entities loaded in the first SELECT. 26
  • 27.
    Fetch Modes... BATCH-SIZE NExample List<A> aList = getList(); for (A a : aList) { List<B> bList = a.getbList(); } In Batch-size = 5, the select query would be: select ... from B where a_id in (?, ?, ?, ?, ?) A B id name a_id Name 1 A1 1 B1 2 A2 1 B2 2 B3 27
  • 28.
    Fetch Modes... SUBSELECT Example List<A>aList = getList(); for (A a : aList) { List<B> bList = a.getbList(); } In subselect, the select query would be: select ... from B where a_id in (select id from A) A B id name a_id Name 1 A1 1 B1 2 A2 1 B2 2 B3 28
  • 29.
    References • A ShortPrimer On Fetching Strategies: https://community.jboss.org/wiki/AShortPrimerO nFetchingStrategies • Hibernate – fetching strategies examples http://www.mkyong.com/hibernate/hibernate- fetching-strategies-examples/ • Bag is recommended over set: http://stackoverflow.com/questions/1505874/hib ernate-best-collection-type-to-use-bag-idbag-set- list-map 29