• No results found

Theory and experimental evaluation of object-­relational mapping optimization techniques : How to ORM and how not to ORM

N/A
N/A
Protected

Academic year: 2022

Share "Theory and experimental evaluation of object-­relational mapping optimization techniques : How to ORM and how not to ORM"

Copied!
71
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

1  |  P a g e   Monday,  January  11,  2010  

             

Theory  and  experimental  evaluation  of  object-­‐

relational  mapping  optimization  techniques  

How  to  ORM  and  how  not  to  ORM  

   

by    

 

Jeroen  Bach  

Supervisors:  Hans  Dekkers  &  Jurgen  Vinju   Company  supervisors:  Ingrid  van  Zaanen  &  Co  Kooijman  

Publication  status:  Openbaar   Version:  1.0    

 

   

(2)

Contents    

1   ABSTRACT ...4  

2   INTRODUCTION...5  

3   RELATED  WORK ...6  

3.1   PATTERNS  AND  TECHNIQUES...6  

3.2   PERFORMANCE  MEASUREMENTS...6  

3.3   THE  OBJECT-­‐RELATIONAL  IMPEDANCE  MISMATCH...7  

4   INTRODUCTION  TO  HIBERNATE...8  

4.1   RELATION  QUERYING  CONFIGURATION  PRINCIPLES...9  

4.2   MAPPING  CONFIGURATION...11  

4.3   APPLYING  THE  TYPE  OF  MAPPING  CONFIGURATION...12  

4.4   APPLYING  THE  FETCHING  STRATEGY...14  

5   THEORY  OF  HIBERNATES  QUERY  BEHAVIOUR...15  

5.1   A  NOTATION  FOR  QUERY  BEHAVIOUR...15  

5.2   BASIC  BEHAVIOUR...16  

5.3   IMPORTANT  FACTORS...19  

5.3.1   Bidirectional  relationship ...19  

5.3.2   Lazy  configuration...19  

5.3.3   Join  fetching ...20  

5.3.4   Recursive  relationship ...21  

5.3.5   Concatenating  relationships...21  

6   RESEARCH  METHOD ...22  

6.1   MEASURING  THE  PERFORMANCE...22  

6.1.1   Environment  set  up ...22  

6.1.2   Test  set  up ...23  

6.1.3   Measurement  set  up ...24  

6.2   PREVENTING  BAD  PERFORMANCE  ONE  TO  MANY  RELATIONSHIP  IN  ORACLE...24  

6.3   FACTORS  INFLUENCING  THE  PERFORMANCE...25  

6.3.1   Object  graph...26  

6.3.2   Mapping  configuration ...26  

6.3.3   Actions  on  object  graph ...27  

6.3.4   Storage...27  

6.4   STABILISATION...27  

7   PERFORMANCE  MEASUREMENTS...28  

7.1   HYPOTHESES  AND  RESULTS...29  

7.1.1   Testing  the  type  of  queries ...29  

7.1.2   Testing  the  amount  of  queries ...33  

7.1.3   Testing  all  factors...34  

7.2   THREATS  TO  VALIDITY...48  

7.2.1   Internal...48  

7.2.2   External ...49  

8   CONCLUSION ...50  

8.1   REJECTED  HYPOTHESES...50  

8.2   RECOMMENDATIONS. ...50  

9   FUTURE  WORK...52  

(3)

10   ACKNOWLEDGEMENTS ...53  

11   BIBLIOGRAPHY...54  

APPENDIX  A:  EXAMPLE  MAPPINGS  USED  IN  THIS  RESEARCH ...57  

APPENDIX  B:  RELATION  QUERYING  BEHAVIOUR...58  

ONE  TO  ONE  (NON-­‐RECURSIVE)...58  

ONE  TO  ONE  (RECURSIVE) ...63  

ONE  TO  MANY  (NON-­‐RECURSIVE) ...64  

ONE  TO  MANY  (RECURSIVE)...68  

MANY  TO  MANY  (NON-­‐RECURSIVE)...71  

MANY  TO  MANY  (RECURSIVE) ...71    

(4)

1 Abstract  

When  an  object  oriented  written  application  has  to  make  use  of  a  relational  database  an  ORM  tool   can  be  used  to  synchronize  the  object  model  with  the  tables  in  the  database.  An  advantage  of  such   an   ORM   tool   is   the   support   for   automatic   querying   of   related   objects.   This   option   allows   the   programmer   to   query   one   object   and   dereference   their   relationships   to   other   objects   without   querying   each   reference   manually.   The   ORM   tool   will   perform   this   relation   querying   automatically   for  the  programmer.    

A   popular   ORM   tool   for   Java   is   Hibernate.   In   this   research   we   focus   only   on   Hibernate   and   in   particular   on   the   querying   of   related   objects.   Configuring   the   Hibernate   configuration   files   can   control  this  querying  of  related  objects.  

As  the  mapping  of  Hibernate  (or  any  ORM  tool)  can  be  configured  in  many  ways,  poor  performance   can  be  a  result  of  “wrong”  configuration.  Therefore  we  investigated  the  effect  these  configurations   will  have  on  the  performance.  

 

(5)

2 Introduction  

Hibernate  is  one  of  the  major  ORM  (Object  Relation  Mapping)  tools  written  in  and  for  Java.  An  ORM   tool  handles  the  persistence  of  objects  in  memory  to  a  relational  database.  One  of  the  main  tasks  of   this  is  retrieving  objects  from  the  database.  A  key  feature  of  this  task  is  the  automatic  retrieving  of   referenced  objects  (of  the  queried  object)  as  well,  making  it  possible  to  dereference  the  references   through   an   entire   object   graph   without   specifying   the   retrieval   of   each   related   object   programmatically.  

Hibernate  supports  a  lot  of  different  mapping  configurations  for  customizing  this  behaviour,  blurring   the  “best”  performing  choice  in  a  specific  situation.  The  mapping  configurations  describe  the  object   to  table  mapping  and  relation  querying  behaviour.  Especially,  relatively  new  users  (to  the  Hibernate   library)   can   make   unknowing   choices   that   will   drastically   deteriorate   the   performance   of   the   tool,   maybe  causing  the  abandoning  of  its  usage  in  total.      

Therefore,   the   goal   of   this   research   is   to   help   the   programmer   find   the   best   performing   mapping   configuration.  To  realize  this  goal  we  investigate  the  query  behaviour  of  Hibernate  for  each  type  of   mapping  configuration.  Interpreting  this  behaviour  into  best  performing  choices  can  still  be  a  difficult   task.  We  therefore  benchmark  certain  configurations  as  well.  

This  research  will  be  led  by  the  following  research  question  and  sub-­‐research  questions.  

Research  question  

What  is  the  effect  on  the  performance  of  Hibernate  querying  objects  when  using  different  mapping   configurations?  

Sub-­‐research  question  1  

What  are  the  mapping  configurations  possibilities?  

Sub-­‐research  question  2  

What  is  their  effect  on  the  behaviour?  

Sub-­‐research  question  3  

What  is  the  effect  of  the  behaviour  on  the  performance?  

The  structure  of  the  rest  of  this  thesis  is  as  follows.  First  we  will  discuss  related  work  in  chapter  3.  

After  that  we  will  give  more  detailed  information  about  Hibernate  and  the  mapping  configurations  in   chapter   4,   answering   sub-­‐research   question   1.   Then   we   analyse   the   querying   behaviour   of   the   mapping  configurations  in  chapter  5,  answering  sub-­‐research  question  2.  In  the  research  method  in   chapter  6  we  describe  how  we  will  perform  our  performance  measurements  and  will  describe  and   discuss  the  results  in  chapter  7,  answering  sub-­‐research  question  3.  Finally  we  draw  our  conclusions   in  chapter  8,  and  indicate  future  work  in  chapter  9.    

(6)

3 Related  work  

In  [1]  van  Zyl  et  al.  performed  research  on  the  performance  of  Hibernate  compared  to  several  other   persistence   techniques   (like   plain   JDBC   and   object   databases).   They   demonstrated   the   bad   performance  of  Hibernate  compared  to  these  other  techniques.  In  later  research  [2]  they  reviewed   their  implementation  of  Hibernate  with  a  member  of  the  Hibernate  team,  after  several  comments  on   the   implementation   by   the   Hibernate   community.   In   this   research   they   concluded   that   the   performance  gains  when  implementing  the  recommendations  made  by  this  member.  They  did  not,   afterwards,   draw   any   conclusions   on   the   performance   of   the   renewed   Hibernate   implementation   compared   to   the   other   persistence   techniques.   These   recommendations   are   based   on   experience   and  rules  of  thumb.    

We   tried   to   improve   their   research   and   other   research   performing   benchmarks   with   Hibernate   by   researching  the  effects  on  the  performance  of  certain  configurations  available  in  Hibernate.  With  this   knowledge   we   also   try   to   help   a   programmer   or   researcher   to   implement   a   good   performing   Hibernate  configuration  for  a  specific  situation.    

Further  research  on  the  remaining  configurations  and  possibilities  of  Hibernate  and  expanding  it  to   other  tools  can  help  create  more  honest  benchmarks  in  total.  

3.1 Patterns  and  techniques  

There   are   a   great   variety   of   patterns   and   techniques   to   achieve   a   good   performing   ORM   and   Hibernate   implements   several   of   these.   W.   Keller   described   a   complete   pattern   language   on   this   subject  in  [3,  4,  5].  Several  others  also  described  best  practices,  patterns  and  techniques  (often  also   implemented  by  Hibernate)  in  [6,  7,  8,  9].  Applying  these  patterns  and  techniques  can  be  achieved  by   adjusting  the  mapping  configuration  of  Hibernate.  

As   demonstrated   in   [2]   and   the   remainder   of   this   thesis,   this   configuration   of   Hibernate   can   have   great  influence  on  the  performance.  Due  to  the  great  variety  of  possibilities  and  the  needed  in  depth   database   knowledge,   this   configuration   remains   a   difficult   and   error-­‐prone   task   that   can   easily   deteriorate   the   overall   performance.   Due   to   this   fact   several   have   tried   to   automate   this   task,   by   analyzing  the  runtime  behaviour  [10,  11],  static  code  analysis  [12,  13]  or  by  model  driven  generation   [14],  but  none  supplies  a  fully  functional  solution  yet.    

We   decided   to   clarify   the   behaviour   of   Hibernate   and   its   effect   on   the   performance   using   these   possible  configurations  for  tackling  this  problem  manually.  

3.2 Performance  measurements  

Measuring  the  performance  of  these  persistence  tools  can  be  done  by  specialized  benchmarks  like:  

OO7  (java  variant)  [1],  PolePosition  and  Torpedo  [15].  The  OO7  benchmark  was  originally  intended  to   test   OODBMS   (Object   Oriented   Database   Management   Systems)   [16].   In   [1]   this   benchmark   is   translated  to  Java  and  used  to  compare  the  performance  of  Hibernate  (and  PostgreSQL)  with  db4o1,   by  van  Zyl  et  al.  indicated  in  the  first  part  of  this  chapter.  The  same  author(s)  also  wrote  PolePosition,   to   further   investigate   the   findings   of   this   (translated)   OO7   benchmark.   In   our   research   we   used   PolePosition  as  the  basis  for  our  benchmark.    

                                                                                                                         

1  db4o  is  an  object  database  created  by  Versant  corporation.  

(7)

Also  it  should  be  noted  that  [17,  18]  wrote  an  ORM  benchmark  (“BenchORM”)  with  tests  based  on   two  real-­‐life  scenarios  (the  JDBC  wrapper  and  the  objects  of  the  object  model  of  this  research  were   used  in  our  tests).  

3.3 The  object-­‐relational  impedance  mismatch  

Benchmarking   persistence   tools   fit   in   a   greater   research,   finding   the   optimal   solution   of   solving/bridging   the   gap   between   the   object   oriented   and   relational   paradigm.   An   ORM   tool   (like   Hibernate)  tries  to  fill  this  gap.  This  gap  is  also  often  referred  to  as  the  object-­‐relational  impedance   mismatch  [19].  

As  Robert  Green  stated  in  [20],  the  problem  of  “impedance  mismatch”  materializes  itself  strongly  in   two  fundamental  ways.  One  way  is  regarding  the  development  burden  presented  by  the  mismatch   and   the   other   is   regarding   the   slower   performance   and/or   resource   consumption   imposed.   As   standardization   of   these   mapping   has   occurred   over   the   last   couple   of   years,   the   development   burden   has   been   decreased   and   productivity   has   improved.   Also   the   issues   of   performance   and   resource  utilization  have  been  relieved.  By  solving  the  “impedance  mismatch”  with  ORM  tools  the   developer  is  equipped  to  create  a  good  performing  solution  easier.  

The  use  of  object  databases  can  also  be  an  alternative  since  they  have  proven  to  be  a  better  solution   for  certain  kinds  of  applications  [20].  However,  this  is  out  of  scope  of  this  research.  

 

(8)

4 Introduction  to  Hibernate  

In   this   part   we   will   give   some   general   information   about   Hibernate   and   will   discuss   the   automatic   retrieving  of  referenced  objects  (relation  querying)  in  more  detail.  

Hibernate   is   an   ORM   (Object-­‐Relational   Mapping)   library   written   in   and   for   JAVA.   An   ORM   is   a   communication  layer  between  the  application  and  the  database  (making  use  of  the  database  drivers   to   send   SQL   statements),   mapping   an   Object   Oriented   data   model   to   a   relational   data   model   and   handling  the  synchronisation  of  the  two.  For  an  overview  of  Hibernates  architecture  see  Figure  1.    

As  both  relational  and  object  oriented  paradigms  are  used,  the  terminology  will  slightly  overlap.  We   speak  of  references  when  there  is  a  relationship  between  objects  and  of  relations  when  there  is  a   relationship  between  tables.  

 

Figure  1:  Context  diagram  of  components  and  layers  in  the  Hibernate  Architecture  (source  [21]).  

In   this   research   we   focus   only   on   the   part   where   objects   are   queried   from   the   database   and   will   describe  the  other  actions  (like  updating,  deleting  and  inserting)  in  future  work.  Querying  an  object  is   the  basic  action  also  needed  to  perform  the  other  actions  of  an  ORM.  

The   Querying   of   objects   can   be   initiated   in   two   ways,   by   using   the   methods   of   the   Hibernate   API   (Application  Programming  Interface)  or  dereferencing  a  reference.    When  dereferencing  a  reference   the   programmer   has   used   the   pointer   in   an   object   (retrieved   by   a   method   of   the   API)   to   access   properties  of  the  related  object.  When  the  API  is  used,  the  programmer  has  thus  called  a  method   that  retrieves  an  object  (or  collection  of  objects).  Objects  retrieved  with  the  API  can  be  seen  as  the   starting  objects  from  which  the  dereferencing  can  begin.  

The   use   of   the   API   and   the   way   these   references   are   configured   can   have   a   great   impact   on   the   performance.   From   this   API   we   only   use   one   method   (the   .get()),   the   remaining   methods   are   discussed   in   chapter   9   Future   work.   After   using   the   method   Hibernate   will   retrieve   all   referenced   objects   automatically.   The   “when”   and   “how”   of   this   action   can   be   configured   by   setting   the   (so   called)   fetching   strategies   and   table   representation.   The   object   containing   the   reference   will   be   referred  to  as  the  owning  object  from  now  on.    

Hibernate

Java Database Drivers

(9)

4.1 Relation  querying  configuration  principles  

Hibernate   supports   several   configurations   to   determine   the   behaviour   of   querying   related   objects   from  the  database:  the  fetching  strategy  and  the  table  representation.      

In  the  Hibernate  reference  documentation  [22]  a  distinction  is  made  between  four  fetching  strategies   and  setting  the  laziness  of  it.  When  a  reference  to  an  object  is  set  to  lazy,  Hibernate  will  wait  with  the   retrieval  of  this  object  until  it  is  first  accessed.  For  each  strategy  we  quote  the  definition  given  by  the   Hibernate  reference  documentation  [22].  

-­‐ Select   Fetching:   A   second   SELECT   is   used   to   retrieve   the   associated   entity   or   collection.  

Unless   you   explicitly   disable   lazy   fetching   by   specifying   lazy="false",   this   second   select   will   only  be  executed  when  you  access  the  association.    

-­‐ Join  Fetching:  Hibernate  retrieves  the  associated  instance  or  collection  in  the  same  SELECT,   using  an  OUTER  JOIN.    

-­‐ Subselect   Fetching:   A   second   SELECT   is   used   to   retrieve   the   associated   collections   for   all   entities  retrieved  in  a  previous  query  or  fetch.  Unless  you  explicitly  disable  lazy  fetching  by   specifying   lazy="false",   this   second   select   will   only   be   executed   when   you   access   the   association.    

-­‐ Batch   Fetching:   Hibernate   retrieves   a   batch   of   entity   instances   or   collections   in   a   single   SELECT  by  specifying  a  list  of  primary  or  foreign  keys.    

The   SubSelect   and   Batch   Fetching   strategy   are   performance   optimizations   of   the   Select   Fetching   strategy.   They   can   only   be   applied   to   one-­‐to-­‐many   and   many-­‐to-­‐many   relationships   and   will   have   effect  only  when  the  owning  object  is  in  a  collection.  We  scoped  our  research  to  only  the  Join  and   Select  Fetching  strategies.  

The   second   influence   on   the   behaviour   is   the   table   representation.   There   will   be   more   queries   or   joins  when  the  amount  of  tables  the  objects  are  divided  over  increases.  Hibernate  supports  13  table   representations;  we  created  an  overview  of  the  possibilities  in  Figure  2.  This  diagram  contains  at  the   leftmost  column  the  object  relationships  (that  we  investigated)  and  a  number  next  to  it  that  indicates   how  this  relationship  can  be  mapped  to  tables  indicated  at  the  rightmost  column.  Also  only  primary   and  foreign  keys  are  shown  in  this  diagram,  the  other  (value)  columns  are  left  out.  

(10)

  Figure  2:  Mapping  objects  and  relationships  

A B

1 - 1

n - m

1 - m

B A

B A

B A

B A

B A

B A

Legend ...

PK FK

Primairy Key Foreign Key U Unique constraint P Primairy key

constraint Table reference Composition

Uni-directional (for all relationships) Object

B A

Object reference representation

A A

A

FK FK

junction table P U PK

table A

P PK

table B P 7 1-1 with junction table

FK FK

junction table P P PK

table A

P PK

table B P 12 n-m with junction table

FK FK

junction table P P + U PK

table A

P PK

table B P 11 1-m with junction table

PK table A

P 4 1-1 unique foreign key

PK FK

table B P U

PK FK

table B P 8 1-m foreign key

PK table A

P PK

table A P

2 1-1 foreign key is primairy key

FK table B

P

Table representation

PK FK

table P

1-m recursive with foreign key 9

PK FK

table P U

1-1 recursive with foreign key 5

PK table

P FK

FK junction table

P U 1-1 recursive with junction table 6

PK table

P FK

FK junction table

P P + U 1-m recursive with junction table 10

PK table

P FK

FK junction table

P P n-m recursive with junction table 13

1 1-1 one table

PK table AB

P

N Table representation

Association / aggregation (Bi-directional) X

Only the owning object can have the foreign key in its table, if this is not desirable the relation should be made

bi-directional.

PK table B

P 3 1-1 unique foreign key

PK FK

table A P U Hibernate mapping possibilities

A

A

A B A

1 2 4

5 6 8

9 10

11 12

13 14

1 2

5 6 8

9 10

11 12

13 14

2 4 5 6 8

9 10

11 12

13 14

5 6 8

9 10

11 12

13 14

1 2

3 4

7 8

9 10

11 12

13 14

1 2

3 4

7 8

9 10

11 12

13 14

1 2

3 4

5 6

7 9 10 12

13 14

1 2

3 4

5 6

7 9 10 12

13 14

1 2

3 4

5 6

7 9 10 12

13 14

1 2

3 4

5 6

7 8

11 12

13 14

1 2

3 4

5 6

7 8

11 12

13 14

1 2

3 4

5 6

7 8

9 10

11 13 14

1 2

3 4

5 6

7 8

9 10

11 13 14

1 2

3 4

5 6

7 8

9 10

11 14

1 2

3 4

5 6

7 8

9 10

11 14

3 7

3 4

7

1 3 7

1 2

3 4

7

5 6

5 6

8 11

8 11

8 11

9 10

9 10

12

12

12

12 13

13

(11)

4.2 Mapping  configuration  

In  the  next  part  we  will  describe  how  references  to  other  objects  can  be  configured  in  Hibernate.  

The  mapping  configuration  of  Hibernate  is  done  in  XML  files,  for  an  example  see  Code  fragment  1.  A   good  practise  is  to  have  a  XML  file  for  each  Java  class.  With  the  introduction  of  annotations  in  Java  5,   Hibernate   now   also   supports   configuring   the   mappings   with   annotations.   In   our   research   we   performed  the  mapping  configuration  in  XML  files.  

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="org.polepos.teams.hibernate.data">

<class name="Person" table="person">

<id name="id" column="id" type="long">

<generator class="native"/>

</id>

<property name="firstName" column="firstname" length="40" />

<property name="lastName" column="lastName" length="40" />

<property name="age" column="age"/>

<many-to-one name="adress"

column="adressId"

unique="true"

not-null="false"

lazy="proxy" fetch="select"

cascade="all"/>

</class>

</hibernate-mapping>

Code  fragment  1:  Hibernate  XML  mapping  file  

When  configuring  the  mappings  we  distinguish  between  two  definitions,  one  describing  the  type  of   relationship   and   one   describing   how   this   type   is   eventually   configured   in   the   mapping   documents   (type  of  mapping  configuration).  Namely,  there  are  four  types  of  relationships  that  can  be  configured   by  six  types  of  mapping  configurations.    

The  four  types  of  relationships  are:  one  to  one,  one  to  many,  many  to  one  and  many  to  many.  There   are  six  Hibernate  mapping  configuration  types  and  a  range  of  attributes  to  configure  them.  The  types   of  mapping  configuration  indicate  either  a  reference  to  a  single  object  or  to  a  collection  of  objects.  

Using   these   types   in   different   combinations,   for   both   objects,   can   create   the   four   types   of   relationships.  

(12)

 

Mapping  configuration  type  for  configuring  a  reference  to  a  single  object:  

-­‐ component   -­‐ many-­‐to-­‐one   -­‐ one-­‐to-­‐one   -­‐ join  

Mapping  configuration  type  for  configuring  a  reference  to  a  collection  of  objects:  

-­‐ one-­‐to-­‐many   -­‐ many-­‐to-­‐many  

In  the  next  part  we  first  describe  how  to  apply  the  type  of  mapping  configurations  and  after  that  how   to  apply  the  fetching  strategies.  

4.3 Applying  the  type  of  mapping  configuration  

In  Table  1  we  demonstrate  how  to  create  the  table  representations  supported  by  Hibernate  by  listing   the  type  of  mapping  configurations  and  key  attributes  (we  used  the  XML  notations  for  clarity).  Note   that  the  recursive  table  representations  are  equal  to  their  non-­‐recursive  variant,  but  with  a  reference   to  their  own  class  (we  leave  them  out  of  the  table  to  create  a  compacter  overview).  

Each   Java   object   knows   only   about   its   own   relationships.   Configuring   one   or   both   objects   of   the   relationship   will   therefore   have   different   effects.   Besides   making   the   relationship   bidirectional   or   unidirectional,  it  is  also  possible  that  some  table  representations  cannot  be  created  when  configuring   only  one  object.  The  optional  sign  will  indicate  that  the  relation  can  be  unidirectional.    

(13)

 

Table  Representation  (TR)   Configuration  object  A   Configuration  object  B  

 

<component>2  with  the   properties  of  B  within   the  start  and  closing   tag.  

No  xml-­‐mapping   document  needed.  For   a  bidirectional  

relationship,  add  the  

<parent>  element  tag   within  the  

<component>  tag  of   object  A.  

 

<one-­‐to-­‐one>     <one-­‐to-­‐one   constrained=”true”>    

 

 

<many-­‐to-­‐one   unique=”true”>  

(optional)    

<one-­‐to-­‐one>    

 

<one-­‐to-­‐one>     <many-­‐to-­‐one   unique=”true”>  

   

<join>    

<key>      

<many-­‐to-­‐one   unique=”true”>  

(optional)    

<join>    

<key   unique=”true”>    

<many-­‐to-­‐one>  

 

 

<set>    

<one-­‐to-­‐many>    

(optional)    

<many-­‐to-­‐one>  

   

<set>    

<many-­‐to-­‐many   unique=”true”>    

(optional)    

<join>    

<key>      

<many-­‐to-­‐one>    

   

<set>  

<many-­‐to-­‐many>    

(optional)    

<set>      

<many-­‐to-­‐many>    

Table  1:  Type  of  mapping  configurations  

                                                                                                                         

2  The  <component>  element  maps  properties  of  a  child  object  to  columns  of  the  table  of  a  parent  class.  

1 1-1 one table

PK tableAB

P

PK table A

P

2 1-1 foreign key is primairy key

FK table B

P

PK table B

P 3 1-1 unique foreign key

PK FK

table A P U

PK table A

P

4 1-1 unique foreign key

PK FK

table B P U

FK FK

junction table P U PK

table A

P PK

table B P 7 1-1 with junction table

PK FK

table B P 8 1-m foreign key

PK table A

P

FK FK

junction table P P + U PK

table A

P PK

table B P 11 1-m with junction table

FK FK

junction table P P PK

table A

P PK

table B P 12 n-m with junction table

(14)

In  “Appendix  A:  Example  mappings  used  in  this  research”  we  listed  the  relationship  configuration  we   used  in  our  test  setups.  

For  more  detail  explanation  see  the  Hibernate  reference  documentation  [22].    

4.4 Applying  the  fetching  strategy  

Each   type   of   mapping   configuration   can   be   set   to   a   specific   fetching   strategy,   by   setting   three   attributes  (the  possible  values  of  the  attributes  are  described  below  this  list):  

-­‐ the  lazy  attribute:  specifying  when  the  reference  needs  to  be  retrieved  (default:  true|proxy);  

-­‐ the  fetch  attribute:  specifies  the  query  used  to  retrieve  the  reference  (default:  select);  

-­‐ the   batch-­‐size   attribute:   specifying   of   how   many   objects   (in   a   collection)   the   relationship   needs  to  be  retrieved  (default:  0).      

The  fetching  strategy  attributes  will  have  no  effect  on  the  join  and  component  mapping  configuration   types,  because  the  join  type  will  always  force  a  join  and  the  component  type  will  force  the  storage  of   two  objects  into  one  table  (making  it  not  possible  to  join  or  perform  separate  select  queries).  

Not  each  one  of  the  remaining  configuration  types  can  contain  all  these  attributes.  In  the  next  list  we   created  an  overview  of  the  possibilities  (taken  from  the  hibernate  reference  documentation  [22]).  

-­‐ one-­‐to-­‐one  

o fetch="join|select"    

o lazy="proxy|no-­‐proxy|false"  

-­‐ many-­‐to-­‐one:    

o fetch="join|select"    

o lazy="proxy|no-­‐proxy|false"  

-­‐ set:  

o fetch="join|select|subselect"    

o lazy="true|extra|false"  

o batch-­‐size=”N”  

-­‐ many-­‐to-­‐many:  

o fetch="select|join"    

o lazy="true|extra|false"  

For  more  detail  see  the  Hibernate  reference  documentation  [22].    

(15)

5 Theory  of  Hibernates  query  behaviour  

As  hibernate  communicates  by  sending  SQL  statements,  the  logical  first  step  is  to  examine  and  create   an  overview  of  the  executed  SQL  statements.  With  this  overview  we  will  form  our  query  behaviour   theory.  Analyzing  this  theory  will  indicate  the  different  factors  that  change  when  different  mappings   are   applied,   but   not   their   effect   on   the   performance.   Therefore   we   will   form   several   hypotheses   based  on  this  theory  and  execute  performance  measurements  to  test  them  in  chapter  7.  

We  created  this  theory  by  examining  the  SQL  queries  executed  by  Hibernate  when  performing  the   following  tests.  We  created  for  each  mapping  possibility   a  test  containing  objects  (that  implement   the   mapping   configuration   and   fetching   strategies).   Then   we   retrieve   the   owning   object   and   dereference  the  reference(s),  while  registering  the  executed  SQL  using  Hibernates  logging  feature.    

The  theory  explained  in  this  chapter  is  the  need  to  know  basis  for  creating  the  query  behaviour  for   every  type  of  object  model.  

First   we   describe   our   notation   and   the   basic   behaviour   of   each   mapping   and   after   that   we   will   describe  the  influences  of  the  following  configurations  on  the  basic  behaviour:    

-­‐ a  bidirectional  relationship;  

-­‐ lazy  configuration;  

-­‐ join  fetching;    

-­‐ recursive  relationships;  and   -­‐ concatenating  relationships  

For  a  complete  understanding  we  worked  out  the  behaviour  for  all  relationships  (one-­‐to-­‐one,  one-­‐to-­‐

many   and   many-­‐to-­‐many)   in   Appendix   B:   Relation   querying   behaviour.   These   examples   also   demonstrate  the  behaviour  of  recursive  and  bidirectional  relationships.  

5.1 A  notation  for  query  behaviour  

We  present  the  SQL  in  the  form  described  below.  As  SQL  visualized  in  form  of  text  will  not  contribute   to   the   clarity   of   the   overview,   we   decided   to   use   a   more   visual   representation   of   the   result   sets   instead.  In  that  representation  we  show  the  actual  results  in  form  of  a  table,  leaving  out  the  more   unimportant  detailed  information.  Figure  3  explains  our  notation.  

(16)

  Figure  3:  Notation  hibernate  querying  behaviour    

5.2 Basic  behaviour  

In  the  next  examples  there  will  be  an  object  A  with  a  reference  to  object(s)  B.  For  both  objects  we   describe  what  type  of  mapping  configuration  is  applied  to  it.  The  ResultSets  indicate  what  queries   were  executed  when  object  A  and  related  object  B  are  retrieved.  When  predicting  the  behaviour  of   the   reference   from   object   B   back   to   A,   it   is   possible   to   concatenate   these   isolated   building   blocks   together.   In   this   case   it   should   be   noted   that   the   rules   described   in   the   other   subchapters   of   this   chapter  must  be  applied  as  well.  

To  make  the  mapping  configuration  type  more  visible,  we  enclosed  them  in  <…>.  

With  the  <component>  configuration  type  all  properties  of  object  B  are  included  in  the  select  query   of  A.  See  Figure  4.  In  this  table  representation  both  objects  are  stored  in  one  table.  

  Figure  4:  Query  <component>  

With  the  <one-­‐to-­‐one>  configuration  type  another  query  is  executed  to  retrieve  object  B  (by  foreign   key).   See   Figure   5   and   Figure   6.   Both   objects   are   stored   in   separate   tables   and   the   foreign   key   is   stored  in  the  table  of  object  B.  When  applying  only  the  <one-­‐to-­‐one>  configuration  type  the  foreign  

The results of one query

The table(s) included in the results The columns included

of each table

PKA columnsA PKB columnsB

Table A Table B

ResultSet2 PKB FKA

D D FKA PKB PKB columnsB

D D FKA PKB PKB columnsB

... ... ... ... ... ...

PKA columnsA Table A ResultSet1

Duplicated columns from table A, due to the join

The dots indicate that there are more rows present.

This amount is equal to amount of objects.

A join between two tables

Table A has a 1 to N relationship to table B, therefore table B returns multiple

related rows for one row in A Indicates the possibility to execute this query lazy.

Thus only executing it when the objects (in this query) are accessed.

FKA2 PKA1 columnsA1

Table A ResultSet3

Overhead caused by bidirectional relationships.

D Duplicated values

Continues N amount of times, this can be rows or queries.

(where N is the amount of objects in the relation)

JT

Overhead when using a bidirectional relationship, compared to a unidirectional relationship.

Join

Indicates the possibility to execute this query lazy.

Columns from a Junctiontable.

Indicates the extra overhead when the bidirectional relationship back to object A is set to join fetching.

Legend

...

1 1-1 one table

PK table

P

1

PKA columnsA columnsB Table AB

ResultSet1

(17)

key  is  set  as  primary  key  in  object  B  by  default.  Adding  the  <many-­‐to-­‐one>  configuration  type  to  the   mapping  of  object  B  will  make  the  foreign  key  a  separate  column  in  the  table.  

  Figure  5:  Queries  <one-­‐to-­‐one>    

  Figure  6:  Queries  <one-­‐to-­‐one>  on  A  and  <many-­‐to-­‐one>  on  B  

With  the  <many-­‐to-­‐one>  configuration  type  also  another  query  is  executed  to  retrieve  object  B  (by   primary  key).  See  Figure  7.  Both  objects  are  stored  in  separate  tables,  but  the  foreign  key  is  stored  in   the  table  of  object  A.  This  introduces  the  possibility  to  execute  the  query  for  object  B  lazy.  Meaning   that   Hibernate   can   create   a   proxy   object   for   B,   because   after   the   first   query   the   ID   of   object   B   is   known.  This  proxy  object  will  retrieve  object  B  as  soon  as  one  of  its  properties  is  accessed.  

  Figure  7:  Queries  <many-­‐to-­‐one>  

With  the  <join>  and  <many-­‐to-­‐one>  configuration  type  the  foreign  key  is  joined  in  the  first  query  and   for   object   B   another   query   is   executed   (by   primary   key).   See   Figure   8.   Both   objects   are   stored   in   separate  tables  and  the  foreign  keys  are  stored  in  a  separate  table  as  well.  Each  object  will  therefore   always  be  retrieved  by  their  primary  key,  instead  of  sometimes  also  by  the  foreign  key.  This  situation   makes  it  possible  to  always  execute  the  second  query  lazy,  while  the  previous  configurations  did  not   allow  this.      

  Figure  8:  Queries  <join>  and  <many-­‐to-­‐one>    

With  the  <set>  and  <one-­‐to-­‐many>  configuration  type  another  query  will  retrieve  all  B’s  connected   to   A   (by   foreign   key).   See   Figure   9.   For   this   relationship   Hibernate   requires   two   mapping   configuration   types.   The   <set>   indicates   that   the   results   belong   to   a   collection   were   the   <one-­‐to-­‐

many>  will  indicate  the  type  of  relationship.    

PK table A

P

2 1-1 foreign key is primairy key

FK table B

P

2

PKA columnsA PKB columnsB

Table A Table B

ResultSet1 ResultSet2

PK table A

P

4 1-1 unique foreign key

PK FK

table B P

U PKA columnsA PKB columnsB FKA

Table A Table B

ResultSet1 ResultSet2

4

PK table B

P 3 1-1 unique foreign key

PK FK

table A P

U PKA columnsA FKB PKB columnsB

Table B Table A

3 ResultSet1 ResultSet2

FK FK

junction table P U PK

table A

P PK

table B P

7 1-1 with junction table 7

FKB

PKA columnsA PKB columnsB

Table A JT Table B

ResultSet1 ResultSet2

(18)

In  this  case  it  is  possible  to  execute  the  second  query  lazy  as  well  because  the  collection  will  function   as  proxy  object  (waiting  with  the  execution  of  the  query  until  the  collection  is  accessed).    

  Figure  9:  Queries  <set>  and  <one-­‐to-­‐many>      

With   the   <set>   and   <many-­‐to-­‐many>   another   query   will   be   executed   to   retrieve   the   foreign   keys   from  the  junction  table  and  then  for  each  related  object  a  query  is  executed  to  retrieve  it  (by  primary   key).  See  Figure  10.  Not  changing  this  basic  behaviour  can  increase  the  amount  of  executed  queries   drastically   when   the   related   objects   increases.   Note:   When   a   unique   constraint   is   added   to   the  

<many-­‐to-­‐many>  tag,  the  relation  will  be  a  one  to  many  relationship.  

  Figure  10:  Queries  <set>  and  <many-­‐to-­‐many>  with  unique  constraint  

With   the   <set>   and   <many-­‐to-­‐many>   (without   a   unique   constraint)   the   behaviour   is   similar   to   the   previous   one   to   many   relationship.   See   Figure   11.   Note:   When   no   unique   constraint   is   added,   the   relation  will  be  a  many  to  many  relationship.    

  Figure  11:  Queries  <set>  and  <many-­‐to-­‐many>    

8

PKA columnsA PKB columnsB

Table A Table B

ResultSet1 ResultSet2

PKB FKA

PKB columnsB PKB

FKA

PKB columnsB PKB

FKA

... ...

...

...

PK FK

table B P 8 1-m foreign key

PK table A

P Select

11

PKA columnsA

Table A ResultSet1

FKA FKB

ResultSet2 JT

PKB columnsB

Table B ResultSet3

FKA FKB

FKA FKB

... ...

Select Select

PKB columnsB

Table B ResultSet4

... ...

...

...

FK FK

junction table P P + U PK

table A

P PK

table B P 11 1-m with junction table

12

PKA columnsA

Table A ResultSet1

FKA FKB

ResultSet2 JT

PKB columnsB

Table B ResultSet3

FKA FKB

FKA FKB

... ...

PKB columnsB

Table B ResultSet4

... ...

...

...

FK FK

junction table P P PK

table A

P PK

table B P 12 n-m with junction table

(19)

5.3 Important  factors  

To  understand  the  query  behaviour  of  a  certain  object  model  there  are  some  important  factors  that   change  the  basic  behaviour  described  in  chapter  5.2.  In  the  next  part  we  describe  these  factors.  

5.3.1 Bidirectional  relationship  

In  a  bidirectional  relationship  both  objects  have  configured  a  reference  to  each  other  by  using  the   normal   configuration   types.   When   processing   these   configuration   types,   Hibernate   will   act   as   the   default  behaviour  described  (in  the  previous  chapter).  What  should  be  mentioned  is  that  the  default   behaviour  is  always  preceded  by  a  session  cache  lookup  that  can  reduce  the  amount  of  queries  when   the   object   is   retrieved   before.   Theoretically   this   should   mean   that   when   the   reference   back   is   processed  no  extra  queries  will  be  executed,  but  due  to  the  working  of  the  session  cache  this  is  not   always   the   case.   When   performing   a   cache   lookup,   the   ID   (primary   key)   of   the   object   has   to   be   known.  In  chapter  5.2  we  indicated  that  an  object  was  queried  by  primary  or  by  foreign  key,  in  the   case   the   object   is   queried   by   the   primary   key   Hibernate   can   retrieve   the   object   from   the   session   cache.  If  this  is  not  the  case  Hibernate  will  perform  an  extra  query  (retrieving  the  first  object  again).  

In  the  following  part  we  will  demonstrate  this  behaviour  by  giving  an  example.  Here  we  will  retrieve   object  A,  dereference  the  reference  to  object  B  and  dereference  it  back  to  object  A.  With  the  table   representation  of  Figure  12  an  extra  query  for  the  reference  from  object  B  back  to  object  A  will  be   executed  (because  the  table  of  object  B  does  not  contain  the  ID  of  object  A).  In  Figure  13  object  A   can  be  retrieved  from  the  session  cache.  

  Figure  12:  Object  B  cannot  find  object  A  in  the  cache  

  Figure  13:  Object  B  can  find  object  A  in  the  cache  

5.3.2 Lazy  configuration  

In  5.2  Basic  behaviour  we  indicate  with  a    if  the  query  of  a  referenced  object  can  be  executed   lazy.  This  sign  represents  two  objects  and  dereferencing  the  reference  of  the  left  object  to  the  right   object.   In   lazily   configured   references   this   dereferencing   is   the   trigger   for   the   query   of   the   right   object  to  be  executed.    

When  configuring  the  laziness  of  a  reference,  Hibernate  distinguishes  between  a  reference  to  a  single   object   or   to   a   collection   of   objects.   When   processing   a   lazy   reference   to   a   single   object,   a   proxy   object  is  created  (to  handle  the  lazy  behaviour).  When  processing  a  lazy  reference  to  a  collection  of   objects,  no  proxy  object  is  needed  (due  to  the  collection  object  that  will  handle  the  lazy  behaviour).    

In   case   of   a   reference   to   a   collection   of   objects   the   query   can   always   be   executed   lazy   but   when   relating  to  single  objects  this  is  not  always  the  case.  To  create  a  proxy  object,  the  ID  (primary  key)  of   the   proxied   object   is   needed.   In   5.2   Basic   behaviour   we   indicated   for   each   table   representation  

PK table B

P 3 1-1 unique foreign key

PK FK

table A P

U PKA columnsA FKB PKB columnsB

Table B Table A

3 ResultSet1 ResultSet2

Select

FKB

PKA columnsA

Table A ResultSet3

PK table A

P 4 1-1 unique foreign key

PK FK

table B P U

FKA

PKB columnsB

PKA columnsA

Table A Table B

ResultSet1 ResultSet2

4 Select

Referenties

GERELATEERDE DOCUMENTEN

If, for example, the salvage value per item is lower than the holding cost per item or the inventory level is not sufficient to fulfil demand after disposing one item

1) The general manager finds it difficult to define the performance of the physical distribution and reverse logistics at Brenntag. This makes it impossible to ensure that

Having seen that the three motivational factors influence the willingness to change and sometimes also directly the change related behaviour, one can understand that the attitude of

Viewed from the control framework for overheads in public sector organizations, the aspect of trust is the most relevant in a situation of high asset specificity

During the transition to a market economy the authorities may wish to either establish a national savings bank or to issue guarantees for the return on savings attracted by

majority by means of the European Commission and the European Parliament does set the fiscal rules as well as does make policy inside those rules on a seemingly

Publisher’s PDF, also known as Version of Record (includes final page, issue and volume numbers) Please check the document version of this publication:.. • A submitted manuscript is

For the development of a growth strategy for Martha’s Flowers the suppliers of floral products from Colombia, Ecuador and California, the floral consumer, the competition