Author: christian.bauer(a)jboss.com
Date: 2006-08-14 10:55:10 -0400 (Mon, 14 Aug 2006)
New Revision: 10262
Added:
trunk/Hibernate3/doc/reference/pt-br/
trunk/Hibernate3/doc/reference/pt-br/images/
trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.gif
trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.zargo
trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.gif
trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.zargo
trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.gif
trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.zargo
trunk/Hibernate3/doc/reference/pt-br/images/Thumbs.db
trunk/Hibernate3/doc/reference/pt-br/images/full_cream.gif
trunk/Hibernate3/doc/reference/pt-br/images/full_cream.svg
trunk/Hibernate3/doc/reference/pt-br/images/hibernate_logo_a.png
trunk/Hibernate3/doc/reference/pt-br/images/lite.gif
trunk/Hibernate3/doc/reference/pt-br/images/lite.svg
trunk/Hibernate3/doc/reference/pt-br/images/overview.gif
trunk/Hibernate3/doc/reference/pt-br/images/overview.svg
trunk/Hibernate3/doc/reference/pt-br/master.xml
trunk/Hibernate3/doc/reference/pt-br/modules/
trunk/Hibernate3/doc/reference/pt-br/modules/architecture.xml
trunk/Hibernate3/doc/reference/pt-br/modules/association_mapping.xml
trunk/Hibernate3/doc/reference/pt-br/modules/basic_mapping.xml
trunk/Hibernate3/doc/reference/pt-br/modules/batch.xml
trunk/Hibernate3/doc/reference/pt-br/modules/best_practices.xml
trunk/Hibernate3/doc/reference/pt-br/modules/collection_mapping.xml
trunk/Hibernate3/doc/reference/pt-br/modules/component_mapping.xml
trunk/Hibernate3/doc/reference/pt-br/modules/configuration.xml
trunk/Hibernate3/doc/reference/pt-br/modules/events.xml
trunk/Hibernate3/doc/reference/pt-br/modules/example_mappings.xml
trunk/Hibernate3/doc/reference/pt-br/modules/example_parentchild.xml
trunk/Hibernate3/doc/reference/pt-br/modules/example_weblog.xml
trunk/Hibernate3/doc/reference/pt-br/modules/filters.xml
trunk/Hibernate3/doc/reference/pt-br/modules/inheritance_mapping.xml
trunk/Hibernate3/doc/reference/pt-br/modules/performance.xml
trunk/Hibernate3/doc/reference/pt-br/modules/persistent_classes.xml
trunk/Hibernate3/doc/reference/pt-br/modules/query_criteria.xml
trunk/Hibernate3/doc/reference/pt-br/modules/query_hql.xml
trunk/Hibernate3/doc/reference/pt-br/modules/query_sql.xml
trunk/Hibernate3/doc/reference/pt-br/modules/session_api.xml
trunk/Hibernate3/doc/reference/pt-br/modules/toolset_guide.xml
trunk/Hibernate3/doc/reference/pt-br/modules/transactions.xml
trunk/Hibernate3/doc/reference/pt-br/modules/tutorial.xml
trunk/Hibernate3/doc/reference/pt-br/modules/tutorial1.xml
trunk/Hibernate3/doc/reference/pt-br/modules/xml.xml
trunk/Hibernate3/doc/reference/pt-br/styles/
trunk/Hibernate3/doc/reference/pt-br/styles/fopdf.xsl
trunk/Hibernate3/doc/reference/pt-br/styles/html.css
trunk/Hibernate3/doc/reference/pt-br/styles/html.xsl
trunk/Hibernate3/doc/reference/pt-br/styles/html_chunk.xsl
Log:
Imported PT-BR translation
Added: trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.zargo
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/AuthorWork.zargo
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.zargo
===================================================================
(Binary files differ)
Property changes on:
trunk/Hibernate3/doc/reference/pt-br/images/CustomerOrderProduct.zargo
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.zargo
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/EmployerEmployee.zargo
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/Thumbs.db
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/Thumbs.db
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/full_cream.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/full_cream.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/full_cream.svg
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/images/full_cream.svg 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/images/full_cream.svg 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,429 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"
+[
+ <!ATTLIST svg
+ xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
+]>
+<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
+<svg
+
xmlns="http://www.w3.org/2000/svg"
+
xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="354.331"
+ height="336.614"
+ id="svg1">
+ <defs
+ id="defs3">
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop128" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop129" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient130"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ <radialGradient
+ cx="0.5"
+ cy="0.5"
+ fx="0.5"
+ fy="0.5"
+ r="0.5"
+ id="radialGradient131"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ </defs>
+ <g
+ transform="matrix(0.823795,0,0,0.823795,0.120302,5.25349)"
+ style="font-size:12;"
+ id="g659">
+ <rect
+ width="212.257"
+ height="57.2441"
+ x="17.9576"
+ y="100.132"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect137" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ transform="matrix(0.743454,0,0,0.482981,6.46949,52.2178)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect132" />
+ </g>
+ <rect
+ width="325.86"
+ height="63.6537"
+ x="17.4083"
+ y="15.194"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect136" />
+ <rect
+ width="325.86"
+ height="63.6537"
+ x="13.6713"
+ y="12.4966"
+ style="font-size:12;fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect126" />
+ <g
+ transform="matrix(1.14345,0,0,0.729078,-1.67818,105.325)"
+ style="font-size:12;"
+ id="g164">
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="16.6979"
+ y="222.966"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect138" />
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="14.7335"
+ y="221.002"
+ transform="translate(-1.30962,-1.30992)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect133" />
+ </g>
+ <text
+ x="170.824753"
+ y="58.402939"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text183">
+ <tspan
+ x="170.824997"
+ y="58.402901"
+ id="tspan360">
+Application</tspan>
+ </text>
+ <text
+ x="178.076340"
+ y="364.281433"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text197">
+ <tspan
+ x="178.076004"
+ y="364.281006"
+ id="tspan421">
+Database</tspan>
+ </text>
+ <text
+ x="68.605331"
+ y="138.524582"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text216">
+ <tspan
+ x="68.605301"
+ y="138.524994"
+ id="tspan384">
+SessionFactory</tspan>
+ </text>
+ <rect
+ width="67.0014"
+ height="101.35"
+ x="196.927"
+ y="89.2389"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect387" />
+ <rect
+ width="67.0014"
+ height="101.35"
+ x="194.633"
+ y="86.4389"
+ style="font-size:12;fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect388" />
+ <text
+ x="249.108841"
+ y="173.885559"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text389">
+ <tspan
+ x="249.108994"
+ y="173.886002"
+ id="tspan392">
+Session</tspan>
+ </text>
+ <rect
+ width="73.0355"
+ height="101.35"
+ x="270.995"
+ y="90.0018"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect395" />
+ <rect
+ width="73.0355"
+ height="101.35"
+ x="267.869"
+ y="87.2018"
+ style="font-size:12;fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect396" />
+ <text
+ x="328.593658"
+ y="174.715622"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text397">
+ <tspan
+ x="328.593994"
+ y="174.716003"
+ id="tspan563">
+Transaction</tspan>
+ </text>
+ <g
+ transform="matrix(0.29544,0,0,0.397877,9.70533,103.96)"
+ style="font-size:12;"
+ id="g565">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect566" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect567" />
+ </g>
+ <text
+ x="25.592752"
+ y="204.497803"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:10;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text568">
+ <tspan
+ x="25.592800"
+ y="204.498001"
+ id="tspan662">
+TransactionFactory</tspan>
+ </text>
+ <g
+ transform="matrix(0.298082,0,0,0.397877,99.6898,103.96)"
+ style="font-size:12;"
+ id="g573">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect574" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect575" />
+ </g>
+ <text
+ x="134.030670"
+ y="205.532791"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:10;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text576">
+ <tspan
+ x="134.031006"
+ y="205.533005"
+ id="tspan664">
+ConnectionProvider</tspan>
+ </text>
+ <g
+ transform="matrix(1.14345,0,0,0.729078,-1.67818,38.9539)"
+ style="font-size:12;"
+ id="g587">
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="16.6979"
+ y="222.966"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect588" />
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="14.7335"
+ y="221.002"
+ transform="translate(-1.30962,-1.30992)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect589" />
+ </g>
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="25.6196"
+ y="206.028"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect594" />
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="24.4229"
+ y="204.135"
+ style="font-size:12;fill:#b3b3b3;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect595" />
+ <text
+ x="85.575645"
+ y="282.300354"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;text-anchor:middle;"
+ id="text596">
+ <tspan
+ x="85.575600"
+ y="282.299988"
+ id="tspan607">
+JNDI</tspan>
+ </text>
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="236.937"
+ y="206.791"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect610" />
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="235.741"
+ y="204.898"
+ style="font-size:12;fill:#b3b3b3;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect611" />
+ <text
+ x="342.093201"
+ y="283.226410"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;text-anchor:middle;"
+ id="text612">
+ <tspan
+ x="342.092987"
+ y="283.226013"
+ id="tspan621">
+JTA</tspan>
+ </text>
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="130.134"
+ y="206.791"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect616" />
+ <rect
+ width="90.951"
+ height="44.4829"
+ x="128.937"
+ y="204.898"
+ style="font-size:12;fill:#b3b3b3;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect617" />
+ <text
+ x="212.445343"
+ y="283.226410"
+ transform="scale(0.823795,0.823795)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;text-anchor:middle;"
+ id="text618">
+ <tspan
+ x="212.445007"
+ y="283.226013"
+ id="tspan623">
+JDBC</tspan>
+ </text>
+ <g
+ transform="matrix(0.823795,0,0,0.823795,0.120302,6.19341)"
+ style="font-size:12;"
+ id="g637">
+ <g
+ transform="matrix(0.499515,0,0,0.415467,-0.237339,5.61339)"
+ id="g167">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect134" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect135" />
+ </g>
+ <text
+ x="33.749969"
+ y="50.589706"
+
style="font-size:11;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text188">
+ <tspan
+ x="33.750000"
+ y="50.589699"
+ id="tspan635">
+Transient Objects</tspan>
+ </text>
+ </g>
+ <g
+ transform="matrix(0.823795,0,0,0.823795,0.120302,5.25349)"
+ style="font-size:12;"
+ id="g644">
+ <g
+ transform="matrix(0.297486,0,0,0.516482,230.251,36.9178)"
+ id="g364">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect365" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect366" />
+ </g>
+ <text
+ x="277.123230"
+ y="85.155571"
+
style="font-size:11;font-weight:normal;stroke-width:1pt;font-family:Helvetica;text-anchor:middle;"
+ id="text367">
+ <tspan
+ x="277.122986"
+ y="85.155602"
+ id="tspan631">
+Persistent</tspan>
+ <tspan
+ x="277.122986"
+ y="96.155602"
+ id="tspan633">
+Objects</tspan>
+ </text>
+ </g>
+</svg>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/full_cream.svg
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/images/hibernate_logo_a.png
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/hibernate_logo_a.png
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/lite.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/lite.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/lite.svg
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/images/lite.svg 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/images/lite.svg 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,334 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"
+[
+ <!ATTLIST svg
+ xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
+]>
+<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
+<svg
+
xmlns="http://www.w3.org/2000/svg"
+
xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="318.898"
+ height="248.031"
+ id="svg1">
+ <defs
+ id="defs3">
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop128" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop129" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient130"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ <radialGradient
+ cx="0.5"
+ cy="0.5"
+ fx="0.5"
+ fy="0.5"
+ r="0.5"
+ id="radialGradient131"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ </defs>
+ <rect
+ width="291.837"
+ height="57.0074"
+ x="17.3169"
+ y="18.646"
+ style="font-size:12;fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect136" />
+ <rect
+ width="291.837"
+ height="57.0074"
+ x="13.9703"
+ y="16.2302"
+ style="font-size:12;fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect126" />
+ <g
+ transform="matrix(0.326107,0,0,0.765831,9.59261,8.98517)"
+ style="font-size:12;"
+ id="g161">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect137" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect132" />
+ </g>
+ <g
+ transform="matrix(1.02406,0,0,0.652953,0.223384,39.9254)"
+ style="font-size:12;"
+ id="g164">
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="16.6979"
+ y="222.966"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect138" />
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="14.7335"
+ y="221.002"
+ transform="translate(-1.30962,-1.30992)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect133" />
+ </g>
+ <g
+ transform="matrix(0.449834,0,0,0.338463,-3.15909,9.73319)"
+ style="font-size:12;"
+ id="g167">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect134" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect135" />
+ </g>
+ <text
+ x="302.277679"
+ y="65.943230"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text183">
+ <tspan
+ x="302.277954"
+ y="65.943184"
+ id="tspan360">
+Application</tspan>
+ </text>
+ <text
+ x="36.235924"
+ y="63.796055"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:14;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text188">
+ <tspan
+ x="36.235950"
+ y="63.796051"
+ id="tspan427">
+Transient Objects</tspan>
+ </text>
+ <text
+ x="180.416245"
+ y="290.543701"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:18;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text197">
+ <tspan
+ x="180.415939"
+ y="290.543549"
+ id="tspan421">
+Database</tspan>
+ </text>
+ <text
+ x="25.037701"
+ y="179.154755"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text216">
+ <tspan
+ x="25.037655"
+ y="179.154648"
+ id="tspan384">
+SessionFactory</tspan>
+ </text>
+ <g
+ transform="matrix(0.252763,0,0,0.765831,109.104,8.98517)"
+ style="font-size:12;"
+ id="g386">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect387" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect388" />
+ </g>
+ <g
+ transform="matrix(0.297394,0,0,0.572692,101.502,21.6359)"
+ style="font-size:12;"
+ id="g364">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect365" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect366" />
+ </g>
+ <text
+ x="202.746506"
+ y="102.992203"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:14;font-weight:normal;stroke-width:1pt;font-family:Helvetica;text-anchor:middle;"
+ id="text367">
+ <tspan
+ x="202.746948"
+ y="102.992249"
+ id="tspan423">
+Persistent</tspan>
+ <tspan
+ x="202.746948"
+ y="116.992355"
+ id="tspan425">
+Objects</tspan>
+ </text>
+ <text
+ x="174.458496"
+ y="180.080795"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text389">
+ <tspan
+ x="174.458618"
+ y="180.080338"
+ id="tspan392">
+Session</tspan>
+ </text>
+ <g
+ transform="matrix(0.127369,0,0,0.765831,188.675,8.98517)"
+ style="font-size:12;"
+ id="g394">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect395" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect396" />
+ </g>
+ <text
+ x="260.413269"
+ y="179.154739"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text397">
+ <tspan
+ x="260.412964"
+ y="179.154343"
+ id="tspan400">
+JDBC</tspan>
+ </text>
+ <g
+ transform="matrix(0.127369,0,0,0.765831,229.156,8.98517)"
+ style="font-size:12;"
+ id="g405">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect406" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect407" />
+ </g>
+ <text
+ x="320.606903"
+ y="179.154739"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text408">
+ <tspan
+ x="320.606964"
+ y="179.154343"
+ id="tspan417">
+JNDI</tspan>
+ </text>
+ <g
+ transform="matrix(0.127369,0,0,0.765831,269.281,8.98517)"
+ style="font-size:12;"
+ id="g411">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect412" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect413" />
+ </g>
+ <text
+ x="377.096313"
+ y="179.154739"
+ transform="scale(0.73778,0.73778)"
+
style="font-size:16;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text414">
+ <tspan
+ x="377.096008"
+ y="179.154999"
+ id="tspan145">
+JTA</tspan>
+ </text>
+</svg>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/lite.svg
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/images/overview.gif
===================================================================
(Binary files differ)
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/overview.gif
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:mime-type
+ application/octet-stream
Added: trunk/Hibernate3/doc/reference/pt-br/images/overview.svg
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/images/overview.svg 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/images/overview.svg 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,250 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
+"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"
+[
+ <!ATTLIST svg
+ xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
+]>
+<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
+<svg
+
xmlns="http://www.w3.org/2000/svg"
+
xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="248.031"
+ height="248.031"
+ id="svg1">
+ <defs
+ id="defs3">
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad">
+ <stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop128" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="1"
+ id="stop129" />
+ </linearGradient>
+ <linearGradient
+ x1="0"
+ y1="0"
+ x2="1"
+ y2="0"
+ id="linearGradient130"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ <radialGradient
+ cx="0.5"
+ cy="0.5"
+ fx="0.5"
+ fy="0.5"
+ r="0.5"
+ id="radialGradient131"
+ xlink:href="#linearGradient127"
+ gradientUnits="objectBoundingBox"
+ spreadMethod="pad" />
+ </defs>
+ <g
+ transform="matrix(0.771934,0,0,0.771934,4.36019,-3.02123)"
+ style="font-size:12;"
+ id="g158">
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="16.6979"
+ y="17.3527"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect136" />
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="14.7335"
+ y="15.3883"
+ transform="translate(-1.30962,-1.30992)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect126" />
+ </g>
+ <g
+ transform="matrix(0.771934,0,0,0.771934,4.36019,3.04452)"
+ style="font-size:12;"
+ id="g161">
+ <rect
+ width="285.502"
+ height="118.523"
+ x="16.6979"
+ y="99.2053"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect137" />
+ <rect
+ width="285.502"
+ height="118.523"
+ x="13.4238"
+ y="95.9309"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect132" />
+ </g>
+ <g
+ transform="matrix(0.771934,0,0,0.771934,4.36019,8.0993)"
+ style="font-size:12;"
+ id="g164">
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="16.6979"
+ y="222.966"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect138" />
+ <rect
+ width="285.502"
+ height="77.2688"
+ x="14.7335"
+ y="221.002"
+ transform="translate(-1.30962,-1.30992)"
+ style="fill:#d2d2d2;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect133" />
+ </g>
+ <g
+ transform="matrix(0.771934,0,0,0.543505,2.59104,21.1103)"
+ style="font-size:12;"
+ id="g167">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect134" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect135" />
+ </g>
+ <text
+ x="105.392174"
+ y="56.568123"
+ transform="scale(0.771934,0.771934)"
+
style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text183">
+ <tspan
+ x="105.392273"
+ y="56.568146"
+ id="tspan186">
+Application</tspan>
+ </text>
+ <text
+ x="81.820183"
+ y="103.149330"
+ transform="scale(0.771934,0.771934)"
+
style="font-size:20;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text188">
+ <tspan
+ x="81.820213"
+ y="103.149727"
+ id="tspan206">
+Persistent Objects</tspan>
+ </text>
+ <text
+ x="111.548180"
+ y="278.927887"
+ transform="scale(0.771934,0.771934)"
+
style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text197">
+ <tspan
+ x="111.547874"
+ y="278.927551"
+ id="tspan200">
+Database</tspan>
+ </text>
+ <text
+ x="94.436180"
+ y="153.805740"
+ transform="scale(0.771934,0.771934)"
+
style="font-size:24;font-weight:normal;stroke-width:1pt;font-family:Helvetica;"
+ id="text216">
+ <tspan
+ x="94.436180"
+ y="153.805740"
+ id="tspan221">
+HIBERNATE</tspan>
+ </text>
+ <g
+ transform="matrix(0.771934,0,0,0.771934,2.59083,1.02261)"
+ style="font-size:12;"
+ id="g254">
+ <g
+ transform="translate(4.58374,2.61928)"
+ id="g176">
+ <g
+ transform="matrix(0.571429,0,0,0.67347,-10.6174,117.093)"
+ id="g170">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect171" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect172" />
+ </g>
+ <g
+ transform="matrix(0.571429,0,0,0.67347,138.682,117.093)"
+ id="g173">
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="61.8805"
+ y="68.4288"
+ style="fill:#757575;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect174" />
+ <rect
+ width="199.065"
+ height="61.5532"
+ x="59.2613"
+ y="65.8095"
+ style="fill:#e0e0e0;fill-rule:evenodd;stroke-width:1pt;"
+ id="rect175" />
+ </g>
+ </g>
+ <text
+ x="47.259438"
+ y="182.367538"
+ style="font-weight:bold;stroke-width:1pt;font-family:Courier;"
+ id="text191">
+ <tspan
+ x="47.259399"
+ y="182.367996"
+ id="tspan212">
+hibernate.</tspan>
+ <tspan
+ x="47.259399"
+ y="194.367996"
+ id="tspan214">
+properties</tspan>
+ </text>
+ <text
+ x="198.523010"
+ y="188.260941"
+ style="font-weight:normal;stroke-width:1pt;font-family:helvetica;"
+ id="text194">
+ <tspan
+ id="tspan195">
+XML Mapping</tspan>
+ </text>
+ </g>
+</svg>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/images/overview.svg
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/master.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/master.xml 2006-08-14 14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/master.xml 2006-08-14 14:55:10 UTC (rev 10262)
@@ -0,0 +1,261 @@
+<?xml version='1.0' encoding="iso-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.3CR3//EN"
+ "../support/docbook-dtd/docbookx.dtd"
+[
+<!ENTITY tutorial SYSTEM "modules/tutorial.xml">
+<!ENTITY architecture SYSTEM "modules/architecture.xml">
+<!ENTITY configuration SYSTEM "modules/configuration.xml">
+<!ENTITY persistent-classes SYSTEM "modules/persistent_classes.xml">
+<!ENTITY basic-mapping SYSTEM "modules/basic_mapping.xml">
+<!ENTITY collection-mapping SYSTEM "modules/collection_mapping.xml">
+<!ENTITY association-mapping SYSTEM
"modules/association_mapping.xml">
+<!ENTITY component-mapping SYSTEM "modules/component_mapping.xml">
+<!ENTITY inheritance-mapping SYSTEM
"modules/inheritance_mapping.xml">
+<!ENTITY session-api SYSTEM "modules/session_api.xml">
+<!ENTITY transactions SYSTEM "modules/transactions.xml">
+<!ENTITY events SYSTEM "modules/events.xml">
+<!ENTITY batch SYSTEM "modules/batch.xml">
+<!ENTITY query-hql SYSTEM "modules/query_hql.xml">
+<!ENTITY query-criteria SYSTEM "modules/query_criteria.xml">
+<!ENTITY query-sql SYSTEM "modules/query_sql.xml">
+<!ENTITY filters SYSTEM "modules/filters.xml">
+<!ENTITY xml SYSTEM "modules/xml.xml">
+<!ENTITY performance SYSTEM "modules/performance.xml">
+<!ENTITY toolset-guide SYSTEM "modules/toolset_guide.xml">
+<!ENTITY example-parentchild SYSTEM
"modules/example_parentchild.xml">
+<!ENTITY example-weblog SYSTEM "modules/example_weblog.xml">
+<!ENTITY example-mappings SYSTEM "modules/example_mappings.xml">
+<!ENTITY best-practices SYSTEM "modules/best_practices.xml">
+]>
+
+<book lang="en">
+
+ <bookinfo>
+ <title>HIBERNATE - Relational Persistence for Idiomatic Java</title>
+ <subtitle>Documenta��o da Refer�ncia do Hibernate</subtitle>
+ <releaseinfo>3.2 cr2</releaseinfo>
+ </bookinfo>
+
+ <toc/>
+
+ <preface id="preface" revision="2">
+ <title>Pref�cio</title>
+
+ <para>
+ <emphasis>Advertencia! Esta � uma vers�o traduzida do ingl�s da
+ documenta��o de referencia do Hibernate. A vers�o traduziada pode estar
+ desatualizada. Sem d�vida, as diferen�as devem ser pequenas e ser�o corrigidas
o
+ mais breve possivel. Consulte a documenta��o de referencia em ingl�s, se
estiver
+ faltando alguma informa��o ou voc� encotrar erros de tradu��o. Se quiser
+ colaborar com ama tradu��o em particular, entre em contato com um dos
tradutores
+ abaixo:</emphasis>. Gamarra
+
+ </para>
+
+ <para>
+ Tradutor(es) em ordem alfab�tica:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Alvaro Netto</emphasis> alvaronetto(a)cetip.com.br
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Anderson Braulio</emphasis> andersonbraulio(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Daniel Vieira Costa</emphasis> danielvc(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Francisco gamarra</emphasis>
francisco.gamarra(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Gamarra</emphasis> mauricio.gamarra(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Luiz Carlos Rodrigues</emphasis>
luizcarlos_rodrigues(a)yahoo.com.br
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Marcel Castelo</emphasis> marcel.castelo(a)gmail.com
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ <emphasis>Paulo C�sar</emphasis> paulocol(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Pablo L. de Miranda</emphasis> pablolmiranda(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Renato Deggau</emphasis> rdeggau(a)gmail.com
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Rog�rio Ara�jo</emphasis> rgildoaraujo(a)yahoo.com.br
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Wanderson Siqueira</emphasis> wandersonxs(a)gmail.com
+ </para>
+ </listitem>
+
+
+ </itemizedlist>
+
+ <para>
+ Trabalhando com software orientado a objetos e banco de dados relacional,
podemos
+ ter alguns inc�modos hoje em dia em ambientes empresariais. Hibernate � uma
ferramenta
+ que mapeia o objeto/relacional para o ambiente Java. O termo de mapeamento de
+ objeto/relacional (ou ORM � Object/Relational Mapping) se refere a t�cnica de
mapear
+ uma representa��o de dados de um modelo de objeto para dados de modelo
+ relacional com o esquema baseado em SQL
+ </para>
+
+ <para>
+ O Hibernate n�o somente cuida do mapeamento de classes em Java
+ para tabelas de banco de dados (e de tipos de dados em Java para tipos de
dados em SQL), como tamb�m
+ fornece facilidade de consultas e recupera��o de dados, podendo tamb�m
reduzir significantemente o
+ tempo de desenvolvimento gasto com a manipula��o manual de dados no SQL e
JDBC.
+ </para>
+
+ <para>
+ O objetivo do Hibernate � de aliviar o desenvolvedor de 95 por cento das
tarefas de programa��o
+ relacionadas aos dados comuns de persist�ncia. O Hibernate talvez n�o seja a
melhor solu��o para
+ aplica��es de dados-data-centric que somente usa stored-procedures para
implementar a l�gica
+ de neg�cio no banco de dados, isto � muito utilizado com o dom�nio de modelos
orientado a objetos e
+ l�gicas de neg�cio em camadas do meio (middle-tier) baseadas em Java. Por�m,
o Hibernate
+ poder� certamente ajuda-lo a remover ou encapsular o c�digo SQL de um
vendedor espec�fico,
+ ajudando tamb�m com a tarefa comum da tradu��o do resultado ajustado de uma
representa��o
+ para um gr�fico de objetos.
+ </para>
+
+ <para>
+ Se voc� for novo no Hibernate e no mapeamento Objeto/Relacional, ou at� mesmo
em Java,
+ por favor, siga os seguintes passos.
+ </para>
+
+ <orderedlist>
+ <listitem>
+ <para>
+ Leia <xref linkend="tutorial"/> para um tutorial com
instru��es passo-a-passo.
+ O c�digo fonte para do tutorial est� inclu�do na distribui��o no
diret�rio
+ <literal>doc/reference/tutorial/</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Leia o <xref linkend="architecture"/> para entender o
ambiente onde o Hibernate pode ser utilizado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ D� uma olhada no diret�rio de exemplo
<literal>eg/</literal> da distribui��o
+ do Hibernate, ele cont�m uma simples aplica��o standalone.
+ Copie seu driver JDBC para o diret�rio
<literal>lib/</literal> e edite o arquivo
+ <literal>etc/hibernate.properties</literal>,
especificando corretamente os valores
+ para seu banco de dados. Usando o prompt de commando no diretorio de
distribuicao,
+ digite <literal>ant eg</literal> (usando Ant), ou no
Windows, digite
+ <literal>build eg</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Use esta documenta��o de referencia como sua fonte primaria de
informa��o.
+ Considere ler tamb�m o livro <emphasis>Hibernate in
Action</emphasis>
+ (
http://www.manning.com/bauer) caso voc� precise de mais ajuda com o
+ desenvolvimento de aplica��es ou caso prefira um tutorial
passo-a-passo.
+ Tamb�m visite o site
http://caveatemptor.hibernate.org e fa�a o
download
+ da aplica��o de exemplo do Hibernate em A��o.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ FAQs (perguntas feitas com mais freq��ncia) est�o respondidas no site do Hibernate
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Demonstra��es, exemplos e tutorials est�o dispon�veis no site do Hibernate.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A �rea da comunidade no site do Hibernate � uma boa fonte de recursos
+ para padr�es de projeto e v�rias solu��es de integra��o (Tomcat,
JBoss AS, Struts, EJB, etc.).
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Caso voc� tenha d�vidas, use o f�rum dos usu�rios encontrado no site do
Hibernate.
+ N�s tamb�m fornecemos um sistema para controle de bug�s (JIRA) para
relat�rios de erros
+ e requisi��es de features. Se voc� est� interessado no desenvolvimento do
Hibernate,
+ junte-se a lista de e-mail dos desenvolvedores.
+ </para>
+
+ <para>
+ Suporte comercial de desenvolvimento, suporte de produ��o e treinamento para
o Hibernate
+ est� dispon�vel atrav�s do JBoss Inc. (veja
http://www.hibernate.org/SupportTraining).
+ O Hibernate � um Projeto Profissional de C�digo Aberto e um componente
cr�tico da su�te
+ de produtos JBoss Enterprise Middleware System (JEMS).
+ </para>
+
+ </preface>
+
+ &tutorial;
+
+ &architecture;
+
+ &configuration;
+
+ &persistent-classes;
+
+ &basic-mapping;
+ &collection-mapping;
+ &association-mapping;
+ &component-mapping;
+ &inheritance-mapping;
+
+ &session-api;
+ &transactions;
+ &events;
+ &batch;
+
+ &query-hql;
+ &query-criteria;
+ &query-sql;
+ &filters;
+ &xml;
+
+ &performance;
+
+ &toolset-guide;
+
+ &example-parentchild;
+ &example-weblog;
+ &example-mappings;
+
+ &best-practices;
+
+</book>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/master.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/architecture.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/architecture.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/architecture.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,359 @@
+<chapter id="architecture">
+
+ <title>Arquitetura</title>
+
+ <sect1 id="architecture-overview" revision="1">
+ <title>Visão Geral</title>
+
+ <para>
+ Uma visão bem ampla da arquitetura do Hibernate:
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/overview.svg"
format="SVG" align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="../shared/images/overview.gif"
format="GIF" align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ Esse diagrama mostra o Hibernate usando o banco de dados e a configuração
+ de dados para prover persistência de serviços (e persistência de objetos)
+ para o aplicativo.
+ </para>
+
+ <para>
+ Nós gostaríamos de mostrar uma visão mais detalhada da arquitetura em
execução.
+ Infelizmente, o Hibernate é muito flexível e suporta várias
aproximações.
+ Nós iremos mostrar os dois extremos. Na arquitetura mais simples o aplicativo
+ fornece suas próprias conexões JDBC e gerencia suas transações. Esta
abordagem
+ usa o mínimo de subconjuntos das APIs do Hibernate:
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/lite.svg" format="SVG"
align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="../shared/images/lite.gif"
format="GIF" align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ A arquitetura "completa" abstrai a aplicação de ter de lidar
diretamente
+ com JDBC/JTA e APIs e deixa o Hibernate tomar conta dos detalhes.
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/full_cream.svg"
format="SVG" align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="../shared/images/full_cream.gif"
format="GIF" align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ Algumas definições dos objetos do diagrama:
+
+ <variablelist spacing="compact">
+ <varlistentry>
+ <term>SessionFactory
(<literal>org.hibernate.SessionFactory</literal>)</term>
+ <listitem>
+ <para>
+ Um cache threadsafe (imutáveis) composto de identidades
compiladas para um
+ único banco de dados. Uma fabrica para
<literal>Session</literal> e um cliente
+ de <literal>ConnectionProvider</literal>. Pode
conter um cachê opcional de
+ dados (segundo nível) reutilizáveis entre transações, no
nível de processo- ou cluster.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Session
(<literal>org.hibernate.Session</literal>)</term>
+ <listitem>
+ <para>
+ Objeto single-threaded, de vida curta, representando uma
conversação entre
+ o aplicativo e o armazenamento persistente. Cria uma camada
sobre uma conexão JDBC.
+ É uma fabrica de <literal>Transaction</literal>.
Possui um cachê obrigatório
+ (primeiro nível) de objetos persistentes, usado para
navegação no gráficos
+ de objetos e pesquisa de objetos pelo identificador.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Objetos persistentes e coleções</term>
+ <listitem>
+ <para>
+ Objetos, de vida curta, single threaded contendo estado
persistente e função
+ de negócios. Esses podem ser JavaBeans/POJOs, onde única
coisa especial sobre
+ eles é que são associados a (exatamente uma)
<literal>Session</literal>.
+ Quando a <literal>Session</literal> é fechada,
eles são separados e liberados
+ para serem usados dentro de qualquer camada da aplicacao (Ex.
diretamente como
+ data transfer objects de e para a camada de apresentação)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Objetos e coleções desatachados e
transientes</term>
+ <listitem>
+ <para>
+ Instâncias de classes persistentes que ainda não estão
associadas a uma
+ <literal>Session</literal>. Eles podem ter sido
instanciados pela aplicação
+ e não persistido (ainda) ou eles foram instanciados por uma
<literal>Session</literal>
+ que foi encerrada.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Transaction
(<literal>org.hibernate.Transaction</literal>)</term>
+ <listitem>
+ <para>
+ (Opcional) Objeto de vida curta, single threaded, usado pela
aplicação para
+ especificar unidades atômicas de trabalho. Abstrai o
aplicativo de lidar
+ diretamente com transações JDBC, JTA ou CORBA. Uma
<literal>Session</literal> pode,
+ em alguns casos, iniciar várias
<literal>Transaction</literal>s. Entretanto,
+ a demarcação da transação, mesmo utilizando API ou
Transaction subjacentes,
+ nunca é opcional!
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>ConnectionProvider
(<literal>org.hibernate.connection.ConnectionProvider</literal>)</term>
+ <listitem>
+ <para>
+ (Opcional) Uma fábrica de (e combinações de) conexões JDBC.
Abstrai a aplicação
+ de lidar diretamente com
<literal>Datasource</literal> ou
<literal>DriverManager</literal>.
+ Não exposto para a aplicação, mas pode ser implementado ou
estendido pelo programador.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>TransactionFactory
(<literal>org.hibernate.TransactionFactory</literal>)</term>
+ <listitem>
+ <para>
+ (Opcional) Uma fábrica para instâncias de
<literal>Transaction</literal>. Não exposta
+ a aplicação, mas pode ser extendida/implementada pelo
programador.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><emphasis>Extension
Interfaces</emphasis></term>
+ <listitem>
+ <para>
+ O Hibernate oferece várias opções de interfaces estendidas
que você pode implementar
+ para customizar sua camada persistente. Veja a documentação
da API para maiores detalhes.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </para>
+
+ <para>
+ Dada uma arquitetura simples, o aplicativo passa pelas APIs
+
<literal>Transaction</literal>/<literal>TransactionFactory</literal>
e/ou
+ <literal>ConnectionProvider</literal> para se comunicar
diretamente com a transação JTA ou JDBC.
+ </para>
+ </sect1>
+
+ <sect1 id="architecture-states" revision="1">
+ <title>Estados de instância</title>
+ <para>
+ Uma instância de classes persistentes pode estar em um dos três diferentes
estados,
+ que são definidos respeitando um <emphasis>contexto
persistente</emphasis>.
+ O objeto <literal>Session</literal> do Hibernate é o contexto
persistente:
+ </para>
+
+ <variablelist spacing="compact">
+ <varlistentry>
+ <term>transiente</term>
+ <listitem>
+ <para>
+ A instância não é, e nunca foi associada com nenhum
+ contexto persistente. Não possui uma identidade persistente
+ (valor de chave primária).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>persistente</term>
+ <listitem>
+ <para>
+ A instância está atualmente associada a um contexto persistente.
+ Possui uma identidade persistente (valor de chave primária) e,
+ talvez, correspondente a um registro no banco de dados. Para um
+ contexto persistente em particular, o Hibernate
+ <emphasis>guarantees</emphasis> que a identidade
persistente
+ é equivalente a identidade Java (na localização em memória do
+ objeto).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>desatachado</term>
+ <listitem>
+ <para>
+ A instância foi associada com um contexto persistente,
+ porém este contexto foi fechado, ou a instância
+ foi serializada por outro processo. Possui uma identidade
+ persistente, e, talvez, correspondenta a um registro no
+ banco de dados. Para instâncias desatachadas, o Hibernate
+ não garante o relacionamento entre identidade persistente
+ e identidade Java.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </sect1>
+
+ <sect1 id="architecture-jmx" revision="1">
+ <title>Integração JMX</title>
+
+ <para>
+ JMX é padrão J2EE para manipulação de componentes Java. O Hibernate pode ser
manipulado
+ por um serviço JMX padrão. Nós fornecemos uma implementação do MBean na
distribuição,
+ <literal>org.hibernate.jmx.HibernateService</literal>.
+ </para>
+
+ <para>
+ Para um exemplo de como instalar o Hibernate como um serviço JMX em um
servidor de
+ aplicativo JBoss, por favor, consulte o manual do usuário do JBoss. No JBoss
As, você
+ poderá ver os benefícios de de se fazer o deploy usando JMX:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Session Management:</emphasis> O ciclo de vida
de uma <literal>Session</literal> do
+ Hibernate pode ser automaticamente conectada a um escopo de transação
JTA. Isso significa
+ que você não precisará mais abrir e fechar manualmente uma
<literal>Session</literal>, isso
+ se torna trabalho para um interceptor EJB do JBoss . Você também não
precisa se preocupar,
+ nunca mais, com demarcação de transação em seu código (a não ser que
você prefira escrever
+ uma camada persistente portável, para isso, use a API opcional do
Hibernate
+ <literal>Transaction</literal>). Você deve chamar
<literal>HibernateContext</literal>
+ para acessar uma <literal>Session</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>HAR deployment:</emphasis>: Normalmente você
faz o deploy de um serviço JMX do
+ Hibernate usando um serviço descritor de deploy do JBoss (em um EAR
e/ou arquivo SAR),
+ que suporta todas as configurações usuais de uma
<literal>SessionFactory</literal> do
+ Hibernate. Entretanto, você ainda precisa nomear todos os seus
arquivos de mapeamento
+ no descritor de deploração. Se você decidir usar o deploy opcional
HAR, o JBoss irá
+ automaticamente detectar todos os seus arquivos de mapeamento no seu
arquivo HAR.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Consulte o manual do usuário do JBoss AS, para obter maiores informações
sobre essas opções.
+ </para>
+
+ <para>
+ Another feature available as a JMX service are runtime Hibernate statistics.
See
+ <xref linkend="configuration-optional-statistics"/>.
+ Outra opção disponível como um serviço JMX são as estatísticas de execução do
Hibernate.
+ Veja a <xref linkend="configuration-optional-statistics"/>.
+ </para>
+ </sect1>
+
+ <sect1 id="architecture-jca" revision="1">
+ <title>Suporte JCA</title>
+ <para>
+ Hibernate may also be configured as a JCA connector. Please see the website
for more
+ details. Please note that Hibernate JCA support is still considered
experimental.
+ O Hibernate pode também ser configurado como um conector JCA. Por favor,
visite o
+ website para maiores detalhes. Entretanto, note que o suporte JCA do
Hibernate
+ ainda é considerado experimental.
+ </para>
+ </sect1>
+
+ <sect1 id="architecture-current-session" revision="2">
+ <title>Sessões contextuais</title>
+ <para>
+ Muitas aplicações que usam o Hibernate necessita de algum tipo de sessão
"contextual",
+ onde uma sessão dada é na verdade um escopo de um contexto. Entretanto,
através de aplicações
+ a definição sobre um contexto é geralmente diferente; e contextos diferentes
definem escopos
+ diferentes. Aplicações usando versões anteriores ao Hibernate 3.0 tendem a
utilizar tanto
+ sessões contextuais baseadas em <literal>ThreadLocal</literal>,
classes utilitárias como
+ <literal>HibernateUtil</literal>, ou utilizar frameworks de
terceiros(como Spring ou Pico)
+ que provê sessões contextuais baseadas em proxy.
+
+ </para>
+ <para>
+ A partir da versão 3.0.1, o Hibernate adicionou o método
<literal>SessionFactory.getCurrentSession()</literal>.
+ Inicialmente, este assume o uso de transações
<literal>JTA</literal>, onde a transação
+ <literal>JTA</literal> define tanto o escopo quanto o contexto de
uma sessão atual.
+ O time do Hibernate mantém este recurso, desenvolvendo as diversas
implementações do
+ <literal>JTA TransactionManager</literal>, a maioria (se não
todos) aplicativos deveria
+ utilizar o gerenciador de transações <literal>JTA</literal> sendo
ou não instalados dentro
+ de um container <literal>J2EE</literal>. Baseado neste recurso,
você deveria sempre utilizar sessões
+ contextuais baseadas em <literal>JTA</literal>.
+ </para>
+ <para>
+ Entretanto, na versão 3.1, o processo por trás do método
<literal>SessionFactory.getCurrentSession()</literal>
+ é agora plugavel. Com isso, uma nova interface
(<literal>org.hibernate.context.CurrentSessionContext</literal>)
+ e um novo parâmetro de configuração
(<literal>hibernate.current_session_context_class</literal>)
+ foram adicionados para possibilitar a compatibilidade do contexto e do escopo
na definição de sessões correntes.
+ </para>
+ <para>
+ De uma olhada em Javadocs sobre a interface
<literal>org.hibernate.context.CurrentSessionContext</literal>
+ para uma discussão detalhada. Ela define um método único,
<literal>currentSession()</literal>,
+ com o qual a implementação é responsável por rastrear a sessão contextual
corrente.
+ Por fora do "encapsulamento", o Hibernate possui duas
implementações dessa interface.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+
<literal>org.hibernate.context.JTASessionContext</literal> - As sessões
correntes
+ são rastreadas e recebem um escopo por uma transação
<literal>JTA</literal>.
+ O processamento aqui é exatamente igual ao antigo processo JTA.
Consulte em
+ Javadocs para maiores detalhes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+
<literal>org.hibernate.context.ThreadLocalSessionContext</literal> - As
sessões
+ correntes são rastreadas por uma thread de execução. Novamente,
consulte em
+ Javadocs para maiores detalhes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+
<literal>org.hibernate.context.ManagedSessionContext</literal> - current
+ sessions are tracked by thread of execution. However, you are
responsible to
+ bind and unbind a <literal>Session</literal> instance
with static methods
+ on this class, it does never open, flush, or close a
<literal>Session</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ As duas primeiras implementações usam o modelo de programação "uma
sessão – uma transação
+ do banco de dados", também conhecida e usado como <emphasis>sessão
por requisição</emphasis>.
+ O começo e o fim de uma sessão Hibernate é definida pela duração da transação
do banco de dados.
+ Se você usa demarcação programática de transação (por exemplo. em J2SE puro
ou com JTA
+ /UserTransaction/BMT), você é recomendado a usar a API Hibernate
<literal>Transaction</literal>
+ para esconder a base do sistema de transação do seu código. Se você executa
em um container EJB
+ que suporta CMT, os limites das transações são definidas declarativamente e
você não necessita
+ de qualquer transação ou operação de demarcação de sessão no seu código.
Consulte o <xref linkend="transactions"/>
+ para mais informações exemplos de código.
+ </para>
+
+ <para>
+ O parâmetro de configuração
<literal>hibernate.current_session_context_class</literal>
+ define que a implementação
<literal>org.hibernate.context.CurrentSessionContext</literal>
+ deve ser usada. Note que para compatibilidade anterior, se este parâmetro de
configuração
+ não é determinado mas um
<literal>org.hibernate.transaction.TransactionManagerLookup</literal>
+ é configurado, Hibernate usará o
<literal>org.hibernate.context.JTASessionContext</literal>.
+ Tipicamente, o valor deste parâmetro nomearia apenas a classe de
implementação para usar;
+ para as duas implementações out-of-the-box, entretanto, há dois pequenos
nomes correspondentes,
+ "jta", "thread", and "managed".
+ </para>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/architecture.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/association_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/association_mapping.xml 2006-08-14
14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/association_mapping.xml 2006-08-14
14:55:10 UTC (rev 10262)
@@ -0,0 +1,635 @@
+<chapter id="associations">
+
+ <title>Mapeamento de Associações</title>
+
+ <sect1 id="assoc-intro" revision="1">
+ <title>Introdução</title>
+
+ <para>
+ Mapeamentos de associações são freqüentemente a coisa mais difícil de se
+ acertar. Nesta seção nós passaremos pêlos casos canônicos um pôr um,
+ começando com mapeamentos unidirecionais e considerando os casos
+ bidirecionais. Nos vamos usar <literal>Person</literal> e
+ <literal>Address</literal> em todos os exemplos.
+ </para>
+
+ <para>
+ Nós classificaremos as associações pelo seu mapeamento ou a falta do
+ mesmo, sua intervenção na tabela associativa, e pela sua multiplicidade.
+ </para>
+
+ <para>
+ O uso de chaves estrangeiras não obrigatórias não é considerada uma boa
+ prática na modelagem de dados tradicional, assim todos nossos exemplos
+ usam chaves estrangeiras obrigatórias. Esta não é uma exigência do
+ Hibernate, e todas as mapeamentos funcionarão se você remover as
+ constraints de obrigatoriedade.
+ </para>
+
+ </sect1>
+
+ <sect1 id="assoc-unidirectional" revision="1">
+ <title>Associações Unidirecionais</title>
+
+ <sect2 id="assoc-unidirectional-m21">
+ <title>muitos para um</title>
+
+ <para>
+ Uma <emphasis>associação unidirecional muitos-para-um</emphasis>
é o
+ tipo mais comum de associação unidirecional.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"/>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key, addressId bigint not null )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-unidirectional-121">
+ <title>um para um</title>
+
+ <para>
+ Uma <emphasis>associação unidirecional um-para-um em uma chave
estrangeira
+ </emphasis> é quase idêntica. A única diferença é a constraint unique
+ na coluna.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <many-to-one name="address"
+ column="addressId"
+ unique="true"
+ not-null="true"/>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key, addressId bigint not null
unique )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ <para>
+ Uma <emphasis>associação unidirecional um-para-um na chave
primaria</emphasis>
+ geralmente usa um gerador de id special. ( Note que nós invertemos a
+ direção da associação nesse exemplo).
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+</class>
+
+<class name="Address">
+ <id name="id" column="personId">
+ <generator class="foreign">
+ <param name="property">person</param>
+ </generator>
+ </id>
+ <one-to-one name="person" constrained="true"/>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table Address ( personId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-unidirectional-12m">
+ <title>um para muitos</title>
+
+ <para>
+ Uma <emphasis>associação unidirecional um-para-muitos em uma chave
+ estrangeira</emphasis> é um caso muito incomum, e realmente não é
recomendada.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <set name="addresses">
+ <key column="personId"
+ not-null="true"/>
+ <one-to-many class="Address"/>
+ </set>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table Address ( addressId bigint not null primary key, personId bigint not null )
+ ]]></programlisting>
+
+ <para>
+ Nós achamos que é melhor usar uma tabela associativa para este tipo de
+ associação.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="assoc-unidirectional-join" revision="1">
+ <title>Associações Unidirecionais com tabelas associativas</title>
+
+ <sect2 id="assoc-unidirectional-join-12m">
+ <title>um para muitos</title>
+
+ <para>
+ Uma <emphasis>associação um-para-muitos unidirecional usando uma tabela
+ associativa</emphasis> e o mais comum. Note que se especificarmos
+ <literal>unique="true"</literal>, estaremos modificando
a cardinalidade
+ de muitos-para-muitos para um-para-muitos.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <set name="addresses" table="PersonAddress">
+ <key column="personId"/>
+ <many-to-many column="addressId"
+ unique="true"
+ class="Address"/>
+ </set>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId not null, addressId bigint not null primary key )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-unidirectional-join-m21">
+ <title>muitos para um</title>
+
+ <para>
+ Uma <emphasis>associação unidirecional muitos-para-um em uma tabela
+ associativa</emphasis> é bastante comum quando a associação for
opcional.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <join table="PersonAddress"
+ optional="true">
+ <key column="personId" unique="true"/>
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"/>
+ </join>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null primary key, addressId bigint not
null )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-unidirectional-join-121">
+ <title>um para um</title>
+
+ <para>
+ Uma <emphasis>associação unidirecional um-para-um em uma tabela
+ associativa</emphasis> é extremamente incomum, mas possível.
+
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <join table="PersonAddress"
+ optional="true">
+ <key column="personId"
+ unique="true"/>
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"
+ unique="true"/>
+ </join>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null primary key, addressId bigint not
null unique )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-unidirectional-join-m2m">
+ <title>muitos para muitos</title>
+
+ <para>
+ Finalmente, nós temos a <emphasis>associação unidirecional
muitos-para-
+ muitos</emphasis>.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <set name="addresses" table="PersonAddress">
+ <key column="personId"/>
+ <many-to-many column="addressId"
+ class="Address"/>
+ </set>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null, addressId bigint not null, primary
key (personId, addressId) )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="assoc-bidirectional" revision="1">
+ <title>Associações Bidirecionais</title>
+
+ <sect2 id="assoc-bidirectional-m21" revision="2">
+ <title>um para muitos / muitos para um</title>
+
+ <para>
+ Uma <emphasis>associação bidirecional muitos-para-um</emphasis> é
o
+ tipo mais comum de associação. (Esse é o relacionamento padrão
+ pai / filho. )
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"/>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+ <set name="people" inverse="true">
+ <key column="addressId"/>
+ <one-to-many class="Person"/>
+ </set>
+</class>]]></programlisting>
+
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key, addressId bigint not null )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ <para>
+ Se você usar uma <literal>List</literal> ( ou outra coleção
indexada ), você
+ precisa especificar a coluna <literal>chave</literal> estrangeira
como not null,
+ e deixar o Hibernate administrar a associação do lado da coleção para que
+ seja mantido o índice de cada elemento da coleção (fazendo com que o outro
+ lado seja virtualmente inverso setando
<literal>update="false"</literal>
+ e <literal>insert="false"</literal>):
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id"/>
+ ...
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"
+ insert="false"
+ update="false"/>
+</class>
+
+<class name="Address">
+ <id name="id"/>
+ ...
+ <list name="people">
+ <key column="addressId" not-null="true"/>
+ <list-index column="peopleIdx"/>
+ <one-to-many class="Person"/>
+ </list>
+</class>]]></programlisting>
+
+ <para>
+ É importante que você defina
<literal>not-null="true"</literal> no elemento
+ <literal><key></literal> no mapeamento na
coleção se a coluna de chave
+ estrangeira for <literal>NOT NULL</literal>. Não declare como
+ <literal>not-null="true"</literal> apenas um
elemento aninhado
+ <literal><column></literal>, mas sim o elemento
+ <literal><key></literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="assoc-bidirectional-121">
+ <title>um para um</title>
+
+ <para>
+ Uma <emphasis>associação bidirecional um para um em uma chave
estrangeira</emphasis>
+ é bastante comum.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <many-to-one name="address"
+ column="addressId"
+ unique="true"
+ not-null="true"/>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+ <one-to-one name="person"
+ property-ref="address"/>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key, addressId bigint not null
unique )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ <para>
+ Uma <emphasis>associação bidirecional um para um em uma chave
primária</emphasis>
+ usa um gerador de id especial.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <one-to-one name="address"/>
+</class>
+
+<class name="Address">
+ <id name="id" column="personId">
+ <generator class="foreign">
+ <param name="property">person</param>
+ </generator>
+ </id>
+ <one-to-one name="person"
+ constrained="true"/>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table Address ( personId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="assoc-bidirectional-join" revision="1">
+ <title>Associações Bidirecionais com tabelas associativas</title>
+
+ <sect2 id="assoc-bidirectional-join-12m">
+ <title>um para muitos / muitos para um</title>
+
+ <para>
+ Uma <emphasis>associação bidirecional um para muitos em uma tabela
+ associativa</emphasis>. Veja que
<literal>inverse="true"</literal> pode ser
+ colocado em qualquer ponta associação, na coleção, ou no join.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <set name="addresses"
+ table="PersonAddress">
+ <key column="personId"/>
+ <many-to-many column="addressId"
+ unique="true"
+ class="Address"/>
+ </set>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+ <join table="PersonAddress"
+ inverse="true"
+ optional="true">
+ <key column="addressId"/>
+ <many-to-one name="person"
+ column="personId"
+ not-null="true"/>
+ </join>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null, addressId bigint not null primary
key )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-bidirectional-join-121">
+ <title>one to one</title>
+
+ <para>
+ Uma <emphasis>associação bidirecional um-para-um em uma tabela de
+ associação</emphasis> é algo bastante incomum, mas possivel.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <join table="PersonAddress"
+ optional="true">
+ <key column="personId"
+ unique="true"/>
+ <many-to-one name="address"
+ column="addressId"
+ not-null="true"
+ unique="true"/>
+ </join>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+ <join table="PersonAddress"
+ optional="true"
+ inverse="true">
+ <key column="addressId"
+ unique="true"/>
+ <many-to-one name="person"
+ column="personId"
+ not-null="true"
+ unique="true"/>
+ </join>
+</class>]]></programlisting>
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null primary key, addressId bigint not
null unique )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="assoc-bidirectional-join-m2m" revision="1">
+ <title>muitos para muitos</title>
+
+ <para>
+ Finally, we have a <emphasis>bidirectional many-to-many
association</emphasis>.
+ Finalmente, nós temos uma associação bidirecional de muitos para muitos.
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id" column="personId">
+ <generator class="native"/>
+ </id>
+ <set name="addresses" table="PersonAddress">
+ <key column="personId"/>
+ <many-to-many column="addressId"
+ class="Address"/>
+ </set>
+</class>
+
+<class name="Address">
+ <id name="id" column="addressId">
+ <generator class="native"/>
+ </id>
+ <set name="people" inverse="true"
table="PersonAddress">
+ <key column="addressId"/>
+ <many-to-many column="personId"
+ class="Person"/>
+ </set>
+</class>]]></programlisting>
+
+ <programlisting><![CDATA[
+create table Person ( personId bigint not null primary key )
+create table PersonAddress ( personId bigint not null, addressId bigint not null, primary
key (personId, addressId) )
+create table Address ( addressId bigint not null primary key )
+ ]]></programlisting>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="assoc-complex">
+ <title>Mapeamento de associações mais complexas</title>
+
+ <para>
+ More complex association joins are <emphasis>extremely</emphasis>
rare.
+ Hibernate makes it possible to handle more complex situations using
+ SQL fragments embedded in the mapping document. For example, if a table
+ with historical account information data defines
+ <literal>accountNumber</literal>,
<literal>effectiveEndDate</literal>
+ and <literal>effectiveStartDate</literal>columns, mapped as
follows:
+Joins de associações mais complexas são extremamente raros. O Hibernate torna possível
tratar mapeamentos mais complexos usando fragmentos de SQL embutidos no documento de
mapeamento. Por exemplo, se uma tabela com informações de dados históricos de uma conta
define a coluna accountNumber, effectiveEndDate e effectiveStartDate, mapeadas assim como
segue:
+ </para>
+
+ <programlisting><![CDATA[<properties
name="currentAccountKey">
+ <property name="accountNumber" type="string"
not-null="true"/>
+ <property name="currentAccount" type="boolean">
+ <formula>case when effectiveEndDate is null then 1 else 0
end</formula>
+ </property>
+</properties>
+<property name="effectiveEndDate" type="date"/>
+<property name="effectiveStateDate" type="date"
not-null="true"/>]]></programlisting>
+
+ <para>
+ Then we can map an association to the
<emphasis>current</emphasis> instance
+ (the one with null <literal>effectiveEndDate</literal>) using:
+Então nós podemos mapear uma associação para a instância corrente (aquela com a
effectiveEndDate igual a null) usando:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one
name="currentAccountInfo"
+ property-ref="currentAccountKey"
+ class="AccountInfo">
+ <column name="accountNumber"/>
+ <formula>'1'</formula>
+</many-to-one>]]></programlisting>
+
+ <para>
+ In a more complex example, imagine that the association between
+ <literal>Employee</literal> and
<literal>Organization</literal> is maintained
+ in an <literal>Employment</literal> table full of historical
employment data.
+ Then an association to the employee's <emphasis>most
recent</emphasis> employer
+ (the one with the most recent <literal>startDate</literal>) might
be mapped this way:
+Em um exemplo mais complexo, imagine que a associação entre Employee e Organization é
mantida em uma tabela Employment cheia de dados históricos do trabalho. Então a associação
do funcionário mais recentemente empregado (aquele com a mais recente startDate) deve ser
mapeado desta maneira:
+ </para>
+
+ <programlisting><![CDATA[<join>
+ <key column="employeeId"/>
+ <subselect>
+ select employeeId, orgId
+ from Employments
+ group by orgId
+ having startDate = max(startDate)
+ </subselect>
+ <many-to-one name="mostRecentEmployer"
+ class="Organization"
+ column="orgId"/>
+</join>]]></programlisting>
+
+ <para>
+ You can get quite creative with this functionality, but it is usually more
practical
+ to handle these kinds of cases using HQL or a criteria query.
+Você pode ser criativo com esta funcionalidade, mas geralmente é mais prático tratar
estes tipos de casos, usando uma pesquisa HQL ou uma pesquisa por criteria.
+ </para>
+
+ </sect1>
+
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/association_mapping.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/basic_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/basic_mapping.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/basic_mapping.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,3491 @@
+<chapter id="mapping">
+ <title>Mapeamento O/R Bassico</title>
+
+ <sect1 id="mapping-declaration" revision="1">
+ <title>Declaração de mapeamento</title>
+
+ <para>
+ Object/relational mappings are usually defined in an XML document. The
mapping
+ document is designed to be readable and hand-editable. The mapping language
is
+ Java-centric, meaning that mappings are constructed around persistent class
+ declarations, not table declarations.
+ </para>
+
+ <para>
+ Note that, even though many Hibernate users choose to write the XML by hand,
+ a number of tools exist to generate the mapping document, including XDoclet,
+ Middlegen and AndroMDA.
+ </para>
+
+ <para>
+ Lets kick off with an example mapping:
+ </para>
+
+ <programlisting id="mapping-declaration-ex1"
revision="1"><![CDATA[<?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="eg">
+
+ <class name="Cat"
+ table="cats"
+ discriminator-value="C">
+
+ <id name="id">
+ <generator class="native"/>
+ </id>
+
+ <discriminator column="subclass"
+ type="character"/>
+
+ <property name="weight"/>
+
+ <property name="birthdate"
+ type="date"
+ not-null="true"
+ update="false"/>
+
+ <property name="color"
+ type="eg.types.ColorUserType"
+ not-null="true"
+ update="false"/>
+
+ <property name="sex"
+ not-null="true"
+ update="false"/>
+
+ <property name="litterId"
+ column="litterId"
+ update="false"/>
+
+ <many-to-one name="mother"
+ column="mother_id"
+ update="false"/>
+
+ <set name="kittens"
+ inverse="true"
+ order-by="litter_id">
+ <key column="mother_id"/>
+ <one-to-many class="Cat"/>
+ </set>
+
+ <subclass name="DomesticCat"
+ discriminator-value="D">
+
+ <property name="name"
+ type="string"/>
+
+ </subclass>
+
+ </class>
+
+ <class name="Dog">
+ <!-- mapping for Dog could go here -->
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Discutir agora o conteúdo deste documento de mapeamento. Iremos apenas
descrever
+ os elementos do documento e atributos que são utilizados pelo Hibernate em
tempo
+ de execução. O documento de mapeamento também contém alguns atributos
adicionais
+ e opcionais além de elementos que afetam os esquemas de banco de dados
exportados
+ pela ferramenta de exportação de esquemas. (Por exemplo, o atributo
+ <literal>not-null</literal>).
+ </para>
+
+
+
+ <sect2 id="mapping-declaration-doctype" revision="3">
+ <title>Doctype</title>
+
+ <para>
+ Todos os mapeamentos de XML devem declarar o doctype exibido. O DTD atual
pode
+ ser encontrado na URL abaixo, no diretório
<literal>hibernate-x.x.x/src/org/
+ hibernate </literal> ou no
<literal>hibernate3.jar</literal>. O Hibernate sempre
+ irá procurar pelo DTD inicialmente no seu classpath. Se você tentar
localizar
+ o DTD usando uma conexão de internet, compare a declaração do seu DTD com
o
+ conteúdo do seu classpath
+ </para>
+
+ <sect3 id="mapping-declaration-entity-resolution">
+ <title>EntityResolver</title>
+ <para>
+ As mentioned previously, Hibernate will first attempt to resolve DTDs
in its classpath. The
+ manner in which it does this is by registering a custom
<literal>org.xml.sax.EntityResolver</literal>
+ implementation with the SAXReader it uses to read in the xml files.
This custom
+ <literal>EntityResolver</literal> recognizes two
different systemId namespaces.
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ a <literal>hibernate namespace</literal> is
recognized whenever the
+ resolver encounteres a systemId starting with
+
<
literal>http://hibernate.sourceforge.net/</literal>; the resolver
+ attempts to resolve these entities via the classlaoder which
loaded
+ the Hibernate classes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ a <literal>user namespace</literal> is recognized
whenever the
+ resolver encounteres a systemId using a
<literal>classpath://</literal>
+ URL protocol; the resolver will attempt to resolve these
entities
+ via (1) the current thread context classloader and (2) the
+ classloader which loaded the Hibernate classes.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ An example of utilizing user namespacing:
+ </para>
+ <programlisting><![CDATA[<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" [
+ <!ENTITY types SYSTEM "classpath://your/domain/types.xml">
+]>
+
+<hibernate-mapping package="your.domain">
+ <class name="MyEntity">
+ <id name="id" type="my-custom-id-type">
+ ...
+ </id>
+ <class>
+ &types;
+</hibernate-mapping>]]></programlisting>
+ <para>
+ Where <literal>types.xml</literal> is a resource in the
<literal>your.domain</literal>
+ package and contains a custom <xref
linkend="mapping-types-custom">typedef</xref>.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 id="mapping-declaration-mapping" revision="3">
+ <title>hibernate-mapping</title>
+
+ <para>
+ Este elemento tem diversos atributos opcionais. Os atributos
+ <literal>schema</literal> e
<literal>catalog</literal> especificam que tabelas
+ referenciadas neste mapeamento pertencem ao esquema e/ou ao catalogo
nomeado.
+ Se especificados, os nomes das tabelas irão ser qualificados no schema ou
catalog dado.
+ Se não, os nomes das tabelas não serão qualificados. O atributo
<literal>default-cascade
+ </literal> especifica qual estilo de cascata será assumido pelas
propriedades e
+ coleções que não especificarm um atributo
<literal>cascade</literal>. O atributo
+ <literal>auto-import</literal> nos deixa utilizar nomes de
classes não qualificados
+ na linguagem de consulta, por default.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="hm1" coords="2 55"/>
+ <area id="hm2" coords="3 55"/>
+ <area id="hm3" coords="4 55"/>
+ <area id="hm4" coords="5 55"/>
+ <area id="hm5" coords="6 55"/>
+ <area id="hm6" coords="7 55"/>
+ <area id="hm7" coords="8 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<hibernate-mapping
+ schema="schemaName"
+ catalog="catalogName"
+ default-cascade="cascade_style"
+ default-access="field|property|ClassName"
+ default-lazy="true|false"
+ auto-import="true|false"
+ package="package.name"
+ />]]></programlisting>
+ <calloutlist>
+ <callout arearefs="hm1">
+ <para>
+ <literal>schema</literal> (opcional): O nome do
esquema do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="hm2">
+ <para>
+ <literal>catalog</literal> (opcional): O nome
do catálogo do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="hm3">
+ <para>
+ <literal>default-cascade</literal> (opcional –
default é <literal>nenhum
+ </literal>): Um estilo cascata default.
+ </para>
+ </callout>
+ <callout arearefs="hm4">
+ <para>
+ <literal>default-access</literal> (opcional –
default é <literal>property</literal>):
+ A estratégia que o Hibernate deve utilizar para acessar
todas as propridades. Pode
+ ser uma implementação própria de
<literal>PropertyAccessor</literal>.
+ </para>
+ </callout>
+ <callout arearefs="hm5">
+ <para>
+ <literal>default-lazy</literal> (opcional -
default é <literal>true</literal>):
+ O valor default para atributos
<literal>lazy</literal> da classe e dos
+ mapeamentos de coleções.
+ </para>
+ </callout>
+ <callout arearefs="hm6">
+ <para>
+ <literal>auto-import</literal> ((opcional -
default é <literal>true</literal>):
+ Especifica se nós podemos usar nomes de classess não
qualificados
+ (das classes deste mapeamento) na linguagem de consulta.
+ </para>
+ </callout>
+ <callout arearefs="hm7">
+ <para>
+ <literal>package</literal> (opcional):
Especifica um prefixo da package para
+ assumir para nomes de classes não qualificadas no documento
de mapeamento.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Se voce tem duas classes persistentes com o mesmo nome (não
qualificadas), você deve
+ setar <literal>auto-import="false"</literal>. O
Hibernate irá gerar uma exceção se
+ você tentar setar duas classes para o mesmo nome "importado".
+ </para>
+
+ <para>
+ Observe que o elemento <literal>hibernate-mapping</literal>
permite a você
+ aninhar diversos mapeamentos de
<literal><class></literal> persistentes,
+ como mostrado abaixo. Entretanto, é uma boa prática (e esperado por
algumas
+ ferramentas)o mapeamento de apenas uma classe persistente simples (ou
uma
+ hierarquia de classes simples) em um arquivo de mapeamento e nomea-la
após
+ a superclasse persistente, por exemplo:
<literal>Cat.hbm.xml</literal>,
+ <literal>Dog.hbm.xml</literal>, ou se estiver usando
herança,
+ <literal>Animal.hbm.xml</literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-class" revision="3">
+ <title>class</title>
+
+ <para>
+ Você pode declarar uma classe persistente utilizando o elemento
+ <literal>class</literal>:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="class1" coords="2 55"/>
+ <area id="class2" coords="3 55" />
+ <area id="class3" coords="4 55"/>
+ <area id="class4" coords="5 55" />
+ <area id="class5" coords="6 55"/>
+ <area id="class6" coords="7 55" />
+ <area id="class7" coords="8 55"/>
+ <area id="class8" coords="9 55" />
+ <area id="class9" coords="10 55" />
+ <area id="class10" coords="11 55"/>
+ <area id="class11" coords="12 55"/>
+ <area id="class12" coords="13 55"/>
+ <area id="class13" coords="14 55"/>
+ <area id="class14" coords="15 55"/>
+ <area id="class15" coords="16 55"/>
+ <area id="class16" coords="17 55"/>
+ <area id="class17" coords="18 55"/>
+ <area id="class18" coords="19 55"/>
+ <area id="class19" coords="20 55"/>
+ <area id="class20" coords="21 55"/>
+ <area id="class21" coords="22 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<class
+ name="ClassName"
+ table="tableName"
+ discriminator-value="discriminator_value"
+ mutable="true|false"
+ schema="owner"
+ catalog="catalog"
+ proxy="ProxyInterface"
+ dynamic-update="true|false"
+ dynamic-insert="true|false"
+ select-before-update="true|false"
+ polymorphism="implicit|explicit"
+ where="arbitrary sql where condition"
+ persister="PersisterClass"
+ batch-size="N"
+ optimistic-lock="none|version|dirty|all"
+ lazy="true|false"
+ entity-name="EntityName"
+ check="arbitrary sql check condition"
+ rowid="rowid"
+ subselect="SQL expression"
+ abstract="true|false"
+ node="element-name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="class1">
+ <para>
+ <literal>name</literal> (opcional): O nome da
classe Java inteiramente qualificado
+ da classe persistente (ou interface); Se o atributo é
ausente, assume-se que o
+ mapeamento é para intidades não-POJO.
+ </para>
+ </callout>
+ <callout arearefs="class2">
+ <para>
+ <literal>table</literal> (opcional – default para
nomes de classes não
+ qualificadas) O nome da sua tabela do banco de dados.
+ </para>
+ </callout>
+ <callout arearefs="class3">
+ <para>
+ <literal>discriminator-value</literal> (opcional
– default para o nome da classe):
+ Um valor que distingue subclasses individuais, usadas para o
comportamento polimorfico.
+ Valores aceitos incluem <literal>null</literal> e
<literal>not null</literal>
+ </para>
+ </callout>
+ <callout arearefs="class4">
+ <para>
+ <literal>mutable</literal> (opcional - valor
default <literal>true</literal>):
+ Especifica que instancias da classe são (ou não) mutáveis
+ </para>
+ </callout>
+ <callout arearefs="class5">
+ <para>
+ <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema especificado
+ pelo elemento root
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="class6">
+ <para>
+ <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo especificado
+ pelo elemento root
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="class7">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica
um interface para ser
+ utilizada pelos proxies de inicialização tardia. Você pode
especificar o
+ nome da própria classe.
+ </para>
+ </callout>
+ <callout arearefs="class8">
+ <para>
+ <literal>dynamic-update</literal> (opcional,
valor default <literal>false</literal>):
+ Especifica que o SQL de <literal>UPDATE</literal>
deve ser gerado em tempo de
+ execução e conter apenas aquelas colunas cujos valores foram
alterados.
+ </para>
+ </callout>
+ <callout arearefs="class9">
+ <para>
+ <literal>dynamic-insert</literal> (opcional,
valor default <literal>false</literal>):
+ Especifica que o SQL de
<literal>INSERT</literal> deve ser gerado em tempo de
+ execução e conter apenas aquelas colunas cujos valores não
estão nulos.
+ </para>
+ </callout>
+ <callout arearefs="class10">
+ <para>
+ <literal>select-before-update</literal>
(opcional, valor default <literal>false</literal>):
+ Especifica que o Hibernate
<emphasis>never</emphasis> deve executar um SQL de
+ <literal>UPDATE</literal> a não ser que com
certeza um objeto está atualmente modificado.
+ Em certos casos (atualmente, apenas quando um objeto
transiente foi associado com uma nova
+ sessão utilizando <literal>update()</literal>),
isto significa que o Hibernate ira executar
+ uma instrução SQL de <literal>SELECT</literal>
adicional para determinar se um
+ <literal>UPDATE</literal> é necessário nesse
momento.
+ </para>
+ </callout>
+ <callout arearefs="class11">
+ <para>
+ <literal>polymorphism</literal> (opcional,
default para <literal>implicit</literal>):
+ Determina se deve ser utilizado a query polimorfica implicita
ou explicitamente.
+ </para>
+ </callout>
+ <callout arearefs="class12">
+ <para>
+ <literal>where</literal> (opicional) especifica
um comando SQL <literal>WHERE</literal>
+ arbitrário para ser usado quando da recuperação de objetos
desta classe.
+ </para>
+ </callout>
+ <callout arearefs="class13">
+ <para>
+ <literal>persister</literal> (opcional):
Espeicifca uma <literal>ClassPersister</literal>
+ customizada.
+ </para>
+ </callout>
+ <callout arearefs="class14">
+ <para>
+ <literal>batch-size</literal> (opcional, valor
default <literal>1</literal>) especifica um
+ "tamanho de lote" para a recuperação de instancias
desta classe pelo identificador.
+ </para>
+ </callout>
+ <callout arearefs="class15">
+ <para>
+ <literal>optimistic-lock</literal> (octional,
valor default <literal>version</literal>):
+ Determina a estratégia de bloqueio.
+ </para>
+ </callout>
+ <callout arearefs="class16">
+ <para>
+ <literal>lazy</literal> (opcional): A recuperação
tardia pode ser completamente
+ desabilitada, setando
<literal>lazy="false"</literal>.
+ </para>
+ </callout>
+ <callout arearefs="class17">
+ <para>
+ <literal>entity-name</literal> (opcional, default
para o nome da classe): O
+ Hibernate3 permite uma classe ser mapeada multiplas vezes,
(potencialmente,para
+ diferentes tabelas), e permite mapeamentos de entidades que
são representadas
+ por Maps ou XML no nível Java. Nestes casos, você deve
especificar um nome
+ arbitrário explicitamente para a entidade. Veja <xref
linkend="persistent-classes-dynamicmodels"/>
+ e <xref linkend="xml"/> para maiores
informações.
+ </para>
+ </callout>
+ <callout arearefs="class18">
+ <para>
+ <literal>check</literal> (opcional): Uma
expressão SQL utilizada para gerar uma
+ constraint de <emphasis>verificação</emphasis> de
múltiplas linhas para a geração
+ automática do esquema.
+ </para>
+ </callout>
+ <callout arearefs="class19">
+ <para>
+ <literal>rowid</literal> (opcional): O Hibernate
poder usar as assim chamadas
+ ROWIDs em bancos de dados que a suportam. Por exemplo, no
Oracle, o Hibernate
+ pode utilizar a coluna extra rowid para atualizações mais
rápidas se você
+ configurar esta opção para
<literal>rowid</literal>. Um ROWID é uma implementação
+ que representa de maneira detalhada a localização física de
uma determinada
+ tupla armazenado.
+ </para>
+ </callout>
+ <callout arearefs="class20">
+ <para>
+ <literal>subselect</literal> (optional): Maps an
immutable and read-only entity
+ to a database subselect. Useful if you want to have a view
instead of a base table,
+ but don't. See below for more information.
+ <literal>subselect</literal> (opcional): Mapeia
uma entidade imutavel e somente
+ de leitura para um subconjunto do banco de dados. Útil se
você quiser ter uma
+ view em vez de uma tabela. Veja abaixo para mais
informações.
+ </para>
+ </callout>
+ <callout arearefs="class21">
+ <para>
+ <literal>abstract</literal> (opcional): Utilizada
para marcar superclasses
+ abstratas em hierarquias
<literal><union-subclass></literal>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ É perfeitamente aceitável para uma classe persitente nomeada ser uma
interface. Você deverá
+ então declarar as classes implementadas desta interface utilizando o
elemento
+ <literal><subclass></literal>. Você pode
persistir qualquer classe de aninhada
+ <emphasis>estatica</emphasis>. Você deverá especificar o nome
da classe usando a forma
+ padrão, por exemplo: <literal>eg.Foo$Bar</literal>.
+ </para>
+
+ <para>
+ Classes imutáveis,
<literal>mutable="false"</literal>, não podem ser modificadas ou
excluídas
+ pela aplicação. Isso permite ao Hibernate fazer alguns aperfeiçoamentos
de performance.
+ </para>
+
+ <para>
+ O atributo opcional <literal>proxy</literal> habilita a
inicialização tardia das
+ instâncias persistentes da classe. O Hibernate irá retornar CGLIB proxies
como implementado
+ na interface nomeada. O objeto persistente atual será carregado quando
um método do proxy
+ for invocado. Veja "Proxies para Inicialização Lazy" abaixo.
+ </para>
+
+ <para>Polimorfismo <emphasis>implícito</emphasis> significa
que instâncias de uma classe
+ serão retornada por uma query que dá nome a qualquer superclasse ou
interface implementada,
+ ou a classe e as instancias de qualquer subclasse da classe será
retornada por umq query
+ que nomeia a classe por si. Polimorfismo
<emphasis>explícito</emphasis> significa que
+ instancias da classe serão retornadas apenas por queries que
explicitamente nomeiam a
+ classe e que queries que nomeiam as classes irão retornar apenas
instancias de subclasses
+ mapeadas dentro da declaração
<literal><class></literal> como uma
+ <literal><subclass></literal> ou
<literal><joined-subclass></literal>.
+ Para a maioria dos casos, o valor default
<literal>polymorphism="implicit"</literal>,
+ é apropriado. Polimorfismo explicito é útil quando duas classes distintas
estão mapeadas
+ para a mesma tabela (isso permite um classe "peso leve" que
contem um subconjunto
+ de colunas da tabela).
+ </para>
+
+ <para>
+ O atributo <literal>persister</literal> deixa você customizar
a estratégia de persistência
+ utilizada para a classe. Você pode, por exemplo, especificar sua prórpia
subclasse do
+ <literal>org.hibernate.persister.EntityPersister</literal> ou
você pode criar
+ uma implementação completamente nova da interface
+ <literal>org.hibernate.persister.ClassPersister</literal> que
implementa a persistência
+ através de, por exemplo, chamadas a stored procedeures, serialização de
arquivos flat ou
+ LDAP. Veja
<literal>org.hibernate.test.CustomPersister</literal> para um exemplo
+ simples (de "persistencia" para uma
<literal>Hashtable</literal>).
+ </para>
+
+ <para>
+ Observe que as configurações
<literal>dynamic-update</literal> e
+ <literal>dynamic-insert</literal> não sao herdadas pelas
subclasses e assim podem tambem
+ ser especificadas em elementos
<literal><subclass></literal> or
+ <literal><joined-subclass></literal>. Estas
configurações podem incrementar a
+ performance em alguns casos, mas pode realmente diminuir a performance em
outras.
+ Use-as de forma bastante criteriosa.
+ </para>
+
+ <para>
+ O uso de <literal>select-before-update</literal> geralmente
irá diminuir a performance. Ela é
+ muito útil para prevenir que uma trigger de atualização no banco de dados
seja ativada
+ desnecessariamente, se você reconectar um nó de uma instancia
desconectada em uma
+ <literal>Session</literal>.
+ </para>
+
+ <para>
+ Se você ativar <literal>dynamic-update</literal>, você terá
de escolher
+ a estratégia de bloqueio otimista:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>version</literal> verifica a versão e a hora
das colunas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>all</literal> cverifica todas as colunas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>dirty</literal> verifica as colunas
modificadas, permitindo
+ alguns updates concorrentes
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>none</literal> não utiliza o bloqueio
otimista
+ </para>
+ </listitem>
+ </itemizedlist>
+ <para>
+ Nós <emphasis>recomendamos</emphasis> com muita enfase que
você utilize a
+ versão e a hora das colunas para o bloqueio otimista com o Hibernate.
+ Esta é a melhor estratégia com respeito a performance e é a única
estratégia
+ que trata corretamente as modificações efetuadas em instancias
desconectadas
+ (por exemplo, quando <literal>Session.merge()</literal> é
utilizado).
+
+ </para>
+
+ <para>
+ Não ha diferença entre uma view e uma tabela para o mapeamento do
Hibernate, e como
+ esperado isto é transparente no nível do banco de dados (observe que
alguns bancos de
+ dados não suportam views apropriadamente, especialmente com updates).
Algumas vezes,
+ você quer utilizar uma view, ma snão pode cria-la no banco de dados (por
exemplo,
+ com um esquema legado). Neste caso, você pode mapear uma entidade
imutável e de
+ somente leitura, para uma dada expressão SQL, que representa um
subselect:
+ </para>
+
+ <programlisting><![CDATA[<class name="Summary">
+ <subselect>
+ select item.name, max(bid.amount), count(*)
+ from item
+ join bid on bid.item_id = item.id
+ group by item.name
+ </subselect>
+ <synchronize table="item"/>
+ <synchronize table="bid"/>
+ <id name="name"/>
+ ...
+</class>]]></programlisting>
+
+ <para>
+ Declare as tabelas para sincronizar com esta entidade, garantindo que o
auto-flush
+ ocorra corretamente, e que as queries para esta entidade derivada não
retornem dados
+ desatualizados. O
<literal><subselect></literal> está disponível tanto como um
+ atributo como um elemento mapeado nested.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-id" revision="4">
+ <title>id</title>
+
+ <para>
+ Classes mapeadas <emphasis>precisam</emphasis> declarar a
coluna de chave primaria da
+ tabela do banco de dados. Muitas classes irão tambem ter uma propriedade
ao estilo
+ Java-Beans declarando o identificador unico de uma instancia. O elemento
+ <literal><id></literal> define o mapeamento
desta propriedade para a chave primária.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="id1" coords="2 70"/>
+ <area id="id2" coords="3 70" />
+ <area id="id3" coords="4 70"/>
+ <area id="id4" coords="5 70" />
+ <area id="id5" coords="6 70" />
+ </areaspec>
+ <programlisting><![CDATA[<id
+ name="propertyName"
+ type="typename"
+ column="column_name"
+ unsaved-value="null|any|none|undefined|id_value"
+ access="field|property|ClassName">
+ node="element-name|@attribute-name|element/(a)attribute|."
+
+ <generator class="generatorClass"/>
+</id>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="id1">
+ <para>
+ <literal>name</literal> (opcional): O nome do
identificador.
+ </para>
+ </callout>
+ <callout arearefs="id2">
+ <para>
+ <literal>type</literal> (opcional): Um nome que
indica o tipo no Hibernate.
+ </para>
+ </callout>
+ <callout arearefs="id3">
+ <para>
+ <literal>column</literal> (opcional – default
para o a propridade name): O
+ nome coluna chave primaria.
+ </para>
+ </callout>
+ <callout arearefs="id4">
+ <para>
+ <literal>unsaved-value</literal> (opcional -
default para um valor "sensível"):
+ Uma propriedade de identificação que indica que a instancia
foi novamente
+ instanciada (unsaved), diferenciando de instancias
desconectadas que foram
+ salvas ou carregadas em uma sessão anterior.
+ </para>
+ </callout>
+ <callout arearefs="id5">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
+ estratégia que o Hiberante deve utilizar para acessar o valor
da propriedade
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Se o atributo <literal>name</literal> não for declarado,
assume-se que a classe não tem
+ a propriedade de identificação.
+ </para>
+
+ <para>
+ O atributo <literal>unsaved-value</literal> não é mais
necessário no Hibernate 3.
+ </para>
+
+ <para>
+ Há declaração alternativa
<literal><composite-id></literal> permite o acesso a
+ dados legados com chaves compostas. Nós desencorajamos fortemente o seu
uso por
+ qualquer pessoa.
+ </para>
+
+ <sect3 id="mapping-declaration-id-generator"
revision="2">
+ <title>Generator</title>
+
+ <para>
+ O elemento filho opcional
<literal><generator></literal> nomeia uma classe Java
+ usada para gerar identificadores unicos para instancias de uma classe
persistente.
+ Se algum parâmetro é requerido para configurar ou inicializar a
instancia geradora,
+ eles são passados utilizando o elemento
<literal><param></literal>.
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="org.hibernate.id.TableHiLoGenerator">
+ <param name="table">uid_table</param>
+ <param name="column">next_hi_value_column</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ Todos os generators implementam a interface
<literal>org.hibernate.id.IdentifierGenerator</literal>.
+ Esta é uma interface bem simples; algumas aplicações podem prover sua
própria implementação
+ esepecializada. Entretanto, o Hibernate disponibiliza um conjunto de
implementações internamente.
+ Há nomes de atalhos para estes generators próprios:
+ <variablelist>
+ <varlistentry>
+
<term><literal>increment</literal></term>
+ <listitem>
+ <para>
+ gera identificadores dos tipos
<literal>long</literal>, <literal>short</literal> ou
+ <literal>int</literal> que são unicos apenas
quando nenhum outro processo está
+ inserindo dados na mesma tabela. <emphasis>Não
utilize em ambientes
+ de cluster.</emphasis>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>identity</literal></term>
+ <listitem>
+ <para>
+ suporta colunas de identidade em DB2, MySQL, MS SQL
Server, Sybase e
+ HypersonicSQL. O identificador retornado é do tipo
<literal>long</literal>,
+ <literal>short</literal> ou
<literal>int</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>sequence</literal></term>
+ <listitem>
+ <para>
+ utiliza uma sequence em DB2, PostgreSQL, Oracle, SAP DB,
McKoi ou um
+ generator no Interbase. O identificador de retorno é do
tipo <literal>
+ long</literal>,
<literal>short</literal> ou <literal>int</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>hilo</literal></term>
+ <listitem>
+ <para
id="mapping-declaration-id-hilodescription" revision="1">
+ utiliza um algoritmo hi/lo para gerar de forma eficiente
identificadores do tipo
+ <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
+ a partir de uma tabela e coluna fornecida (por default
+ <literal>hibernate_unique_key</literal> e
<literal>next_hi</literal>)
+ como fonte para os valores hi. O algoritmo hi/lo gera
identificadores que são
+ únicos apenas para um banco de dados particular.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>seqhilo</literal></term>
+ <listitem>
+ <para>
+ utiliza um algoritmo hi/lo para gerar de forma eficinete
identificadores do tipo
+ <literal>long</literal>,
<literal>short</literal> ou <literal>int</literal>,
+ a partir de uma sequence de banco de dados fornecida.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>uuid</literal></term>
+ <listitem>
+ <para>
+ utiliza um algortimo UUID de 128-bits para gerar
identificadores do
+ tipo string, unicos em uma rede(o endereço IP é
utilizado). O UUID é
+ codificado como um string de digitos hexadecimais de
tamanho 32.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>guid</literal></term>
+ <listitem>
+ <para>
+ utiliza um string GUID gerado pelo banco de dados no MS
SQL Server
+ e MySQL.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>native</literal></term>
+ <listitem>
+ <para>
+ seleciona entre <literal>identity</literal>,
<literal>sequence</literal>
+ ou <literal>hilo</literal> dependendo das
capacidades do banco de dados
+ utilizado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>assigned</literal></term>
+ <listitem>
+ <para>
+ deixa a aplicação definir um identificador para o objeto
antes que o
+ <literal>save()</literal> seja chamado. Esta
é a estratégia default
+ se nenhum elemento
<literal><generator></literal> é especificado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>select</literal></term>
+ <listitem>
+ <para>
+ retorna a chave primaria recuperada por uma trigger do
banco de
+ dados, selecionado uma linha pela chave única e
recuperando o valor
+ da chave primária.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>foreign</literal></term>
+ <listitem>
+ <para>
+ utiliza o identificador de um outro objeto associado.
Normalmente utilizado
+ em conjunto com uma associaçõa de chave primária do tipo
+
<literal><one-to-one></literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>sequence-identity</literal></term>
+ <listitem>
+ <para>
+ a specialized sequence generation strategy which utilizes
a
+ database sequence for the actual value generation, but
combines
+ this with JDBC3 getGeneratedKeys to actually return the
generated
+ identifier value as part of the insert statement
execution. This
+ strategy is only known to be supported on Oracle 10g
drivers
+ targetted for JDK 1.4. Note comments on these insert
statements
+ are disabled due to a bug in the Oracle drivers.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-hilo"
revision="1">
+ <title>Algoritmo Hi/lo</title>
+ <para>
+ Os geradores <literal>hilo</literal> e
<literal>seqhilo</literal> fornecem duas
+ implementações alternativas do algoritmo hi/lo, uma solução
preferencial para a geração
+ de identificadores. A primeira implementação requer uma tabela
especial do banco de
+ dados para manter o proximo valor "hi" disponível. A
segunda utiliza uma seqüência
+ do estilo Oracle (quando suportado).
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="hilo">
+ <param name="table">hi_value</param>
+ <param name="column">next_value</param>
+ <param name="max_lo">100</param>
+ </generator>
+</id>]]></programlisting>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="cat_id">
+ <generator class="seqhilo">
+ <param name="sequence">hi_value</param>
+ <param name="max_lo">100</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ Infelizemente, voce não pode utilizar
<literal>hilo</literal> quando estiver
+ fornecendo sia propria <literal>Connection</literal>
para o Hibernate. Quando o
+ Hibernate está usando um datasource do servidor de aplicações para
obter conexões
+ suportadas com JTA, você precisa configurar adequadamente o
+
<literal>hibernate.transaction.manager_lookup_class</literal>.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-uuid">
+ <title>UUID algorithm</title>
+ <para>
+ O UUID contem: o endereço IP, hora de inicio da JVM (com precisão de
um quarto
+ de segundo), a hora do sistema e um valor contador (unico dentro da
JVM).
+ Não é possivel obter o endereço MAC ou um endereço de memória do
código Java,
+ assim este é o melhor que pode ser feito sem utilizar JNI.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-sequences">
+ <title>Colunas de identidade e sequencias</title>
+ <para>
+ Para bancos de dados que suportam colunas de identidade (DB2, MySQL,
Sybase,
+ MS SQL), você pode utilizar uma geração de chave
<literal>identity</literal>.
+ Para bancos de dados que suportam sequencias (DB2, Oracle,
PostgreSQL, Interbase,
+ McKoi, SAP DB) voce pode utilizar a geração de chaves no estilo
+ <literal>sequence</literal>. As duas estratégias requerem
duas consultas SQL
+ para inserir um novo objeto.
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
+ <generator class="sequence">
+ <param name="sequence">person_id_sequence</param>
+ </generator>
+</id>]]></programlisting>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id" unsaved-value="0">
+ <generator class="identity"/>
+</id>]]></programlisting>
+
+ <para>
+ Para desenvolvimento multi-plataforma, a estratégia
<literal>native</literal>
+ irá escolher entre as estratégias i
<literal>identity</literal>,
+ <literal>sequence</literal> e
<literal>hilo</literal>, dependendo das
+ capacidades do banco de dados utilizado.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-assigned">
+ <title>Identificadores especificados</title>
+ <para>
+ Se você quer que a aplicação especifique os identificadores
+ (em vez do Hibernate gerá-los) você deve utilizar o gerador
+ <literal>assigned</literal>. Este gerador especial irá
utilizar o valor
+ do identificador especificado para a propriedade de identificação do
objeto.
+ Este gerador é usado quando a chave primaria é a chave natural em vez
de uma
+ surrogate key. Este é o comportamento padrão se você não especificar
+ um elemento
<literal><generator></literal>.
+ </para>
+
+ <para>
+ Escolher o gerador <literal>assigned</literal> faz com
que o Hibernate
+ utilize
<literal>unsaved-value="undefined"</literal>, forçando o Hibernate
+ ir até o banco de dados para determinar se uma instância está
transiente ou
+ desasociada, a menos que haja uma versão ou uma propriedade
timestamp,
+ ou você pode definir
<literal>Interceptor.isUnsaved()</literal>.
+ </para>
+ </sect3>
+
+ <sect3 id="mapping-declaration-id-select">
+ <title>Chaves primárias geradas por triggers</title>
+ <para>
+ Apenas para sistemas legados (o Hibernate nao gera DDL com
triggers).
+ </para>
+
+ <programlisting><![CDATA[<id name="id"
type="long" column="person_id">
+ <generator class="select">
+ <param name="key">socialSecurityNumber</param>
+ </generator>
+</id>]]></programlisting>
+
+ <para>
+ No exemplo acima, há uma única propriedade com valor nomeada
+ <literal>socialSecurityNumber</literal> definida pela
classe,
+ uma chave natural, e uma surrogate key nomeada
+ <literal>person_id</literal> cujo valor é gerado pro uma
trigger.
+ </para>
+
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-compositeid"
revision="3">
+ <title>composite-id</title>
+
+ <programlisting><![CDATA[<composite-id
+ name="propertyName"
+ class="ClassName"
+ mapped="true|false"
+ access="field|property|ClassName">
+ node="element-name|."
+
+ <key-property name="propertyName" type="typename"
column="column_name"/>
+ <key-many-to-one name="propertyName class="ClassName"
column="column_name"/>
+ ......
+</composite-id>]]></programlisting>
+
+ <para>
+ Para tabelas com uma chave composta, você pode mapear múltiplas
propriedades
+ da classe como propriedades de identificação. O elemento
+ <literal><composite-id></literal> aceita o
mapeamento da propriedade
+ <literal><key-property></literal> e mapeamentos
+ <literal><key-many-to-one></literal>como
elements filhos.
+ </para>
+
+ <programlisting><![CDATA[<composite-id>
+ <key-property name="medicareNumber"/>
+ <key-property name="dependent"/>
+</composite-id>]]></programlisting>
+
+ <para>
+ Sua classe persistente <emphasis>precisa</emphasis> sobre
escrever
+ <literal>equals()</literal> e
<literal>hashCode()</literal> para implementar
+ identificadores compostos igualmente. E precisa também implementar
+ <literal>Serializable</literal>.
+ </para>
+
+ <para>
+ Infelizmente, esta solução para um identificador composto significa que
um objeto
+ persistente é seu próprio identificador. Não há outro "handle"
que o próprio objeto.
+ Você mesmo precisa instanciar uma instância de outra classe persistente e
preencher
+ suas propriedades de identificação antes que você possa dar um
<literal>load()</literal>
+ para o estado persistente associado com uma chave composta. Nos chamamos
esta
+ solução de identificador composto
<emphasis>embedded</emphasis> e não aconselhamos
+ para aplicações sérias.
+ </para>
+
+ <para>
+ Uma segunda solução é o que podemos chamar de identificador composto
+ <emphasis>mapped</emphasis> quando a propriedades de
identificação nomeadas dentro do
+ elemento <literal><composite-id></literal>
estão duplicadas tando na classe
+ persistente como em uma classe de identificação separada.
+ </para>
+
+ <programlisting><![CDATA[<composite-id
class="MedicareId" mapped="true">
+ <key-property name="medicareNumber"/>
+ <key-property name="dependent"/>
+</composite-id>]]></programlisting>
+
+ <para>
+ No exemplo, ambas as classes de identificação compostas,
<literal>MedicareId</literal>,
+ e a própria classe entidade tem propriedades nomeadas
<literal>medicareNumber</literal>
+ e <literal>dependent</literal>. A classe identificadora
precisa sobrepor
+ <literal>equals()</literal> e
<literal>hashCode()</literal> e implementar
+ <literal>Serializable</literal>. A desvantagem desta solução
é obvia –
+ duplicação de código.
+ </para>
+
+ <para>
+ Os seguintes atributos ão utilizados para especificar o mapeamento de
+ um identificador composto:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>mapped</literal> mapped (opcional, valor
default <literal>false
+ </literal>): indica que um identificar composto mapeado é
usado, e que as
+ propriedades de mapeamento contidas refere-se tanto a classe
entidade e
+ a classe de identificação composta.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>class</literal> (opcional, mas requerida
para um identificar composto
+ mapeado): A classe usada como um identificador composto.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Nós iremos descrever uma terceira e as vezes mais conveniente solução,
onde o
+ identificador composto é implementado como uma classe componente na
+ <xref linkend="components-compositeid"/>. Os atributos
descritos abaixo aplicam-se
+ apenas para esta solução:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>name</literal> (opcional, requerida para
esta solução): Uma
+ propriedade do tipo componente que armazena o identificador
composto
+ (veja capítulo 9)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>access</literal> (opcional - valor default
<literal>property</literal>):
+ A estartégia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>class</literal> (opcional - valor default
para o tipo de propriedade
+ determiando por reflexão) : A classe componente utilizada como um
identificador
+ composto (veja a próxima sessão).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Esta terceira solução, um <emphasis>componente de
identificação</emphasis>, é o que nós
+ recomendamos para a maioria das aplicações.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-discriminator"
revision="3">
+ <title>discriminator</title>
+
+ <para>
+ O elemento <literal><discriminator></literal>
é necessário para persistência
+ polimórfica utilizando a estratégia de mapeamento
table-per-class-hierarchy e declara
+ uma coluna discriminadora da tabela. A coluna discriminadora contem
valores de marcação
+ que dizem a camada de persistência qual subclasse instanciar para uma
linha particular.
+ Um restrito conjunto de tipos que podem ser utilizados:
<literal>string</literal>,
+ <literal>character</literal>,
<literal>integer</literal>, <literal>byte</literal>,
+ <literal>short</literal>,
<literal>boolean</literal>,
+ <literal>yes_no</literal>,
<literal>true_false</literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="discriminator1" coords="2 60"/>
+ <area id="discriminator2" coords="3 60" />
+ <area id="discriminator3" coords="4 60" />
+ <area id="discriminator4" coords="5 60" />
+ <area id="discriminator5" coords="6 60" />
+ </areaspec>
+ <programlisting><![CDATA[<discriminator
+ column="discriminator_column"
+ type="discriminator_type"
+ force="true|false"
+ insert="true|false"
+ formula="arbitrary sql expression"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="discriminator1">
+ <para>
+ <literal>column</literal> (opcional - valor
default <literal>class</literal>)
+ o nome da coluna discriminadora
+ </para>
+ </callout>
+ <callout arearefs="discriminator2">
+ <para>
+ <literal>type</literal> (opcional - valor default
<literal>string</literal>)
+ o nome que indica o tipo Hibernate
+ </para>
+ </callout>
+ <callout arearefs="discriminator3">
+ <para>
+ <literal>force</literal> (opcional - valor
default <literal>false</literal>)
+ "força" o Hibernate a especificar valores
discriminadores permitidos mesmo
+ quando recuperando todas as instancias da classe root.
+ </para>
+ </callout>
+ <callout arearefs="discriminator4">
+ <para>
+ <literal>insert</literal> (opcional - valor
default para <literal>true</literal>)
+ sete isto para <literal>false</literal> se sua
coluna discriminadora é também
+ parte do identificador composto mapeado. (Diz ao Hibernate
para não incluir a
+ coluna em comandos SQL
<literal>INSERT</literal>s).
+ </para>
+ </callout>
+ <callout arearefs="discriminator5">
+ <para>
+ <literal>formula</literal> (opcional) uma
expressão SQL arbitraria que é e
+ xecutada quando um tipo tem que ser avaliado. Permite
discriminação baseada
+ em conteúdo.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Valores atuais de uma coluna discriminada são especificados pelo atributo
+ <literal>discriminator-value</literal> da
<literal><class></literal>
+ e elementos da <literal><subclass></literal>.
+ </para>
+
+ <para>
+ O atributo <literal>force</literal> é util (apenas) em
tabelas contendo linhas com
+ valores discriminadores "extras" que não estão mapeados para
uma classe persistente.
+ Este não é geralmente o caso.
+ </para>
+
+ <para>
+ Usando o atributo <literal>formula</literal> voce pode
declarar uma expressão SQL
+ arbitrária que sera utilizada para avaliar o tipo de uma linha :
+ </para>
+
+ <programlisting><![CDATA[<discriminator
+ formula="case when CLASS_TYPE in ('a', 'b', 'c') then 0
else 1 end"
+ type="integer"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-version" revision="4">
+ <title>version (optional)</title>
+
+ <para>
+ O elemento <literal><version></literal> é
opcional e indica que a tabela
+ possui dados versionados. Isto é particularmente útil se você planeja
utilizar
+ <emphasis>transações longas</emphasis> (veja abaixo):
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="version1" coords="2 70"/>
+ <area id="version2" coords="3 70"/>
+ <area id="version3" coords="4 70"/>
+ <area id="version4" coords="5 70"/>
+ <area id="version5" coords="6 70"/>
+ <area id="version6" coords="7 70"/>
+ <area id="version7" coords="8 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<version
+ column="version_column"
+ name="propertyName"
+ type="typename"
+ access="field|property|ClassName"
+ unsaved-value="null|negative|undefined"
+ generated="never|always"
+ insert="true|false"
+ node="element-name|@attribute-name|element/(a)attribute|."
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="version1">
+ <para>
+ <literal>column</literal> (opcional - default a a
propriedade name): O nome da
+ coluna mantendo o numero da versão
+ </para>
+ </callout>
+ <callout arearefs="version2">
+ <para>
+ <literal>name</literal>: O nome da propriedade da
classe persistente.
+ </para>
+ </callout>
+ <callout arearefs="version3">
+ <para>
+ <literal>type</literal> (opcional - valor default
para <literal>integer</literal>):
+ O tipo do numero da versão
+ </para>
+ </callout>
+ <callout arearefs="version4">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>):
+ A estratégia Hibernate que deve ser usada para acessar o
valor da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="version5">
+ <para>
+ <literal>unsaved-value</literal> (opcional –
valor default para <literal>undefined
+ </literal>): Um valor para a propriedade versão que
indica que uma instancia é
+ uma nova instanciada (unsaved), distinguindo de instancias
desconectadas que foram
+ salvas ou carregadas em sessões anteriores.
((<literal>undefined</literal> especifica
+ que o valor da propriedade de identificação deve ser
utilizado).
+ </para>
+ </callout>
+ <callout arearefs="version6">
+ <para>
+ <literal>generated</literal> (optional - defaults
to <literal>never</literal>):
+ Specifies that this version property value is actually
generated by the database.
+ See the discussion of <xref
linkend="mapping-generated">generated properties</xref>.
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que valor para a propriedade versão é na verdade
gerado pelo banco de
+ dados. Veja a discussão da Seção
+ <xref linkend="mapping-generated">generated
properties</xref>.
+ </para>
+ </callout>
+ <callout arearefs="version7">
+ <para>
+ <literal>insert</literal> (opcional - valor
default para <literal>true</literal>):
+ Especifica se a coluna de versão deve ser incluída no comando
SQL de insert.
+ Pode ser configurado como
<literal>false</literal> se a coluna do banco de dados
+ está definida com um valor default de
<literal>0</literal>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Números de versão podem ser dos tipos Hibernate
<literal>long</literal>,
+ <literal>integer</literal>,
<literal>short</literal>, <literal>timestamp</literal> ou
+ <literal>calendar</literal>.
+ </para>
+
+ <para>
+ A versão de uma propriedade timestamp nunca deve ser nula para uma
instancia
+ desconectada, assim o Hibernate irá identificar qualquer instância com
uma versão
+ nula ou timestamp como transiente, não importando qual estratégia para
foi
+ especificada para <literal>unsaved-value</literal>.
<emphasis>Declarando uma versão
+ nula ou a propriedade timestamp é um caminho fácil para tratar problemas
com
+ reconexões transitivas no Hibernate, especialmente úteis para pessoas
utilizando
+ identificadores assinaldados ou chaves compostas!</emphasis>
+ </para>
+ </sect2>
+
+ <sect2 id="mapping-declaration-timestamp" revision="4"
>
+ <title>timestamp (optional)</title>
+
+ <para>
+ O elemento opcional
<literal><timestamp></literal> indica que uma tabela contém
+ dados timestamped. Isso tem por objetivo dar uma alternativa para
versionamento. Timestamps
+ são por natureza uma implementação menos segura do locking otimista.
Entretanto, algumas
+ vezes a aplicação pode usar timestamps em outros caminhos.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="timestamp1" coords="2 70"/>
+ <area id="timestamp2" coords="3 70" />
+ <area id="timestamp3" coords="4 70" />
+ <area id="timestamp4" coords="5 70" />
+ <area id="timestamp5" coords="6 70" />
+ <area id="timestamp6" coords="7 70" />
+ </areaspec>
+ <programlisting><![CDATA[<timestamp
+ column="timestamp_column"
+ name="propertyName"
+ access="field|property|ClassName"
+ unsaved-value="null|undefined"
+ source="vm|db"
+ generated="never|always"
+ node="element-name|@attribute-name|element/(a)attribute|."
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="timestamp1">
+ <para>
+ <literal>column</literal> (opcional - valor
default para a propriedade name):
+ O nome da coluna que mantem o timestamp.
+ </para>
+ </callout>
+ <callout arearefs="timestamp2">
+ <para>
+ <literal>name</literal>: O nome da propriedade no
estilo JavaBeans do
+ tipo <literal>Date</literal> ou
<literal>Timestamp</literal> da classe
+ persistente Java.
+ </para>
+ </callout>
+ <callout arearefs="timestamp3">
+ <para>
+ <literal>access</literal> (opcional - valor
default para <literal>property</literal>):
+ A estretagia Hibernate que deve ser utilizada para acessar o
valor da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="timestamp4">
+ <para>
+ <literal>unsaved-value</literal> (opcional -
valor default <literal>null</literal>):
+ Uma propriedade para a versão de que indica que uma instância
é uma nova instanciada
+ (unsaved), distinguindo-a de instancias desconectadas que
foram salvas ou carregadas
+ em sessões previas. (<literal>undefined</literal>
especifica que um valor de
+ propriedade de identificação deve ser utilizado)
+ </para>
+ </callout>
+ <callout arearefs="timestamp5">
+ <para>
+ <literal>source</literal> (opcional - valor
default para <literal>vm</literal>):
+ De onde o Hibernate deve recuperar o valor timestamp? Do
banco de dados ou da JVM
+ corrente? Timestamps baseados em banco de dados levam a um
overhead porque o
+ Hibernate precisa acessar o banco de dados para determinar o
"próximo valor", mas é
+ mais seguro para uso em ambientes de "cluster".
Observe também, que nem todos
+ <literal>Dialect</literal>s suportam a
recuperação do timestamp corrente do banco
+ de dados, enquando outros podem não ser seguros para
utilização em bloqueios
+ pela falta de precisão (Oracle 8 por exemplo)
+ </para>
+ </callout>
+ <callout arearefs="timestamp6">
+ <para>
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que o valor da propriedade timestamp é gerado pelo
banco de dados.
+ Veja a discussão <xref
linkend="mapping-generated">generated properties</xref>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Observe que <literal><timestamp></literal> é
equivalente a
+ <literal><version
type="timestamp"></literal>. E
+ <literal><timestamp
source="db"></literal> é equivalente a
+ <literal><version
type="dbtimestamp"></literal>.
+ </para>
+ </sect2>
+
+
+ <sect2 id="mapping-declaration-property" revision="4">
+ <title>property</title>
+
+ <para>
+ O elemento <literal><property></literal>
declara uma propriedade
+ persistente de uma classe, no estilo JavaBean.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="property1" coords="2 70"/>
+ <area id="property2" coords="3 70"/>
+ <area id="property3" coords="4 70"/>
+ <areaset id="property4-5" coords="">
+ <area id="property4" coords='5 70'/>
+ <area id="property5" coords='6 70'/>
+ </areaset>
+ <area id="property6" coords="7 70"/>
+ <area id="property7" coords="8 70"/>
+ <area id="property8" coords="9 70"/>
+ <area id="property9" coords="10 70"/>
+ <area id="property10" coords="11 70"/>
+ <area id="property11" coords="12 70"/>
+ <area id="property12" coords="13 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<property
+ name="propertyName"
+ column="column_name"
+ type="typename"
+ update="true|false"
+ insert="true|false"
+ formula="arbitrary SQL expression"
+ access="field|property|ClassName"
+ lazy="true|false"
+ unique="true|false"
+ not-null="true|false"
+ optimistic-lock="true|false"
+ generated="never|insert|always"
+ node="element-name|@attribute-name|element/(a)attribute|."
+ index="index_name"
+ unique_key="unique_key_id"
+ length="L"
+ precision="P"
+ scale="S"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="property1">
+ <para>
+ <literal>name</literal>: o nome da propriedade,
iniciando com letra minúscula.
+ </para>
+ </callout>
+ <callout arearefs="property2">
+ <para>
+ <literal>column</literal> (opcional - default
para a propriedade name): o nome
+ da coluna mapeada do banco de dados, Isto pode também ser
especificado pelo(s)
+ elemento(s)
<literal><column></literal> aninhados.
+
+ </para>
+ </callout>
+ <callout arearefs="property3">
+ <para>
+ <literal>type</literal> (opcional): um nome que
indica o tipo Hibernate.
+ </para>
+ </callout>
+ <callout arearefs="property4-5">
+ <para>
+ <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
+ especifica que as colunas mapeadas devem ser incluidas nas
instruções SQL de
+ <literal>UPDATE</literal> e/ou
<literal>INSERT</literal> . Setar ambas para to
+ <literal>false</literal> permite uma propridade
"derivada" pura cujo valor é
+ inicializado de outra propriedade que mapeie a mesma
coluna(s) ou por uma trigger
+ ou outra aplicação.
+ </para>
+ </callout>
+ <callout arearefs="property6">
+ <para>
+ <literal>formula</literal> (opcional): uma
expressão SQL que definie o valor para
+ uma propriedade <emphasis>calculada</emphasis>.
Propriedades calculadas nao tem
+ uma coluna de mapeamento para elas.
+ </para>
+ </callout>
+ <callout arearefs="property7">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o Hibernate deve utilizar para acessar o
valor da propriedade
+ </para>
+ </callout>
+ <callout arearefs="property8">
+ <para>
+ <literal>lazy</literal> (opcional - valor default
para <literal>false</literal>):
+ Especifica que esta propriedade deve ser trazida de forma
"lazy" quando a
+ instancia da variável é acessada pela primeira vez (requer
instrumentação
+ bytecode em tempo de criação).
+ </para>
+ </callout>
+ <callout arearefs="property9">
+ <para>
+ <literal>unique</literal> (opcional): Habilita a
geração de DDL de uma
+ unica constraint para as colunas. Assim, permite que isto
seja o
+ alvo de uma <literal>property-ref</literal>.
+ </para>
+ </callout>
+ <callout arearefs="property10">
+ <para>
+ <literal>not-null</literal> (opcional): Habilita
a geração de DDL de uma
+ constraint de nulidade para as colunas.
+ </para>
+ </callout>
+ <callout arearefs="property11">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
+ Especifica se mudanças para esta propriedade requerem ou não
bloqueio otimista.
+ Em outras palavras, determina se um incremento de versão deve
ocorrer quando
+ esta propriedade está suja.
+ </para>
+ </callout>
+ <callout arearefs="property12">
+ <para>
+ <literal>generated</literal> (opcional - valor
default <literal>never</literal>):
+ Especifica que o valor da propriedade é na verdade gerado
pelo banco de dados.
+ Veja a discussão da seção
+ <xref linkend="mapping-generated">generated
properties</xref>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ <emphasis>typename</emphasis> pode ser:
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ The name of a Hibernate basic type (eg. <literal>integer,
string, character,
+ date, timestamp, float, binary, serializable, object,
blob</literal>).
+ O nome do tipo basico do Hibernate (ex., <literal>integer,
string, character,
+ date, timestamp, float, binary, serializable, object,
blob</literal>).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe Java com um tipo básico default (ex.
<literal>int, float,
+ char, java.lang.String, java.util.Date, java.lang.Integer,
java.sql.Clob</literal>).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe Java serializable
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O nome da classe de um tipo customizado (ex.
<literal>com.illflow.type.MyCustomType</literal>).
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ Se você não especificar um tipo, o Hibernate ira utilizar reflexão sobre
a
+ propriedade nomeada para ter uma idéia do tipo Hibernate correto. O
Hibernate ira
+ tentar interpretar o nome da classe retornada, usando as regras 2, 3 e 4
nesta ordem.
+ Entretanto, isto não é sempre suficiente Em certos casos, você ainda irá
necessitar
+ do atributo <literal>type</literal>. (Por exemplo, para
distinguir entre
+ <literal>Hibernate.DATE</literal> ou
<literal>Hibernate.TIMESTAMP</literal>,
+ ou para espcificar uma tipo ciustomizado.)
+ </para>
+
+ <para>
+ O atributo <literal>access</literal> permite voce controlar
como o Hibernate irá
+ acessar a propriedade em tempo de execução. Por default, o Hibernate irá
chamar os
+ métodos get/set da propriedades. Se voce especificar
<literal>access="field"</literal>,
+ o Hibernate ira bipassar os metodos get/set, acessnado o campo
diretamente,
+ usando reflexão. Voc epode especificar sua própria estratégia para acesso
da
+ propriedade criando uma classe que implemente a interface
+ <literal>org.hibernate.property.PropertyAccessor</literal>.
+ </para>
+
+ <para>
+ Um recurso especialmente poderoso é o de propriedades derivadas. Estas
propriedades
+ são por definição read-only, e o valor da propriedade é calculado em
tempo de execução.
+ Você declara este calculo como uma expressão SQL, que traduz para
clausula
+ <literal>SELECT</literal> de uma subquery daquery SQL que
carrega a instancia:
+ </para>
+
+ <programlisting><![CDATA[
+<property name="totalPrice"
+ formula="( SELECT SUM (li.quantity*p.price) FROM LineItem li, Product p
+ WHERE li.productId = p.productId
+ AND li.customerId = customerId
+ AND li.orderNumber = orderNumber
)"/>]]></programlisting>
+
+ <para>
+ Observe que você pode referenciar as entidades da própria tabela,
+ através da não declaração de um alias para uma coluna particular (
+ <literal>customerId</literal> no exemplo dado). Observe
tambem que voce pode usar o
+ mapeamento de elemento aninhado
<literal><formula></literal>, se você não
+ gostar de usar o atributo.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-manytoone"
revision="5">
+ <title>many-to-one</title>
+
+ <para>
+ Uma associação ordinária para outra classe persistente é declarada usando
o
+ elemento <literal>many-to-one</literal>. O modelo relacional
é uma
+ associação many-to-one: a uma chave estrangeira de uma tabela
referenciando
+ a chave primaria da tabela destino.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="manytoone1" coords="2 70"/>
+ <area id="manytoone2" coords="3 70"/>
+ <area id="manytoone3" coords="4 70"/>
+ <area id="manytoone4" coords="5 70"/>
+ <area id="manytoone5" coords="6 70"/>
+ <areaset id="manytoone6-7" coords="">
+ <area id="manytoone6" coords='7 70'/>
+ <area id="manytoone7" coords='8 70'/>
+ </areaset>
+ <area id="manytoone8" coords="9 70"/>
+ <area id="manytoone9" coords="10 70"/>
+ <area id="manytoone10" coords="11 70"/>
+ <area id="manytoone11" coords="12 70"/>
+ <area id="manytoone12" coords="13 70"/>
+ <area id="manytoone13" coords="14 70"/>
+ <area id="manytoone14" coords="15 70"/>
+ <area id="manytoone15" coords="16 70"/>
+ <area id="manytoone16" coords="17 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<many-to-one
+ name="propertyName"
+ column="column_name"
+ class="ClassName"
+ cascade="cascade_style"
+ fetch="join|select"
+ update="true|false"
+ insert="true|false"
+ property-ref="propertyNameFromAssociatedClass"
+ access="field|property|ClassName"
+ unique="true|false"
+ not-null="true|false"
+ optimistic-lock="true|false"
+ lazy="proxy|no-proxy|false"
+ not-found="ignore|exception"
+ entity-name="EntityName"
+ formula="arbitrary SQL expression"
+ node="element-name|@attribute-name|element/(a)attribute|."
+ embed-xml="true|false"
+ index="index_name"
+ unique_key="unique_key_id"
+ foreign-key="foreign_key_name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="manytoone1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="manytoone2">
+ <para>
+ <literal>column</literal> (opcional): O nome da
coluna foreign key. Isto
+ pode também ser especificado através de elementos aninhados
+ <literal><column></literal>.
+ </para>
+ </callout>
+ <callout arearefs="manytoone3">
+ <para>
+ <literal>class</literal> (opcional – default para
o tipo de propriedade
+ determinado pela reflexão). O nome da classe associada.
+ </para>
+ </callout>
+ <callout arearefs="manytoone4">
+ <para>
+ <literal>cascade</literal> (opcional): Especifica
quais operações dever
+ ser em cascata do objeto pai para o objeto associado.
+ </para>
+ </callout>
+ <callout arearefs="manytoone5">
+ <para>
+ <literal>fetch</literal> (opcional - default para
<literal>select</literal>):
+ Escolhe entre recuperação outer-join ou recuperação
seqüencial.
+ </para>
+ </callout>
+ <callout arearefs="manytoone6-7">
+ <para>
+ <literal>update, insert</literal> (opcional -
valor default <literal>true</literal>):
+ especifica que as colunas mapeadas dever ser incluidas em
instruções SQL de
+ <literal>UPDATE</literal> e/ou
<literal>INSERT</literal>. Setando ambas para
+ <literal>false</literal> você permite uma
associação "derivada" pura cujos valores
+ são inicializados de algumas outras propriedades que mapeiam
a mesma coluna ou
+ por uma trigger ou outra aplicação.
+ </para>
+ </callout>
+ <callout arearefs="manytoone8">
+ <para>
+ <literal>property-ref</literal>: (opcional) O
nome da propriedade da classe associada
+ que faz a junção desta foreign key. Se não especificada, a
chave primaria da
+ classe associada será utilizada.
+ </para>
+ </callout>
+ <callout arearefs="manytoone9">
+ <para>
+ <literal>access</literal> (opcional - valor
default <literal>property</literal>): A
+ estrategia que o Hibernate deve utilizar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="manytoone10">
+ <para>
+ <literal>unique</literal> (opcional): Habilita a
geração DDL de uma constraint
+ unique para a coluna foreign-key. Alem disso, permite ser o
alvo de uma
+ <literal>property-ref</literal>. Isso torna a
associação multipla
+ efetivamente um para um.
+ </para>
+ </callout>
+ <callout arearefs="manytoone11">
+ <para>
+ <literal>not-null</literal> (opcional): Habilita
a geração DDL de uma constraint de
+ nulidade para as foreign keys.
+ </para>
+ </callout>
+ <callout arearefs="manytoone12">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default <literal>true</literal>):
+ Especifica se mudanças desta propriedade requerem ou não
travamento otimista.
+ Em outras palavras, determina se um incremento de versão deve
ocorrer quando
+ esta propriedade está suja.
+ </para>
+ </callout>
+ <callout arearefs="manytoone13">
+ <para>
+ <literal>lazy</literal>(opcional – valor default
<literal>proxy</literal>):
+ Por default, associações de ponto unico são envoltas em um
proxie.
+ <literal>lazy="no-proxy"</literal>
especifica que a propriedade deve ser
+ trazida de forma tardia quando a instancia da variável é
acessada pela
+ primeira vez (requer instrumentação bytecode em tempo de
criação)
+ <literal>lazy="false"</literal>
especifica que a associação será
+ sempre recuperada fortemente.
+ </para>
+ </callout>
+ <callout arearefs="manytoone14">
+ <para>
+ <literal>not-found</literal> (opcional - valor
default <literal>exception</literal>):
+ Especifica como as foreign keys que referenciam linhas
ausentes serão tratadas:
+ <literal>ignore</literal> irá tratar a linha
ausente como ama associaççao de null
+ </para>
+ </callout>
+ <callout arearefs="manytoone15">
+ <para>
+ <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
+ </para>
+ </callout>
+ </calloutlist>
+ <callout arearefs="manytoone16">
+ <para>
+ <literal>formula</literal> (optional): Uma
expressão SQL que define um valor
+ para um foreign key
<emphasis>computed</emphasis>.
+ </para>
+ </callout>
+ </programlistingco>
+
+ <para>
+ Setar o valor do atributo <literal>cascade</literal> para
qualquer valor
+ significativo diferente de <literal>none</literal> irá
propagar certas operações
+ ao objeto associado. Os valores significativos são os nomes das operações
básicas
+ do Hibernate, <literal>persist, merge, delete, save-update, evict,
replicate, lock,
+ refresh</literal>, assim como os valores especiais
<literal>delete-orphan</literal>
+ e <literal>all</literal> e combinações de nomes de operações
separadas por vírgula,
+ como por exemplo,
<literal>cascade="persist,merge,evict"</literal> ou
+ <literal>cascade="all,delete-orphan"</literal>.
Veja a seção
+ <xref linkend="objectstate-transitive"/> para uma
explicação completa. Note que
+ associações valoradas simples (associações muitos-pra-um, e um-pra-um)
não suportam
+ orphan delete.
+ </para>
+
+ <para>
+ Uma típica declaração <literal>muitos-pra-um</literal> se
parece com esta:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="product"
class="Product" column="PRODUCT_ID"/>]]></programlisting>
+
+ <para>
+ O atributo <literal>property-ref</literal> deve apenas ser
usado para mapear dados
+ legados onde uma chave estrangeira se referencia a uma chave exclusiva da
tabela
+ associada que não seja à chave primária. Este é um modelo relacional
desagradável.
+ Por exemplo, suponha que a classe <literal>Product</literal>
tenha um número
+ seqüencial exclusivo, que não é a chave primária. (O atributo
<literal>unique</literal>
+ controla a geração de DDL do Hibernate com a ferramenta SchemaExport.)
+ </para>
+
+ <programlisting><![CDATA[<property name="serialNumber"
unique="true" type="string"
column="SERIAL_NUMBER"/>]]></programlisting>
+
+ <para>
+ Então o mapeamento para <literal>OrderItem</literal> poderia
usar:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="product"
property-ref="serialNumber"
column="PRODUCT_SERIAL_NUMBER"/>]]></programlisting>
+
+ <para>
+ Porém, isto obviamente não é indicado, nunca.
+ </para>
+
+ <para>
+ Se a chave exclusiva referenciada engloba múltiplas propriedades da
entidade associada,
+ você deve mapear as propriedades referenciadas dentro de um elemento
chamado
+ <literal><properties></literal>
+
+ </para>
+
+ <para>
+ Se a chave exclusiva referenciada é a propriedade de um componente, você
pode especificar
+ um caminho para a propriedade.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="owner"
property-ref="identity.ssn"
column="OWNER_SSN"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-onetoone" revision="3">
+ <title>one-to-one (um-pra-um)</title>
+
+ <para>
+ Uma associação um-pra-um para outra classe persistente é declarada usando
+ um elemento <literal>one-to-one </literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="onetoone1" coords="2 70"/>
+ <area id="onetoone2" coords="3 70"/>
+ <area id="onetoone3" coords="4 70"/>
+ <area id="onetoone4" coords="5 70"/>
+ <area id="onetoone5" coords="6 70"/>
+ <area id="onetoone6" coords="7 70"/>
+ <area id="onetoone7" coords="8 70"/>
+ <area id="onetoone8" coords="9 70"/>
+ <area id="onetoone9" coords="10 70"/>
+ <area id="onetoone10" coords="11 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<one-to-one
+ name="propertyName"
+ class="ClassName"
+ cascade="cascade_style"
+ constrained="true|false"
+ fetch="join|select"
+ property-ref="propertyNameFromAssociatedClass"
+ access="field|property|ClassName"
+ formula="any SQL expression"
+ lazy="proxy|no-proxy|false"
+ entity-name="EntityName"
+ node="element-name|@attribute-name|element/(a)attribute|."
+ embed-xml="true|false"
+ foreign-key="foreign_key_name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="onetoone1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="onetoone2">
+ <para>
+ <literal>class</literal> (opcional – default para
o tipo da propriedade
+ definido via reflection): O nome da classe associada.
+ </para>
+ </callout>
+ <callout arearefs="onetoone3">
+ <para>
+ <literal>cascade</literal> (opcional): Especifica
qual operação deve
+ ser cascateada do objeto pai para o objeto associado.
+ </para>
+ </callout>
+ <callout arearefs="onetoone4">
+ <para>
+ <literal>constrained</literal> (opcional):
Especifica que uma chave estrangeira
+ constraint na chave primária da tabela mapeada referencia a
tabela da classe
+ associada, Esta opção afeta a ordem em queh
<literal>save()</literal> e
+ <literal>delete()</literal> são cascateadas, e
determina se a associação
+ pode ser substituída (isto também é usado pela ferramenta
schema export).
+ </para>
+ </callout>
+ <callout arearefs="onetoone5">
+ <para>
+ <literal>fetch</literal> ((opcional – valor
default <literal>select</literal>):
+ Escolhe entre outer-join fetching ou sequential select
fetching.
+ </para>
+ </callout>
+ <callout arearefs="onetoone6">
+ <para>
+ <literal>property-ref</literal>(opcional): O nome
da propriedade da classe associada
+ que é ligada a chave primária desta classe. Se não for
especificada, a chave primária
+ da classe associada é utilizada.
+ </para>
+ </callout>
+ <callout arearefs="onetoone7">
+ <para>
+ <literal>access</literal> (opcional - valor
default padrão <literal>property</literal>):
+ A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="onetoone8">
+ <para>
+ <literal>formula</literal> (opcional): Quase
todas associações um-pra-um mapeiam
+ para a chave primária da entidade dona. No caso raro, que não
é o caso, você
+ pode especificar uma outra coluna, colunas ou expressões para
juntar utilizando
+ uma formula SQL. (Veja
<literal>org.hibernate.test.onetooneformula</literal>
+ para exemplo).
+ </para>
+ </callout>
+ <callout arearefs="onetoone9">
+ <para>
+ <literal>lazy</literal> (opcional – valor default
<literal>proxy</literal>):
+ Por default, associações single point são proxied.
<literal>lazy="no-proxy"</literal>
+ especifica que a propriedade deve ser fetched lazily quando o
atributo é acessado
+ pela primeira vez (requer build-time bytecode
instrumentation).
+ <literal>lazy="false"</literal>
especifica que a associação vai sempre ser
+ avidamente fetched. <emphasis>Note que se
<literal>constrained="false"</literal>,
+ proxing é impossível e o Hibernate vai ávido fetch a
associação!</emphasis>
+ </para>
+ </callout>
+ <callout arearefs="onetoone10">
+ <para>
+ <literal>entity-name</literal> (opcional): O nome
da entidade da classe associada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Existem duas variedades de associações um-pra-um:
+ </para>
+ <itemizedlist>
+ <listitem><para>
+ associações de chave primária
+ </para></listitem>
+ <listitem><para>
+ associações de chave estrangeira exclusiva
+ </para></listitem>
+ </itemizedlist>
+
+ <para>
+ Associações de chave primária não necessitam de uma coluna extra de
tabela; se duas
+ linhas são relacionadas pela associação então as duas linhas da tabela
dividem a mesmo
+ valor da chave primária. Assim, se você quer que dois objetos sejam
relacionados por
+ uma associação de chave primária, você deve ter certeza que eles são
assinados com o
+ mesmo valor identificador!
+ </para>
+
+ <para>
+ Para uma associação de chave primária, adicione os seguintes mapeamentos
em
+ <literal>Employee</literal> e
<literal>Person</literal>, respectivamente.
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
class="Person"/>]]></programlisting>
+ <programlisting><![CDATA[<one-to-one name="employee"
class="Employee" constrained="true"/>]]></programlisting>
+
+ <para>
+ Agora nós devemos assegurar que as chaves primárias de linhas
relacionadas nas
+ tabelas PERSON e EMPLOYEE são iguais. Nós usamos uma estratégia especial
de geração
+ de identificador do Hibernate chamada
<literal>foreign</literal>:
+ </para>
+
+ <programlisting><![CDATA[<class name="person"
table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="foreign">
+ <param name="property">employee</param>
+ </generator>
+ </id>
+ ...
+ <one-to-one name="employee"
+ class="Employee"
+ constrained="true"/>
+</class>]]></programlisting>
+
+ <para>
+ Uma nova instância de <literal>Person</literal> salva
recentemente é então assinada
+ com o mesmo valor da chave primária da instância de
<literal>employee</literal> referenciada
+ com a propriedade <literal>employee</literal> daquela
<literal>Person</literal>.
+ </para>
+
+ <para>
+ Alternativamente, uma chave estrangeira com uma unique constraint, de
+ <literal>Employee</literal> para
<literal>Person</literal>, pode ser expressa como:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="person"
class="Person" column="PERSON_ID"
unique="true"/>]]></programlisting>
+
+ <para>
+ E esta associação pode ser feita de forma bi-direcional adicionando o
seguinte
+ no mapeamento de <literal>Person</literal>:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name"employee"
class="Employee"
property-ref="person"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-naturalid">
+ <title>natural-id</title>
+
+ <programlisting><![CDATA[<natural-id
mutable="true|false"/>
+ <property ... />
+ <many-to-one ... />
+ ......
+</natural-id>]]></programlisting>
+
+ <para>
+ Embora nós recomendemos o uso de surrogate keys como chaves primárias,
você deve
+ ainda identificar chaves naturais para todas as entidades. Uma chave
natural é
+ uma propriedade ou combinação de propriedades que é exclusiva e não nula.
Se não
+ pude ser modificada, melhor ainda. Mapeie as propriedades da chave
natural dentro do
+ elemento <literal><natural-id></literal>. O
Hibernate irá gerar a chave
+ exclusiva necessária e as constraints de nullability , e seu mapeamento
será
+ apropriadamente auto documentado.
+ </para>
+
+ <para>
+ Nós recomendamos com enfase que você implemente
<literal>equals()</literal> e
+ <literal>hashCode()</literal> para comparar as propriedades
da chave natural da
+ entidade.
+ </para>
+
+ <para>
+ Este mapeamento não tem o objetivo de uso com entidades com natural
chaves primárias.
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>mutable</literal> mutable (opcional, valor
default<literal>false</literal>):
+ Por default, propriedades naturais identificadoras são
consideradas imutáveis (constante).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-component"
revision="2">
+ <title>componente, componente dinâmico</title>
+
+ <para>
+ O elemento<literal><component></literal> mapeia
propriedades de um
+ objeto filho para colunas da tabela de uma classe pai. Componentes podem,
+ um após o outro, declarar suas próprias propriedades, componentes ou
coleções.
+ Veja "Components" abaixo.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="component1" coords="2 45"/>
+ <area id="component2" coords="3 45"/>
+ <area id="component3" coords="4 45"/>
+ <area id="component4" coords="5 45"/>
+ <area id="component5" coords="6 45"/>
+ <area id="component6" coords="7 45"/>
+ <area id="component7" coords="8 45"/>
+ <area id="component8" coords="9 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<component
+ name="propertyName"
+ class="className"
+ insert="true|false"
+ update="true|false"
+ access="field|property|ClassName"
+ lazy="true|false"
+ optimistic-lock="true|false"
+ unique="true|false"
+ node="element-name|."
+>
+
+ <property ...../>
+ <many-to-one .... />
+ ........
+</component>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="component1">
+ <para>
+ <literal>name</literal>: O nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="component2">
+ <para>
+ <literal>class</literal> (opcional – valor
default para o tipo de
+ propriedade determinada por reflection): O nome da classe
(filha) do
+ componente.
+ </para>
+ </callout>
+ <callout arearefs="component3">
+ <para>
+ <literal>insert</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>INSERT</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="component4">
+ <para>
+ <literal>update</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>UPDATE</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="component5">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o Hibernate pode usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="component6">
+ <para>
+ <literal>lazy</literal> (opcional - valor default
<literal>false</literal>):
+ Especifica que este componente deve ser fetched lazily quando
o atributo for
+ acessado pela primeira vez (requer build-time bytecode
instrumentation).
+ </para>
+ </callout>
+ <callout arearefs="component7">
+ <para>
+ <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
+ Especifica que atualizações para este componente requerem
ou não aquisição
+ de um lock otimista. Em outras palavras, determina se uma
versão de incremento deve
+ ocorrer quando esta propriedade estiver modificada.
+ </para>
+ </callout>
+ <callout arearefs="component8">
+ <para>
+ <literal>unique</literal> (opcional – valor
default <literal>false</literal>):
+ Especifica que existe uma unique constraint em todas as
colunas mapeadas do
+ componente.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A tag filha <literal><property></literal>
acrescenta a propriedade
+ de mapeamento da classe filha para colunas de uma tabela.
+ </para>
+
+ <para>
+ O elemento <literal><component></literal>
permite um sub-elemento
+ <literal><parent></literal> mapeie uma
propriedade da classe do componente
+ como uma referencia de volta para a entidade que o contém.
+ </para>
+
+ <para>
+ O elemento
<literal><dynamic-component></literal> permite que um
+ <literal>Map</literal> possa ser mapeado como um componente
onde os nomes das
+ propriedades referem-se para as chaves no mapa, veja
+ <xref linkend="components-dynamic"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-properties"
revision="2">
+ <title>propriedades</title>
+
+ <para>
+ O elemento <literal><properties></literal>
permite a definição de um grupo
+ com nome, lógico de propriedades de uma classe. O uso mais importante do
construtor
+ é que este permite uma combinação de propriedades para ser o objetivo de
uma
+ <literal>property-ref</literal>. É também um modo
conveninente para definir uma
+ unique constraint de múltiplas colunas.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="properties1" coords="2 45"/>
+ <area id="properties2" coords="3 45"/>
+ <area id="properties3" coords="4 45"/>
+ <area id="properties4" coords="5 45"/>
+ <area id="properties5" coords="6 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<properties
+ name="logicalName"
+ insert="true|false"
+ update="true|false"
+ optimistic-lock="true|false"
+ unique="true|false"
+>
+
+ <property ...../>
+ <many-to-one .... />
+ ........
+</properties>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="properties1">
+ <para>
+ <literal>name</literal>:: O nome lógico do
agrupamento –
+ <emphasis>não </emphasis> é o nome atual de
propriedade.
+ </para>
+ </callout>
+ <callout arearefs="properties2">
+ <para>
+ <literal>insert</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>INSERT</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="properties3">
+ <para>
+ <literal>update</literal>: As colunas mapeadas
aparecem nos
+ SQL de <literal>UPDATE</literal>s?
+ </para>
+ </callout>
+ <callout arearefs="properties4">
+ <para>
+ <literal>optimistic-lock</literal> (opcional
– valor default <literal>true</literal>):
+ Especifica que atualizações para estes componentes
requerem ou não aquisição de um
+ lock otimista. Em outras palavras, determina se uma
versão de incremento deve ocorrer
+ quando estas propriedades estiverem modificadas.
+ </para>
+ </callout>
+ <callout arearefs="properties5">
+ <para>
+ <literal>unique</literal> (opcional – valor
defautl <literal>false</literal>):
+ Especifica que uma unique constraint existe em todas as
colunas mapeadas do componente.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Por exemplo, se nós temos o seguinte mapeamento de
<literal><properties></literal>:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="personNumber"/>
+ ...
+ <properties name="name"
+ unique="true" update="false">
+ <property name="firstName"/>
+ <property name="initial"/>
+ <property name="lastName"/>
+ </properties>
+</class>]]></programlisting>
+
+ <para>
+ Então nós podemos ter uma associação de dados herdados que referem a
esta chave
+ exclusiva da tabela <literal>Person</literal>, ao invés de se
referirem a chave
+ primária:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="person"
+ class="Person" property-ref="name">
+ <column name="firstName"/>
+ <column name="initial"/>
+ <column name="lastName"/>
+</many-to-one>]]></programlisting>
+
+ <para>
+ Nós não recomendamos o uso deste tipo de coisa fora do contexto de
mapeamento de
+ dados herdados.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-subclass" revision="4">
+ <title>subclass (subclasse)</title>
+
+ <para>
+ Finalmente, a persistência polimórfica requer a declaração de cada
subclasse
+ da classe de persistência raiz. Para a estratégia de mapeamento
+ table-per-class-hierarchy, a declaração
<literal><subclass></literal>
+ deve ser usada.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="subclass1" coords="2 55"/>
+ <area id="subclass2" coords="3 55"/>
+ <area id="subclass3" coords="4 55"/>
+ <area id="subclass4" coords="5 55"/>
+ </areaspec>
+ <programlisting><![CDATA[<subclass
+ name="ClassName"
+ discriminator-value="discriminator_value"
+ proxy="ProxyInterface"
+ lazy="true|false"
+ dynamic-update="true|false"
+ dynamic-insert="true|false"
+ entity-name="EntityName"
+ node="element-name"
+ extends="SuperclassName">
+
+ <property .... />
+ .....
+</subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="subclass1">
+ <para>
+ <literal>name</literal>: O nome de classe
completamente qualificada da subclasse.
+ </para>
+ </callout>
+ <callout arearefs="subclass2">
+ <para>
+ <literal>discriminator-value</literal> (opcional
– valor default o nome da classe):
+ Um valor que distingue subclasses individuais.
+ </para>
+ </callout>
+ <callout arearefs="subclass3">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface que
+ usará os proxies de inicialização atrasada.
+ </para>
+ </callout>
+ <callout arearefs="subclass4">
+ <para>
+ <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
+ Configurar
<literal>lazy="false"</literal> desabilitará o uso de
+ inicialização atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+ <para>
+ Cada subclasse deve declarar suas próprias propriedades persistentes e
subclasses.
+ As propriedades <literal><version></literal> e
<literal><id></literal>
+ são configuradas para serem herdades da classe raiz. Cada subclasse numa
hierarquia
+ deve definir um único <literal>discriminator-value</literal>.
Se nenhum for
+ especificado, o nome da classe Java completamente qualificada será
usada.
+ </para>
+
+ <para>
+ Para informações sobre mapeamento de heranças, veja o <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-joinedsubclass"
revision="3">
+ <title>joined-subclass</title>
+
+ <para>
+ Alternativamente, cada subclasse pode ser mapeada para sua própria tabela
+ (Estratégia de mapeamento table-per-subclass). O estado herdado é
devolvido
+ por associação com a tabela da superclasse. Nós usamos o elemento
+ <literal><joined-subclass></literal>.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="joinedsubclass1" coords="2 45"/>
+ <area id="joinedsubclass2" coords="3 45"/>
+ <area id="joinedsubclass3" coords="4 45"/>
+ <area id="joinedsubclass4" coords="5 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<joined-subclass
+ name="ClassName"
+ table="tablename"
+ proxy="ProxyInterface"
+ lazy="true|false"
+ dynamic-update="true|false"
+ dynamic-insert="true|false"
+ schema="schema"
+ catalog="catalog"
+ extends="SuperclassName"
+ persister="ClassName"
+ subselect="SQL expression"
+ entity-name="EntityName"
+ node="element-name">
+
+ <key .... >
+
+ <property .... />
+ .....
+</joined-subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="joinedsubclass1">
+ <para>
+ <literal>name</literal>: O nome da classe
completamente qualificada da
+ subclasse.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass2">
+ <para>
+ <literal>table</literal>: O nome da tabela da
subclasse.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass3">
+ <para>
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface
+ para usar os proxies de recuperação atrasada.
+ </para>
+ </callout>
+ <callout arearefs="joinedsubclass4">
+ <para>
+ <literal>lazy</literal> (opcional, valor default
<literal>true</literal>):
+ Fixanr <literal>lazy="false"</literal>
desabilita o uso recuperação
+ atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A coluna discriminator requerida para esta estratégia de mapeamento.
Porém,
+ cada subclasse deve declarar uma coluna de tabela com o identificador do
objeto
+ usando o elemento <literal><key></literal>. O
mapeamento no início do
+ capítulo poderia ser re-escrito assim:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+ "-//Hibernate/Hibernate Mapping DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
+
+<hibernate-mapping package="eg">
+
+ <class name="Cat" table="CATS">
+ <id name="id" column="uid"
type="long">
+ <generator class="hilo"/>
+ </id>
+ <property name="birthdate" type="date"/>
+ <property name="color" not-null="true"/>
+ <property name="sex" not-null="true"/>
+ <property name="weight"/>
+ <many-to-one name="mate"/>
+ <set name="kittens">
+ <key column="MOTHER"/>
+ <one-to-many class="Cat"/>
+ </set>
+ <joined-subclass name="DomesticCat"
table="DOMESTIC_CATS">
+ <key column="CAT"/>
+ <property name="name" type="string"/>
+ </joined-subclass>
+ </class>
+
+ <class name="eg.Dog">
+ <!-- mapping for Dog could go here -->
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Para informações de mapeamentos de herança, veja <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-unionsubclass"
revision="2">
+ <title>union-subclass</title>
+
+ <para>
+ Uma terceira opção é mapear para tabelas apenas as classes concretas de
uma
+ hierarquia de heranças, (a estratégia table-per-concrete-class) onde cada
tabela
+ define todos os estados persistentes da classe, incluindo estados
herdados.
+ No Hibernate, não é absolutamente necessário mapear explicitamente como
hierarquia
+ de heranças. Você pode simplesmente mapear cada classe com uma declaração
+ <literal><class></literal> separada. Porém, se
você deseja usar associações
+ polimórficas (por exemplo: uma associação para a superclasse de sua
hierarquia),
+ você precisa usar o mapeamento
<literal><union-subclass></literal>.
+
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="unionsubclass1" coords="2 45"/>
+ <area id="unionsubclass2" coords="3 45"/>
+ <area id="unionsubclass3" coords="4 45"/>
+ <area id="unionsubclass4" coords="5 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<union-subclass
+ name="ClassName"
+ table="tablename"
+ proxy="ProxyInterface"
+ lazy="true|false"
+ dynamic-update="true|false"
+ dynamic-insert="true|false"
+ schema="schema"
+ catalog="catalog"
+ extends="SuperclassName"
+ abstract="true|false"
+ persister="ClassName"
+ subselect="SQL expression"
+ entity-name="EntityName"
+ node="element-name">
+
+ <property .... />
+ .....
+</union-subclass>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="unionsubclass1">
+ <para>
+ <literal>name</literal>: O nome da subclasse
completamente qualificada.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass2">
+ <para>
+ <literal>table</literal>: O nome da tabela da
subclasse.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass3">
+ <para>
+ <literal>proxy</literal> (optional): Specifies a
class or interface to use
+ for lazy initializing proxies.
+
+ <literal>proxy</literal> (opcional): Especifica a
classe ou interface para usar
+ os proxies de recuperação atrasada.
+ </para>
+ </callout>
+ <callout arearefs="unionsubclass4">
+ <para>
+ <literal>lazy</literal> (optional, defaults to
<literal>true</literal>): Setting
+ <literal>lazy="false"</literal>
disables the use of lazy fetching.
+ <literal>lazy</literal> (opcional, valor default
p<literal>true</literal>):
+ Fixando <literal>lazy="false"</literal>
desabilita o uso da recuperação atrasada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A coluna discriminatõria não é requerida para esta estratégia de
mapeamento.
+
+ </para>
+
+ <para>
+ Para informações sobre mapeamentos de herança, veja <xref
linkend="inheritance"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-join" revision="3">
+ <title>join</title>
+
+ <para>
+ Usando o elemento
<literal><join></literal>>, é possível mapear
+ propriedades de uma classe para várias tabelas.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="join1" coords="2 50"/>
+ <area id="join2" coords="3 50"/>
+ <area id="join3" coords="4 50"/>
+ <area id="join4" coords="5 50"/>
+ <area id="join5" coords="6 50"/>
+ <area id="join6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<join
+ table="tablename"
+ schema="owner"
+ catalog="catalog"
+ fetch="join|select"
+ inverse="true|false"
+ optional="true|false">
+
+ <key ... />
+
+ <property ... />
+ ...
+</join>]]></programlisting>
+
+ <calloutlist>
+ <callout arearefs="join1">
+ <para>
+ <literal>table</literal>: O nome da tabela
associada.
+ </para>
+ </callout>
+ <callout arearefs="join2">
+ <para>
+ <literal>schema</literal> (opcional): Sobrepõe o
nome do esquema
+ especificado pelo elemento raiz
<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="join3">
+ <para>
+ <literal>catalog</literal> (opcional): Sobrepõe o
nome do catálogo
+ especificado pelo elemento
raiz<literal><hibernate-mapping></literal>.
+ </para>
+ </callout>
+ <callout arearefs="join4">
+ <para>
+ <literal>fetch</literal>(opcional – valor default
<literal>join</literal>): Se setado
+ para <literal>join</literal>, o padrão, o
Hibernate irá usar um inner join para
+ restaurar um <literal>join</literal> definido por
uma classe ou suas subclasses e
+ uma outer join para um <literal>join</literal>
definido por uma subclasse.
+ Se setado para <literal>select</literal>, então o
Hibernate irá usar uma seleção
+ seqüencial para um
<literal><join></literal> definida numa subclasse, que irá
+ ser emitido apenas se uma linha se concentrar para
representar uma instância
+ da subclasse. Inner joins irá ainda ser usado para restaurar
um
+ <literal><join></literal> definido
pela classe e suas superclasses.
+ </para>
+ </callout>
+ <callout arearefs="join5">
+ <para>
+ <literal>inverse</literal> (opcional – valor
default <literal>false</literal>):
+ Se habilitado, o Hibernate não irá tentar inserir ou
atualizar as propriedades
+ definidas por este join.
+ </para>
+ </callout>
+ <callout arearefs="join6">
+ <para>
+ <literal>optional</literal> (opcional – valor
default <literal>false</literal>):
+ Se habilitado, o Hibernate irá inserir uma linha apenas se as
propriedades definidas
+ por esta junção não forem nulas e irá sempre usar uma outer
join para
+ recuperar as propriedades.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Por exemplo, a informação de endereço para uma pessoa pode ser mapeada
para uma
+ tabela separada (enquanto preservando o valor da semântica de tipos para
+ todas as propriedades):
+ </para>
+
+ <programlisting><![CDATA[<class name="Person"
+ table="PERSON">
+
+ <id name="id" column="PERSON_ID">...</id>
+
+ <join table="ADDRESS">
+ <key column="ADDRESS_ID"/>
+ <property name="address"/>
+ <property name="zip"/>
+ <property name="country"/>
+ </join>
+ ...]]></programlisting>
+
+ <para>
+ Esta característica é útil apenas para modelos de dados legados, nós
recomendamos
+ menos tabelas do que classes e um modelo de domínio bem granulado. Porém,
é
+ útil para ficar trocando entre estratégias de mapeamento de herança
+ numa hierarquia simples, como explicado mais a frente.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-key">
+ <title>key</title>
+
+ <para>
+ Nós vimos que o elemento
<literal><key></literal> surgiu algumas vezes
+ até agora. Ele aparece em qualquer lugar que o elemento pai define uma
junção
+ para a nova tabela, e define a chave estrangeira para a tabela associada,
que
+ referencia a chave primária da tabela original.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="key1" coords="2 50"/>
+ <area id="key2" coords="3 50"/>
+ <area id="key3" coords="4 50"/>
+ <area id="key4" coords="5 50"/>
+ <area id="key5" coords="6 50"/>
+ <area id="key6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<key
+ column="columnname"
+ on-delete="noaction|cascade"
+ property-ref="propertyName"
+ not-null="true|false"
+ update="true|false"
+ unique="true|false"
+/>]]></programlisting>
+
+ <calloutlist>
+ <callout arearefs="key1">
+ <para>.
+ <literal>column</literal> (opcional): O nome da
coluna da chave estrangeira.
+ Isto também pode ser especificado por aninhamento de
elemento(s)
+ <literal><column></literal>.
+ </para>
+ </callout>
+ <callout arearefs="key2">
+ <para>
+ <literal>on-delete</literal> (opcional, valor
default <literal>noaction</literal>):
+ Especifica se a constraint da chave estrangeira no banco de
dados esta
+ habilitada para cascade delete .
+ </para>
+ </callout>
+ <callout arearefs="key3">
+ <para>
+ <literal>property-ref</literal> (opcional):
Especifica que a chave estrangeira
+ se refere a colunas que não são chave primária da tabela
original.
+ (Util para base de dados legadas.)
+ </para>
+ </callout>
+ <callout arearefs="key4">
+ <para>
+ <literal>not-null</literal> (opcional):
Especifica que a coluna da chave
+ estrangeira não aceita valores nulos (isto é implícito em
qualquer momento
+ que a chave estrangeira também fizer parte da chave
primária).
+ </para>
+ </callout>
+ <callout arearefs="key5">
+ <para>
+ <literal>update</literal> (optional): Specifies
that the foreign key should never
+ be updated (this is implied whenever the foreign key is also
part of the primary
+ key).
+ <literal>update</literal> (opcional): Especifica
que a chave estrangeira nunca
+ deve ser atualizada (isto é implícito em qualquer momento que
a chave estrangeira
+ também fizer parte da chave primária).
+ </para>
+ </callout>
+ <callout arearefs="key6">
+ <para>
+ <literal>unique</literal> (opcional): Especifica
que a chave estrangeira deve ter
+ uma constraint unique (sto é implícito em qualquer momento
que a chave estrangeira
+ também fizer parte da chave primária).
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Nós recomendamos que para sistemas que a performance de delete seja
importante, todas as
+ chaves deve ser definida
<literal>on-delete="cascade"</literal>, e o Hibernate irá usar
+ uma constraint a nível de banco de dados <literal>ON CASCADE
DELETE</literal>, ao invés
+ de muitas instruções <literal>DELETE</literal>. Esteja ciente
que esta característica é
+ um atalho da estratégia usual de optimistic locking do Hibernate para
dados versionados.
+ </para>
+
+ <para>
+ Os atributos <literal>not-null</literal> e
<literal>update</literal> são úteis quando
+ estamos mapeamos uma associação unidirecional um para muitos. Se você
mapear uma
+ asociação unidirecional um para muitos para uma chave estrangeira
non-nullable, você
+ <emphasis>deve</emphasis> declarar a coluna chave usando
+ <literal><key
not-null="true"></literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-column" revision="4">
+ <title>elementos column e formula</title>
+ <para>
+ Qualquer elemento de mapeamente que aceita um atributo
<literal>column</literal> irá
+ aceitar alternativamente um subelemento
<literal><column></literal>. Da mesma forma,
+ <literal>formula</literal> é uma alternativa para o atributo
<literal>formula</literal>.
+ </para>
+
+ <programlisting><![CDATA[<column
+ name="column_name"
+ length="N"
+ precision="N"
+ scale="N"
+ not-null="true|false"
+ unique="true|false"
+ unique-key="multicolumn_unique_key_name"
+ index="index_name"
+ sql-type="sql_type_name"
+ check="SQL expression"
+ default="SQL expression"/>]]></programlisting>
+
+ <programlisting><![CDATA[<formula>SQL
expression</formula>]]></programlisting>
+
+ <para>
+ O atributo <literal>column</literal> e
<literal>formula</literal> podem até ser combinados
+ dentro da mesma propriedade ou associação mapeando para expressar,
+ por exemplo, associações exóticas.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one
name="homeAddress" class="Address"
+ insert="false" update="false">
+ <column name="person_id" not-null="true"
length="10"/>
+ <formula>'MAILING'</formula>
+</many-to-one>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="mapping-declaration-import">
+ <title>import</title>
+
+ <para>
+ Suponha que a sua aplicação tem duas classes persistentes com o mesmo
nome, e você não quer
+ especificar o nome qualificado (do pacote) nas queries do Hibernate. As
Classes devem
+ ser "importadas" explicitamente, de preferência contando com
<literal>auto-import="true"</literal>.
+ Você pode até importar classes e interfaces que não estão explicitamente
mapeadas.
+ </para>
+
+ <programlisting><![CDATA[<import
class="java.lang.Object"
rename="Universe"/>]]></programlisting>
+
+ <programlistingco>
+ <areaspec>
+ <area id="import1" coords="2 40"/>
+ <area id="import2" coords="3 40"/>
+ </areaspec>
+ <programlisting><![CDATA[<import
+ class="ClassName"
+ rename="ShortName"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="import1">
+ <para>
+ <literal>class</literal>: O nome qualificado (do
pacote) de qualquer classe Java.
+ </para>
+ </callout>
+ <callout arearefs="import2">
+ <para>
+ <literal>rename</literal> (opcional – valor
default, o nome da classe não
+ qualificada): Um nome que pode ser usado numa linguagem de
consulta.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </sect2>
+
+ <sect2 id="mapping-types-anymapping" revision="2">
+ <title>any</title>
+
+ <para>
+ Existe mais um tipo de propriedade de mapeamento. O elemento de
mapeamento
+ <literal><any></literal> define uma associação
polimórfica para classes de múltiplas tabelas.
+ Este tipo de mapeamento sempre requer mais de uma coluna. A primeira
coluna possui o tipo da entidade
+ associada. A outra coluna que ficou possui o identificador. É impossível
especificar uma restrição
+ de chave estrangeira para este tipo de associação, assim isto claramente
não é visto
+ como um caminho usual para associações (polimórficas) de mapeamento. Você
deve usar este mapeamento
+ apenas em casos muito especiais (exemplo: audit logs, dados de sessão do
usuário, etc).
+
+ </para>
+
+ <para>
+ O atributo <literal>meta-type</literal> permite a aplicação
especificar um tipo adaptado
+ que mapeia valores de colunas de banco de dados para classes
persistentes que tem propriedades
+ identificadoras do tipo especificado através do
<literal>id-type</literal>. Você deve especificar
+ o mapeamento de valores do meta-type para nome de classes.
+ </para>
+
+ <programlisting><![CDATA[<any name="being"
id-type="long" meta-type="string">
+ <meta-value value="TBL_ANIMAL" class="Animal"/>
+ <meta-value value="TBL_HUMAN" class="Human"/>
+ <meta-value value="TBL_ALIEN" class="Alien"/>
+ <column name="table_name"/>
+ <column name="id"/>
+</any>]]></programlisting>
+
+ <programlistingco>
+ <areaspec>
+ <area id="any1" coords="2 50"/>
+ <area id="any2" coords="3 50"/>
+ <area id="any3" coords="4 50"/>
+ <area id="any4" coords="5 50"/>
+ <area id="any5" coords="6 50"/>
+ <area id="any6" coords="7 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<any
+ name="propertyName"
+ id-type="idtypename"
+ meta-type="metatypename"
+ cascade="cascade_style"
+ access="field|property|ClassName"
+ optimistic-lock="true|false"
+>
+ <meta-value ... />
+ <meta-value ... />
+ .....
+ <column .... />
+ <column .... />
+ .....
+</any>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="any1">
+ <para>
+ <literal>name</literal>: o nome da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="any2">
+ <para>
+ <literal>id-type</literal>: o tipo
identificador.
+ </para>
+ </callout>
+ <callout arearefs="any3">
+ <para>
+ <literal>meta-type</literal> (opcional – valor
default <literal>string</literal>):
+ Qualquer tipo que é permitido para um mapeamento
discriminador.
+ </para>
+ </callout>
+ <callout arearefs="any4">
+ <para>
+ <literal>cascade</literal> (opcional – valor
default <literal>none</literal>):
+ o estilo do cascade.
+ </para>
+ </callout>
+ <callout arearefs="any5">
+ <para>
+ <literal>access</literal> (opcional – valor
default <literal>property</literal>):
+ A estratégia que o hibernate deve usar para acessar o valor
da propriedade.
+ </para>
+ </callout>
+ <callout arearefs="any6">
+ <para>
+ <literal>optimistic-lock</literal> (opcional -
valor default<literal>true</literal>):
+ Especifica que as atualizações para esta propriedade requerem
ou não aquisição da
+ trava otimista. Em outras palavras, define se uma versão de
incremento deve ocorrer
+ se esta propriedade está modificada.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="mapping-types">
+ <title>Tipos do Hibernate</title>
+
+ <sect2 id="mapping-types-entitiesvalues" revision="1">
+ <title>Entidades e valores</title>
+
+ <para>
+ Para entender o comportamento de vários objetos em nível de linguagem de
Java a
+ respeito do serviço de persistência, nós precisamos classificá-los em
dois grupos.
+ </para>
+
+ <para>
+ Uma <emphasis>entidade </emphasis> existe independentemente
de qualquer outro
+ objeto guardando referências para a entidade. Em contraste com o modelo
usual de
+ Java que um objeto não referenciado é coletado pelo garbage collector.
Entidades
+ devem ser explicitamente salvas ou deletada (exceto em operações de
salvamento
+ ou deleção que possam ser executada em
<emphasis>cascata</emphasis> de uma entidade
+ pai para seus filhos). Isto é diferente do modelo ODMG de persistência do
objeto
+ por acessibilidade – e corresponde quase a como objetos de aplicações são
+ geralmente usados em grandes sistemas. Entidades suportam referências
circulares
+ e comuns. Eles podem ser versionadas.
+ </para>
+
+ <para>
+ Uma entidade em estado persistente consiste de referências para outras
entidades
+ e instâncias de tipos de <emphasis>valor</emphasis>. Valores
são primitivos,
+ coleções (não o que tem dentro de uma coleção), componentes e certos
objetos
+ imutáveis. Entidades distintas, valores (em coleções e componentes
particulares)
+ <emphasis>são </emphasis> persistidos e apagados por
acessibilidade. Visto que
+ objetos value (e primitivos) são persistidos e apagados junto com as
entidades
+ que os contém e não podem ser versionados independentemente. Valores têm
+ identidade não independente, assim eles não podem ser comuns para duas
+ entidades ou coleções.
+
+ </para>
+
+ <para>
+ Até agora, nós estivemos usando o termo "classe persistente"
para referir
+ a entidades. Nós iremos continuar a fazer isto. Falando a rigor, porém,
nem todas
+ as classes definidas pelo usuário com estados persistentes são entidades.
Um
+ <emphasis>componente</emphasis> é uma classe de usuário
definida com valores
+ semânticos. Uma propriedade de Java de tipo
<literal>java.lang.String</literal>
+ também tem um valor semêntico. Dada esta definição, nós podemos dizer que
+ todos os tipos (classes) fornecida pelo JDK tem tipo de valor semântico
em Java,
+ enquanto que tipos definidos pelo usuário pode ser mapeados com entidade
ou valor
+ de tipo semântico. Esta decisão pertence ao desenvolvedor da aplicação.
Uma boa
+ dica para uma classe entidade em um modelo de domínio são referências
comuns
+ para uma instância simples daquela classe, enquanto a composição ou
agregação
+ geralmente se traduz para um valor de tipo.
+ </para>
+
+ <para>
+ Nós iremos rever ambos os conceitos durante toda a documentação.
+
+ </para>
+
+ <para>
+ O desafio pe mapear o sistema de tipo de Java (e a definição do
desenvolvedor de
+ entidades e tipos de valor) para o sistema de tipo SQL/banco de dados. A
ponte entre ambos
+ os sistemas é fornecido pelo Hibernate: para entidades que usam
+ <literal><class></literal>,
<literal><subclass></literal> e assim por diante.
+ Para tipos de valores nós usamos
<literal><property></literal>,
+ <literal><component></literal>, etc, geralmente
com um atributo
+ <literal>type</literal>. O valor deste atributo é o nome de
um <emphasis>tipo de
+ mapeamento</emphasis> do Hibernate. O Hibernate fornece muitos
mapeamentos
+ (para tipos de valores do JDK padrão) ut of the box. Você pode escrever
os seus
+ próprios tipos de mapeamentos e implementar sua estratégia de conversão
adaptada,
+ como você verá adiante.
+ </para>
+
+ <para>
+ Todos os tipos internos do hibernate exceto coleções suportam semânticas
nulas.
+
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-types-basictypes" revision="3">
+ <title>Valores de tipos básicos</title>
+
+ <para>
+ O tipos internos de mapeamentos básicos podem ser a grosso modo
categorizado como:
+ <variablelist>
+ <varlistentry>
+ <term><literal>integer, long, short, float, double,
character, byte,
+ boolean, yes_no, true_false</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos de classes primitivas ou wrapper
Java especificos
+ (vendor-specific) para tipos de coluna SQL. Boolean,
+ <literal>boolean, yes_no</literal> são todas
codificações alternativas
+ para um <literal>boolean</literal> ou
<literal>java.lang.Boolean</literal>
+ do Java.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>string</literal></term>
+ <listitem>
+ <para>
+ Um tipo de mapeamento de
<literal>java.lang.String</literal> para
+ <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>date, time,
timestamp</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamento de
<literal>java.util.Date</literal> e suas
+ subclasses para os tipos SQL
<literal>DATE</literal>,
+ <literal>TIME</literal> e
<literal>TIMESTAMP</literal>
+ (ou equivalente).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>calendar,
calendar_date</literal></term>
+ <listitem>
+ <para>
+ Tipo de mapeamento de
<literal>java.util.Calendar</literal> para
+ os tipos SQL <literal>TIMESTAMP</literal> e
+ <literal>DATE</literal> (ou equivalente).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>big_decimal,
big_integer</literal></term>
+ <listitem>
+ <para>
+ Tipo de mapeamento de
<literal>java.math.BigDecimal</literal> and
+ <literal>java.math.BigInteger</literal> para
<literal>NUMERIC</literal>
+ (ou <literal>NUMBER</literal> no Oracle).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>locale, timezone,
currency</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos de
<literal>java.util.Locale</literal>,
+ <literal>java.util.TimeZone</literal> e
<literal>java.util.Currency</literal>
+ para <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no Oracle).
+ Instâncias de f <literal>Locale</literal> e
<literal>Currency</literal>
+ são mapeados para seus códigos ISO. Instâncias de
<literal>TimeZone</literal>
+ são mapeados para seu <literal>ID</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>class</literal></term>
+ <listitem>
+ <para>
+ um tipo de mapeamento de
<literal>java.lang.Class</literal> para
+ <literal>VARCHAR</literal> (ou
<literal>VARCHAR2</literal> no
+ Oracle). Uma <literal>Class</literal> é
mapeada pelo
+ seu nome qualificado (completo).
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>binary</literal></term>
+ <listitem>
+ <para>
+ Mapeia arrays de bytes para um tipo binário de SQL
apropriado.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>text</literal></term>
+ <listitem>
+ <para>
+ Maps long Java strings to a SQL
<literal>CLOB</literal> or
+ <literal>TEXT</literal> type.
+ Mapeia strings longas de Java para um tipo SQL
+ <literal>CLOB</literal> ou
<literal>TEXT</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>serializable</literal></term>
+ <listitem>
+ <para>
+ Mapeia tipos Java serializáveis para um tipo binário SQL
apropriado.
+ Você pode também indicar o tipo
<literal>serializable</literal> do
+ Hibernate com o nome da classe ou interface Java
serializável que
+ não é padrão para um tipo básico.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><literal>clob,
blob</literal></term>
+ <listitem>
+ <para>
+ Tipos de mapeamentos para as classes JDBC
<literal>java.sql.Clob</literal> and
+ <literal>java.sql.Blob</literal>. Estes tipos
podem ser inconveniente para
+ algumas aplicações, visto que o objeto blob ou clob pode
não ser reusado
+ fora de uma transação. (Além disso, o suporte de driver é
imcompleto e
+ inconsistente.)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <literal>imm_date, imm_time, imm_timestamp,
imm_calendar, imm_calendar_date,
+ imm_serializable, imm_binary</literal>
+ </term>
+ <listitem>
+ <para>
+ Mapeando tipos para o que geralmente são consideradas
tipos mutáveis de
+ Java, onde o Hibernate faz determinadas otimizações
apropriadas somente
+ para tipos imutáveis de Java, e a aplicação trata o
objeto como imutável.
+ Por exemplo, você não deve chamar
<literal>Date.setTime()</literal> para
+ uma instância mapeada como
<literal>imm_timestamp</literal>. Para mudar
+ o valor da propriedade, e ter a mudança feita
persistente, a aplicação
+ deve atribuir um novo objeto (nonidentical) à
propriedade.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+
+ <para>
+ Identificadores únicos das entidades e coleções podem ser de qualquer
tipo
+ básico exceto <literal>binary</literal>,
<literal>blob</literal> ou
+ <literal>clob</literal>. (Identificadores compostos também
são permitidos,
+ veja abaixo.)
+ </para>
+
+ <para>
+ Os tipos de valores básicos têm suas constantes
<literal>Type</literal>
+ correspondentes definidas em
<literal>org.hibernate.Hibernate</literal>. Por exemplo,
+ <literal>Hibernate.STRING</literal> representa o tipo
<literal>string</literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-types-custom" revision="2">
+ <title>Tipos de valores personalizados</title>
+
+ <para>
+ É relativamente fácil para desenvolvedores criar seus próprios tipos de
valor.
+ Por exemplo, você pode querer persistir propriedades do tipo
+ <literal>java.lang.BigInteger</literal> para colunas
<literal>VARCHAR</literal>. O
+ Hibernate não fornece um tipo correspondente para isso. Mas os tipos
adaptados
+ não são limitados a mapeamento de uma propriedade (ou elemento de
coleção) a uma
+ única coluna da tabela. Assim, por exemplo, você pôde ter uma propriedade
Java
+
<literal>getName()</literal>/<literal>setName()</literal> do tipo
+ <literal>java.lang.String</literal> que é persistido para
colunas
+ <literal>FIRST_NAME</literal>,
<literal>INITIAL</literal>, <literal>SURNAME</literal>.
+
+ </para>
+
+ <para>
+ Para implementar um tipo personalizado, implemente
<literal>org.hibernate.UserType</literal>
+ or <literal>org.hibernate.CompositeUserType</literal> e
declare propriedades usando o nome
+ qualificado da classe do tipo. Veja
<literal>org.hibernate.test.DoubleStringType</literal>
+ para ver o tipo das coisas que são possíveis.
+ </para>
+
+ <programlisting><![CDATA[<property name="twoStrings"
type="org.hibernate.test.DoubleStringType">
+ <column name="first_string"/>
+ <column name="second_string"/>
+</property>]]></programlisting>
+
+ <para>
+ Observe o uso da tag
<literal><column></literal> para mapear uma propriedade
+ para colunas múltiplas.
+ </para>
+
+ <para>
+ As interfaces <literal>CompositeUserType</literal>,
<literal>EnhancedUserType</literal>,
+ <literal>UserCollectionType</literal>, e
<literal>UserVersionType</literal>
+ fornecem suporte para usos mais especializados.
+ </para>
+
+ <para>
+ Você pode mesmo fornecer parâmetros a um
<literal>UserType</literal> no arquivo de mapeamento.
+ Para isto, seu <literal>UserType</literal> deve implementar a
interface
+ <literal>org.hibernate.usertype.ParameterizedType</literal>.
Para fornecer parâmetros a seu
+ tipo personalizado, você pode usar o elemento
<literal><type></literal> em seus
+ arquivos de mapeamento.
+ </para>
+
+ <programlisting><![CDATA[<property name="priority">
+ <type name="com.mycompany.usertypes.DefaultValueIntegerType">
+ <param name="default">0</param>
+ </type>
+</property>]]></programlisting>
+
+ <para>
+ O <literal>UserType</literal> pode agora recuperar o valor
para o parâmetro chamado
+ <literal>default</literal> da
<literal>Propriedade</literal> do passado a ele.
+ </para>
+
+ <para>
+ Se você usar freqüentemente um determinado
<literal>UserType</literal>, pode ser útil definir
+ um nome mais curto para ele. Você pode fazer isto usando o elemento
+ <literal><typedef></literal>. Typedefs atribui
um nome a um tipo personalizado, e pode também
+ conter uma lista de valores default de parâmetro se o tipo for
parametrizado.
+ </para>
+
+ <programlisting><![CDATA[<typedef
class="com.mycompany.usertypes.DefaultValueIntegerType"
name="default_zero">
+ <param name="default">0</param>
+</typedef>]]></programlisting>
+
+ <programlisting><![CDATA[<property name="priority"
type="default_zero"/>]]></programlisting>
+
+ <para>
+ It is also possible to override the parameters supplied in a typedef on a
case-by-case basis
+ by using type parameters on the property mapping.
+ </para>
+
+ <para>
+ Even though Hibernate's rich range of built-in types and support for
components means you
+ will very rarely <emphasis>need</emphasis> to use a custom
type, it is nevertheless
+ considered good form to use custom types for (non-entity) classes that
occur frequently
+ in your application. For example, a
<literal>MonetaryAmount</literal> class is a good
+ candidate for a <literal>CompositeUserType</literal>, even
though it could easily be mapped
+ as a component. One motivation for this is abstraction. With a custom
type, your mapping
+ documents would be future-proofed against possible changes in your way of
representing
+ monetary values.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="mapping-entityname">
+ <title>Mapping a class more than once</title>
+ <para>
+ It is possible to provide more than one mapping for a particular persistent
class. In this
+ case you must specify an <emphasis>entity name</emphasis> do
disambiguate between instances
+ of the two mapped entities. (By default, the entity name is the same as the
class name.)
+ Hibernate lets you specify the entity name when working with persistent
objects, when writing
+ queries, or when mapping associations to the named entity.
+ </para>
+
+ <programlisting><![CDATA[<class name="Contract"
table="Contracts"
+ entity-name="CurrentContract">
+ ...
+ <set name="history" inverse="true"
+ order-by="effectiveEndDate desc">
+ <key column="currentContractId"/>
+ <one-to-many entity-name="HistoricalContract"/>
+ </set>
+</class>
+
+<class name="Contract" table="ContractHistory"
+ entity-name="HistoricalContract">
+ ...
+ <many-to-one name="currentContract"
+ column="currentContractId"
+ entity-name="CurrentContract"/>
+</class>]]></programlisting>
+
+ <para>
+ Notice how associations are now specified using
<literal>entity-name</literal> instead of
+ <literal>class</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="mapping-quotedidentifiers">
+ <title>SQL quoted identifiers</title>
+ <para>
+ You may force Hibernate to quote an identifier in the generated SQL by
enclosing the table or
+ column name in backticks in the mapping document. Hibernate will use the
correct quotation
+ style for the SQL <literal>Dialect</literal> (usually double
quotes, but brackets for SQL
+ Server and backticks for MySQL).
+ </para>
+
+ <programlisting><![CDATA[<class name="LineItem"
table="`Line Item`">
+ <id name="id" column="`Item Id`"/><generator
class="assigned"/></id>
+ <property name="itemNumber" column="`Item #`"/>
+ ...
+</class>]]></programlisting>
+
+ </sect1>
+
+
+ <sect1 id="mapping-alternatives">
+ <title>Metadata alternatives</title>
+
+ <para>
+ XML isn't for everyone, and so there are some alternative ways to define O/R
mapping metadata in Hibernate.
+ </para>
+
+ <sect2 id="mapping-xdoclet">
+ <title>Using XDoclet markup</title>
+
+ <para>
+ Many Hibernate users prefer to embed mapping information directly in
sourcecode using
+ XDoclet <literal>(a)hibernate.tags</literal>. We will not cover
this approach in this
+ document, since strictly it is considered part of XDoclet. However, we
include the
+ following example of the <literal>Cat</literal> class with
XDoclet mappings.
+ </para>
+
+ <programlisting><![CDATA[package eg;
+import java.util.Set;
+import java.util.Date;
+
+/**
+ * @hibernate.class
+ * table="CATS"
+ */
+public class Cat {
+ private Long id; // identifier
+ private Date birthdate;
+ private Cat mother;
+ private Set kittens
+ private Color color;
+ private char sex;
+ private float weight;
+
+ /*
+ * @hibernate.id
+ * generator-class="native"
+ * column="CAT_ID"
+ */
+ public Long getId() {
+ return id;
+ }
+ private void setId(Long id) {
+ this.id=id;
+ }
+
+ /**
+ * @hibernate.many-to-one
+ * column="PARENT_ID"
+ */
+ public Cat getMother() {
+ return mother;
+ }
+ void setMother(Cat mother) {
+ this.mother = mother;
+ }
+
+ /**
+ * @hibernate.property
+ * column="BIRTH_DATE"
+ */
+ public Date getBirthdate() {
+ return birthdate;
+ }
+ void setBirthdate(Date date) {
+ birthdate = date;
+ }
+ /**
+ * @hibernate.property
+ * column="WEIGHT"
+ */
+ public float getWeight() {
+ return weight;
+ }
+ void setWeight(float weight) {
+ this.weight = weight;
+ }
+
+ /**
+ * @hibernate.property
+ * column="COLOR"
+ * not-null="true"
+ */
+ public Color getColor() {
+ return color;
+ }
+ void setColor(Color color) {
+ this.color = color;
+ }
+ /**
+ * @hibernate.set
+ * inverse="true"
+ * order-by="BIRTH_DATE"
+ * @hibernate.collection-key
+ * column="PARENT_ID"
+ * @hibernate.collection-one-to-many
+ */
+ public Set getKittens() {
+ return kittens;
+ }
+ void setKittens(Set kittens) {
+ this.kittens = kittens;
+ }
+ // addKitten not needed by Hibernate
+ public void addKitten(Cat kitten) {
+ kittens.add(kitten);
+ }
+
+ /**
+ * @hibernate.property
+ * column="SEX"
+ * not-null="true"
+ * update="false"
+ */
+ public char getSex() {
+ return sex;
+ }
+ void setSex(char sex) {
+ this.sex=sex;
+ }
+}]]></programlisting>
+
+ <para>
+ See the Hibernate web site for more examples of XDoclet and Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="mapping-annotations" revision="2">
+ <title>Using JDK 5.0 Annotations</title>
+
+ <para>
+ JDK 5.0 introduced XDoclet-style annotations at the language level, type-safe
and
+ checked at compile time. This mechnism is more powerful than XDoclet
annotations and
+ better supported by tools and IDEs. IntelliJ IDEA, for example, supports
auto-completion
+ and syntax highlighting of JDK 5.0 annotations. The new revision of the EJB
specification
+ (JSR-220) uses JDK 5.0 annotations as the primary metadata mechanism for
entity beans.
+ Hibernate3 implements the <literal>EntityManager</literal> of
JSR-220 (the persistence API),
+ support for mapping metadata is available via the <emphasis>Hibernate
Annotations</emphasis>
+ package, as a separate download. Both EJB3 (JSR-220) and Hibernate3 metadata
is supported.
+ </para>
+
+ <para>
+ This is an example of a POJO class annotated as an EJB entity bean:
+ </para>
+
+ <programlisting><![CDATA[@Entity(access = AccessType.FIELD)
+public class Customer implements Serializable {
+
+ @Id;
+ Long id;
+
+ String firstName;
+ String lastName;
+ Date birthday;
+
+ @Transient
+ Integer age;
+
+ @Embedded
+ private Address homeAddress;
+
+ @OneToMany(cascade=CascadeType.ALL)
+ @JoinColumn(name="CUSTOMER_ID")
+ Set<Order> orders;
+
+ // Getter/setter and business methods
+}]]></programlisting>
+
+ <para>
+ Note that support for JDK 5.0 Annotations (and JSR-220) is still work in
progress and
+ not completed. Please refer to the Hibernate Annotations module for more
details.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <sect1 id="mapping-generated" revision="1">
+ <title>Generated Properties</title>
+ <para>
+ Generated properties are properties which have their values generated by the
+ database. Typically, Hibernate applications needed to
<literal>refresh</literal>
+ objects which contain any properties for which the database was generating
values.
+ Marking properties as generated, however, lets the application delegate this
+ responsibility to Hibernate. Essentially, whenever Hibernate issues an SQL
INSERT
+ or UPDATE for an entity which has defined generated properties, it
immediately
+ issues a select afterwards to retrieve the generated values.
+ </para>
+ <para>
+ Properties marked as generated must additionally be non-insertable and
non-updateable.
+ Only <xref
linkend="mapping-declaration-version">versions</xref>,
+ <xref
linkend="mapping-declaration-timestamp">timestamps</xref>, and
+ <xref linkend="mapping-declaration-property">simple
properties</xref> can be marked as
+ generated.
+ </para>
+ <para>
+ <literal>never</literal> (the default) - means that the given property
value
+ is not generated within the database.
+ </para>
+ <para>
+ <literal>insert</literal> - states that the given property value is
generated on
+ insert, but is not regenerated on subsequent updates. Things like created-date
would
+ fall into this category. Note that even thought
+ <xref linkend="mapping-declaration-version">version</xref>
and
+ <xref
linkend="mapping-declaration-timestamp">timestamp</xref> properties
can
+ be marked as generated, this option is not available there...
+ </para>
+ <para>
+ <literal>always</literal> - states that the property value is generated
both
+ on insert and on update.
+ </para>
+ </sect1>
+
+ <sect1 id="mapping-database-object">
+ <title>Auxiliary Database Objects</title>
+ <para>
+ Allows CREATE and DROP of arbitrary database objects, in conjunction with
+ Hibernate's schema evolution tools, to provide the ability to fully
define
+ a user schema within the Hibernate mapping files. Although designed
specifically
+ for creating and dropping things like triggers or stored procedures, really
any
+ SQL command that can be run via a
<literal>java.sql.Statement.execute()</literal>
+ method is valid here (ALTERs, INSERTS, etc). There are essentially two modes
for
+ defining auxiliary database objects...
+ </para>
+ <para>
+ The first mode is to explicitly list the CREATE and DROP commands out in the
mapping
+ file:
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <create>CREATE TRIGGER my_trigger ...</create>
+ <drop>DROP TRIGGER my_trigger</drop>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ <para>
+ The second mode is to supply a custom class which knows how to construct the
+ CREATE and DROP commands. This custom class must implement the
+ <literal>org.hibernate.mapping.AuxiliaryDatabaseObject</literal>
interface.
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <definition class="MyTriggerDefinition"/>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ <para>
+ Additionally, these database objects can be optionally scoped such that they
only
+ apply when certain dialects are used.
+ </para>
+ <programlisting><![CDATA[<hibernate-mapping>
+ ...
+ <database-object>
+ <definition class="MyTriggerDefinition"/>
+ <dialect-scope name="org.hibernate.dialect.Oracle9Dialect"/>
+ <dialect-scope name="org.hibernate.dialect.OracleDialect"/>
+ </database-object>
+</hibernate-mapping>]]></programlisting>
+ </sect1>
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/basic_mapping.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/batch.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/batch.xml 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/batch.xml 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,357 @@
+<chapter id="batch">
+ <title>Processamento de lotes</title>
+
+ <para>
+ Uma alternativa para inserir 100.000 linhas no banco de dados usando o Hibernate
+ pode ser a seguinte:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+for ( int i=0; i<100000; i++ ) {
+ Customer customer = new Customer(.....);
+ session.save(customer);
+}
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Isto irá falhar em algum lugar próximo a linha 50.000, lançando uma
+ <literal>OutOfMemoryException</literal>. Isso ocorre devido ao fato
do Hibernate
+ fazer cache de todas as instâncias de <literal>Customer</literal>
inseridas num
+ cachê em nível de sessão.
+ </para>
+
+ <para>
+ Neste capítulo veremos como contornar esse problema. Entretanto, se você vai
realizar
+ processamento de lotes, é muito importante que você habilite o uso de lotes JDBC,
se
+ você pretende obter um desempenho razoável. Defina o tamanho do lote JDBC em um
+ valor razoável (algo entre 10-50):
+ </para>
+
+<programlisting><![CDATA[hibernate.jdbc.batch_size
20]]></programlisting>
+
+ <para>
+ Você também pode querer rodar esse tipo de processamento de lotes com o cache
+ secundário completamente desabilitado:
+ </para>
+
+<programlisting><![CDATA[hibernate.cache.use_second_level_cache
false]]></programlisting>
+
+ <para>
+ Mas isto não é absolutamente necessário, desde que nós possamos ajustar o
+ <literal>CacheMode</literal> para desabilitar a interação com o
cache secundário.
+ </para>
+
+ <sect1 id="batch-inserts">
+ <title>Inserção de lotes</title>
+
+ <para>
+ Quando você estiver inserindo novos objetos persistentes, vocês deve executar
+ os métodos <literal>flush()</literal> e
<literal>clear()</literal> regularmente
+ na sessão, para controlar o tamanho do cache primário.
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+for ( int i=0; i<100000; i++ ) {
+ Customer customer = new Customer(.....);
+ session.save(customer);
+ if ( i % 20 == 0 ) { //20, same as the JDBC batch size
+ //flush a batch of inserts and release memory:
+ session.flush();
+ session.clear();
+ }
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="batch-update" >
+ <title>Batch updates</title>
+
+ <para>
+ Para recuperar e atualizar informações a mesma idéia é válida.
Adicionalmente,
+ pode precisar usar o <literal>scroll()</literal> para usar
recursos no lado
+ do servidor em queries que retornam muita informação.
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+ScrollableResults customers = session.getNamedQuery("GetCustomers")
+ .setCacheMode(CacheMode.IGNORE)
+ .scroll(ScrollMode.FORWARD_ONLY);
+int count=0;
+while ( customers.next() ) {
+ Customer customer = (Customer) customers.get(0);
+ customer.updateStuff(...);
+ if ( ++count % 20 == 0 ) {
+ //flush a batch of updates and release memory:
+ session.flush();
+ session.clear();
+ }
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="batch-statelesssession">
+ <title>A interface StatelessSession</title>
+ <para>
+ Alternativamente, o Hibernate provê uma API orientada à comandos, usada para
+ transmitir um fluxo de dados de e para o banco de dados na forma de objetos
soltos.
+ Uma <literal>StatelessSession</literal> não tem um contexto
persistente associado e
+ não fornece muito das semânticas de alto nível para controle do ciclo de
vida.
+ Em especial, uma StatelessSession não implemente o cache primário e nem
interage
+ com o cache secundário ou query cache. Ele não implementa salvamento
transacional
+ automatico ou checagem automática de mudanças. Operação realizadas usando uma
+ StatelessSession não fazem nenhum tipo de cascade com as instancias
associadas.
+ As coleções são ignoradas por uma StatelessSession. Operações realizadas com
um
+ StatelessSession ignoram a arquitetura de eventos e os interceptadores.
+ StatelessSession são vulneráveis aos efeitos do aliasing dos dados, devido a
+ falta do cache primário. Uma StatelessSession é uma abstração de baixo nível,
+ muito mais próxima do JDBC.
+ </para>
+
+<programlisting><![CDATA[StatelessSession session =
sessionFactory.openStatelessSession();
+Transaction tx = session.beginTransaction();
+
+ScrollableResults customers = session.getNamedQuery("GetCustomers")
+ .scroll(ScrollMode.FORWARD_ONLY);
+while ( customers.next() ) {
+ Customer customer = (Customer) customers.get(0);
+ customer.updateStuff(...);
+ session.update(customer);
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Veja neste exempo, as instancias de <literal>Customer</literal>
retornadas pela query
+ são imediatamente desvinculadas. Elas nunca serão assossiadas à um contexto
persistente.
+ </para>
+
+ <para>
+ As operações <literal>insert(), update()</literal> e
<literal>delete()</literal>
+ definidos pela interface <literal>StatelessSession</literal> são
considerados
+ operações diretas no banco de dados (row-level operations), isso resulta em
uma
+ execução imediata de comandos SQL <literal>INSERT,
UPDATE</literal> ou
+ <literal>DELETE</literal> respectivamente. Devido a isso, eles
possuem uma
+ semântica bem diferente das operações <literal>save(),
saveOrUpdate()</literal>
+ ou <literal>delete()</literal> definidas na interface
<literal>Session</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="batch-direct" revision="3">
+ <title>Operações no estilo DML</title>
+
+ <para>
+ Como já discutido, mapeamento objeto/relacional automático e transparente é
conseguido
+ com a gerência do estado do objeto. Com isto o estado daquele objeto fica
disponível na
+ memória, manipulando(usando as expressões SQL <literal>Data
Manipulation Language</literal>
+ (SQL-style DML): <literal>INSERT</literal>,
<literal>UPDATE</literal>, <literal>DELETE</literal>)
+ os dados diretamente no banco de dados não irá afetar o estado registrado em
memória.
+ Entretanto, o Hibernate provê métodos para executar queries SQL-style DML,
que são
+ totalmente executas com HQL (Hibernate Query Language)
+ (<xref linkend="queryhql">HQL</xref>).
+ </para>
+
+ <para>
+ A pseudo-sintaxe para expressões <literal>UPDATE</literal> e
<literal>DELETE</literal> é:
+ <literal>( UPDATE | DELETE ) FROM? NomeEntidade (WHERE
condições_where)?</literal>.
+ Algumas observações:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Na clausula from, a palavra chave FROM é opcional;
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Somente uma entidade pode ser chamada na clausula from; opcionalmente
pode ter
+ um alias. Se o nome da entidade for possuir um alias, então qualquer
propriedade
+ referenciada deve usar esse alias qualificado; se o nome da entidade
não possuir
+ um alias, então nenhuma das propriedade precisa usar o acesso
qualificado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Na <xref linkend="queryhql-joins-forms">joins</xref>
(ambas implícita ou explicita)
+ pode ser especificada em um bulk HQL query. Sub-queries podem ser usadas na
clausula
+ where; as subqueries podem conter joins.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A clausula where também é opcional.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Como exemplo para executar um HQL <literal>UPDATE</literal>, use
o
+ método <literal>Query.executeUpdate()</literal>(o método ganhou o
nome
+ devido a sua familiaridade com o do JDBC
+ <literal>PreparedStatement.executeUpdate()</literal>):
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+String hqlUpdate = "update Customer c set c.name = :newName where c.name =
:oldName";
+// or String hqlUpdate = "update Customer set name = :newName where name =
:oldName";
+int updatedEntities = s.createQuery( hqlUpdate )
+ .setString( "newName", newName )
+ .setString( "oldName", oldName )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ HQL <literal>UPDATE</literal> statements, by default do not
effect the
+ <xref
linkend="mapping-declaration-version">version</xref>
+ or the <xref
linkend="mapping-declaration-timestamp">timestamp</xref> property
values
+ for the affected entities; this is in keeping with the EJB3 specification.
However,
+ you can force Hibernate to properly reset the
<literal>version</literal> or
+ <literal>timestamp</literal> property values through the use of a
<literal>versioned update</literal>.
+ This is achieved by adding the <literal>VERSIONED</literal>
keyword after the <literal>UPDATE</literal>
+ keyword.
+
+ </para>
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+String hqlVersionedUpdate = "update versioned Customer set name = :newName where
name = :oldName";
+int updatedEntities = s.createQuery( hqlUpdate )
+ .setString( "newName", newName )
+ .setString( "oldName", oldName )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Note that custom version types
(<literal>org.hibernate.usertype.UserVersionType</literal>)
+ are not allowed in conjunction with a <literal>update
versioned</literal> statement.
+ </para>
+
+ <para>
+
+ Para executar um HQL <literal>DELETE</literal>, use o mesmo
método
+ <literal>Query.executeUpdate()</literal>:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+String hqlDelete = "delete Customer c where c.name = :oldName";
+// or String hqlDelete = "delete Customer where name = :oldName";
+int deletedEntities = s.createQuery( hqlDelete )
+ .setString( "oldName", oldName )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ O valor <literal>int</literal> retornado pelo método
<literal>Query.executeUpdate()</literal>
+ indica o numero de entidade afetadas pela operação. Lembre-se que isso pode
estar ou não
+ relacionado ao número de linhas alteradas no banco de dados. Uma operação
bulk HQL pode resultar
+ em várias expressões SQL reais a serem executadas, por exemplo, no caso de
joined-subclass.
+ O número retornado indica a quantidade real de entidades afetadas pela
expressão. Voltando
+ ao exemplo da joined-subclass, a exclusão de uma das subclasses pode resultar
numa
+ exclusão em outra tabelas, não apenas na tabela para qual a subclasses está
mapeada, mas
+ também tabela "root" e possivelmente nas tabelas joined-subclass
num nível hierárquico
+ imediatamente abaixo.
+ </para>
+
+ <para>
+
+ A pseudo-sintaxe para o comando <literal>INSERT</literal> é:
+ <literal>INSERT INTO EntityName properties_list
select_statement</literal>. Alguns
+ pontos a observar:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Apenas a forma INSERT INTO ... SELECT ... é suportada; INSERT INTO
... VALUES ...
+ não é suportada.
+ </para>
+ <para>
+ A lista de propriedade é análoga à <literal>especificação da
coluna</literal>
+ do comando SQL <literal>INSERT</literal>. Para entidades
envolvidas em mapeamentos,
+ apenas a propriedades definidas diretamente a nível da classe podem
ser usandas na
+ properties_list. Propriedades da superclass não são permitidas; e as
propriedades
+ da subclasse não faz sentido. Em outras palavras, os comandos
+ <literal>INSERT</literal> não são polimorficos.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O camando select pode ser qualquer query HQL válida, que tenha um
retorno compatível
+ com o tipo com o esperado pela inclusão. Atualmente, isto é
verificado durante a compilação
+ da query, isto é melhor do que permitir que a verificação chegue ao
banco de dados.
+ Entretanto perceba que isso pode causar problemas entre os
<literal>Tipo</literal> do Hibernate
+ que são <emphasis>equivalentes</emphasis> em oposição a
<emphasis>equal</emphasis>.
+ Isso pode causar problemas nas combinações entre a propriedade
definida como
+ <literal>org.hibernate.type.DateType</literal>e um
propriedade definida como
+ <literal>org.hibernate.type.TimestampType</literal>,
embora o banco de dados não possa
+ fazer uma distinção ou possa ser capaz de manusear a conversão.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Para a propriedade id, a expressão insert oferece duas opções. Você
pode especificar
+ qualquer propriedade id explicitamente no properties_list (em alguns
casos esse valor
+ é obtido diretamente da expressão select) ou pode omitir do
properties_list (nesse caso,
+ um valor gerado é usado). Essa ultima opção só é válida quando são
usados geradores de ids
+ que operam no banco de dados; a tentativa de usar essa opção com
geradores do tipo
+ "em memória" vai causar um exceção durante a etapa de
parser. Veja a finalidades desta
+ discussão, os seguintes geradores operam com o banco de dados
+ <literal>org.hibernate.id.SequenceGenerator</literal> (e
suas subclasses)
+ e qualquer implementação de
<literal>org.hibernate.id.PostInsertIdentifierGenerator</literal>.
+ Aqui, a exceção mais notável é o
<literal>org.hibernate.id.TableHiLoGenerator</literal>, que
+ não pode ser usado porque ele não dispõe de mecanismos para recuperar
o seu valor.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ For properties mapped as either
<literal>version</literal> or <literal>timestamp</literal>,
+ the insert statement gives you two options. You can either specify
the property in the
+ properties_list (in which case its value is taken from the
corresponding select expressions)
+ or omit it from the properties_list (in which case the
<literal>seed value</literal> defined
+ by the <literal>org.hibernate.type.VersionType</literal>
is used).
+
+ Para propriedades mapeadas como
<literal>version</literal> ou <literal>timestamp</literal>,
+ a expressão insert oferece a você duas opções. Você pode especificar
a propriedade na
+ properties_list (nesse caso o seu valor é obtido a partir da
expressão select correspondente)
+ ou ele pode ser omitido da properties_list (neste caso o usa o
<literal>valor semente</literal>
+ definido pela classe
<literal>org.hibernate.type.VersionType</literal>).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Exemplo da execução de um HQL <literal>INSERT</literal>:
+ </para>
+
+<programlisting><![CDATA[Session session = sessionFactory.openSession();
+Transaction tx = session.beginTransaction();
+
+String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name
from Customer c where ...";
+int createdEntities = s.createQuery( hqlInsert )
+ .executeUpdate();
+tx.commit();
+session.close();]]></programlisting>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/batch.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/best_practices.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/best_practices.xml 2006-08-14 14:43:45
UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/best_practices.xml 2006-08-14 14:55:10
UTC (rev 10262)
@@ -0,0 +1,225 @@
+<chapter id="best-practices" revision="3">
+ <title>Boas práticas</title>
+
+ <variablelist spacing="compact">
+ <varlistentry>
+ <term>Escreva classes compactas e mapeie-as usando
<literal><component></literal>.</term>
+ <listitem>
+ <para>
+ Use uma classe <literal>Endereco</literal> para
encapsular <literal>rua</literal>,
+ <literal>bairro</literal>,
<literal>estado</literal>, <literal>CEP</literal>. Isto promove
+ a reutilização de código e simplifica o refactoring.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Declare propriedades identificadoras em classes
persistentes.</term>
+ <listitem>
+ <para>
+ O Hibernate constrói propriedades identificadoras opcionais. Existem
todos os tipos
+ de razões que explicam porquê você deveria utilizá-las. Nós
recomendamos que os
+ identificadores sejam 'sintéticos' (gerados, sem significado
para o negocio).
+
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Identifique chaves naturais.</term>
+ <listitem>
+ <para>
+ Identifique chaves naturais para todas as entidades, e mapeie-as
usando
+ <literal><natural-id></literal>. Implemente
<literal>equals()</literal> e
+ <literal>hashCode()</literal> para comparar as
propriedades que compõem a chave natural.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Coloque cada classe de mapeamento em seu próprio
arquivo.</term>
+ <listitem>
+ <para>
+ Não use um único código de mapeamento monolítico. Mapeie
<literal>com.eg.Foo</literal>
+ no arquivo <literal>com/eg/Foo.hbm.xml</literal>. Isto
promove particularmente o bom
+ senso no time de desenvolvimento.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Carregue os mapeamentos como recursos.</term>
+ <listitem>
+ <para>
+ Faça o deploy dos mapeamentos junto com as classes que eles mapeiam.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Considere externalizar as strings de consultas.</term>
+ <listitem>
+ <para>
+ Esta é uma boa prática se suas consultas chamam funções SQL que não
sejam ANSI.
+ Externalizar as strings de consultas para mapear arquivos irão tornar
a aplicação
+ mais portável.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Use bind variables.</term>
+ <listitem>
+ <para>
+ Assim como em JDBC, sempre substitua valores não constantes por
"?". Nunca use a manipulação
+ de strings para concatenar valores não constantes em uma consulta!
Até melhor, considere
+ usar parâmetros nomeados nas consultas.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Não gerencie suas conexões JDBC.</term>
+ <listitem>
+ <para>
+ O Hibernate permite que a aplicação gerencie conexões JDBC. Esta
abordagem deve ser considerada
+ um último recurso. Se você não pode usar os provedores de conexão
embutidos, considere fazer
+ sua implementação a partir de
<literal>org.hibernate.connection.ConnectionProvider</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Considere usar tipos customizados.</term>
+ <listitem>
+ <para>
+ Suponha que você tenha um tipo Java, de alguma biblioteca, que
precisa ser persistido mas não
+ provê os acessórios necessários para mapeá-lo como um componente.
Você deve implementar
+ <literal>org.hibernate.UserType</literal>. Esta abordagem
livra o código da aplicação de
+ implementar transformações de/para o tipo Hibernate.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term> Use código manual JDBC nos gargalos.</term>
+ <listitem>
+ <para>
+ Nas áreas de desempenho crítico do sistema, alguns tipos de operações
podem se beneficiar do
+ uso direto do JDBC. Mas por favor, espere até você
<emphasis>saber </emphasis> se é um gargalo.
+ E não suponha que o uso direto do JDBC é necessariamente mais rápido.
Se você precisar usar
+ diretamente o JDBC, vale a pena abrir uma
<literal>Session</literal> do Hibernate e usar uma
+ conexão JDBC. De modo que você possa ainda usar a mesma estratégia de
transação e ocultar
+ o provedor a conexão
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Entenda o <literal>Session</literal>
flushing.</term>
+ <listitem>
+ <para>
+ De tempos em tempos a sessão sincroniza seu estado persistente com o
banco de dados. O desempenho
+ será afetado se este processo ocorrer frequentemente. Você pode
algumas vezes minimizar o fluxo
+ desnecessário desabilitando o fluxo automático ou até mesmo mudando a
ordem das consultas e outras
+ operações em uma transação particular.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Em uma arquitetura de três camadas, considere o uso de objetos
separados.</term>
+ <listitem>
+ <para>
+ When using a servlet / session bean architecture, you could pass
persistent objects loaded in
+ the session bean to and from the servlet / JSP layer. Use a new
session to service each request.
+ Use <literal>Session.merge()</literal> or
<literal>Session.saveOrUpdate()</literal> to
+ synchronize objects with the database.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>In a two tiered architecture, consider using long persistence
contexts.</term>
+ <listitem>
+ <para>
+ Database Transactions have to be as short as possible for best
scalability. However, it is often
+ neccessary to implement long running <emphasis>application
transactions</emphasis>, a single
+ unit-of-work from the point of view of a user. An application
transaction might span several
+ client request/response cycles. It is common to use detached objects
to implement application
+ transactions. An alternative, extremely appropriate in two tiered
architecture, is to maintain
+ a single open persistence contact (session) for the whole lifecycle
of the application transaction
+ and simply disconnect from the JDBC connection at the end of each
request and reconnect at the
+ beginning of the subsequent request. Never share a single session
across more than one application
+ transaction, or you will be working with stale data.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Don't treat exceptions as recoverable.</term>
+ <listitem>
+ <para>
+ This is more of a necessary practice than a "best"
practice. When an exception occurs, roll back
+ the <literal>Transaction</literal> and close the
<literal>Session</literal>. If you don't, Hibernate
+ can't guarantee that in-memory state accurately represents
persistent state. As a special case of this,
+ do not use <literal>Session.load()</literal> to determine
if an instance with the given identifier
+ exists on the database; use
<literal>Session.get()</literal> or a query instead.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Prefer lazy fetching for associations.</term>
+ <listitem>
+ <para>
+ Use eager fetching sparingly. Use proxies and lazy collections for
most associations to classes that
+ are not likely to be completely held in the second-level cache. For
associations to cached classes,
+ where there is an a extremely high probability of a cache hit,
explicitly disable eager fetching using
+ <literal>lazy="false"</literal>. When an join
fetching is appropriate to a particular use
+ case, use a query with a <literal>left join
fetch</literal>.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ Use the <emphasis>open session in view</emphasis> pattern, or
a disciplined
+ <emphasis>assembly phase</emphasis> to avoid problems with
unfetched data.
+ </term>
+ <listitem>
+ <para>
+ Hibernate frees the developer from writing tedious
<emphasis>Data Transfer Objects</emphasis> (DTO).
+ In a traditional EJB architecture, DTOs serve dual purposes: first,
they work around the problem
+ that entity beans are not serializable; second, they implicitly
define an assembly phase where
+ all data to be used by the view is fetched and marshalled into the
DTOs before returning control
+ to the presentation tier. Hibernate eliminates the first purpose.
However, you will still need
+ an assembly phase (think of your business methods as having a strict
contract with the presentation
+ tier about what data is available in the detached objects) unless you
are prepared to hold the
+ persistence context (the session) open across the view rendering
process. This is not a limitation
+ of Hibernate! It is a fundamental requirement of safe transactional
data access.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Consider abstracting your business logic from
Hibernate.</term>
+ <listitem>
+ <para>
+ Hide (Hibernate) data-access code behind an interface. Combine the
<emphasis>DAO</emphasis> and
+ <emphasis>Thread Local Session</emphasis> patterns. You
can even have some classes persisted by
+ handcoded JDBC, associated to Hibernate via a
<literal>UserType</literal>. (This advice is
+ intended for "sufficiently large" applications; it is not
appropriate for an application with
+ five tables!)
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Don't use exotic association mappings.</term>
+ <listitem>
+ <para>
+ Good usecases for a real many-to-many associations are rare. Most of
the time you need
+ additional information stored in the "link table". In this
case, it is much better to
+ use two one-to-many associations to an intermediate link class. In
fact, we think that
+ most associations are one-to-many and many-to-one, you should be
careful when using any
+ other association style and ask yourself if it is really neccessary.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Prefer bidirectional associations.</term>
+ <listitem>
+ <para>
+ Unidirectional associations are more difficult to query. In a large
application, almost
+ all associations must be navigable in both directions in queries.
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/best_practices.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/collection_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/collection_mapping.xml 2006-08-14
14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/collection_mapping.xml 2006-08-14
14:55:10 UTC (rev 10262)
@@ -0,0 +1,1238 @@
+<chapter id="collections">
+ <title>Mapeamento de Coleções</title>
+
+ <sect1 id="collections-persistent" revision="3">
+ <title>Persistent collections</title>
+
+ <para>
+ Hibernate requires that persistent collection-valued fields be declared
+ as an interface type, for example:
+ </para>
+
+ <programlisting><![CDATA[public class Product {
+ private String serialNumber;
+ private Set parts = new HashSet();
+
+ public Set getParts() { return parts; }
+ void setParts(Set parts) { this.parts = parts; }
+ public String getSerialNumber() { return serialNumber; }
+ void setSerialNumber(String sn) { serialNumber = sn; }
+}]]></programlisting>
+
+ <para>
+ The actual interface might be <literal>java.util.Set</literal>,
+ <literal>java.util.Collection</literal>,
<literal>java.util.List</literal>,
+ <literal>java.util.Map</literal>,
<literal>java.util.SortedSet</literal>,
+ <literal>java.util.SortedMap</literal> or ... anything you like!
(Where
+ "anything you like" means you will have to write an implementation
of
+ <literal>org.hibernate.usertype.UserCollectionType</literal>.)
+ </para>
+
+ <para>
+ Notice how we initialized the instance variable with an instance of
+ <literal>HashSet</literal>. This is the best way to initialize
collection
+ valued properties of newly instantiated (non-persistent) instances. When
+ you make the instance persistent - by calling
<literal>persist()</literal>,
+ for example - Hibernate will actually replace the
<literal>HashSet</literal>
+ with an instance of Hibernate's own implementation of
<literal>Set</literal>.
+ Watch out for errors like this:
+ </para>
+
+ <programlisting><![CDATA[Cat cat = new DomesticCat();
+Cat kitten = new DomesticCat();
+....
+Set kittens = new HashSet();
+kittens.add(kitten);
+cat.setKittens(kittens);
+session.persist(cat);
+kittens = cat.getKittens(); // Okay, kittens collection is a Set
+(HashSet) cat.getKittens(); // Error!]]></programlisting>
+
+ <para>
+ The persistent collections injected by Hibernate behave like
+ <literal>HashMap</literal>,
<literal>HashSet</literal>,
+ <literal>TreeMap</literal>,
<literal>TreeSet</literal> or
+ <literal>ArrayList</literal>, depending upon the interface type.
+ </para>
+
+ <para>
+ Collections instances have the usual behavior of value types. They are
+ automatically persisted when referenced by a persistent object and
+ automatically deleted when unreferenced. If a collection is passed from one
+ persistent object to another, its elements might be moved from one table to
+ another. Two entities may not share a reference to the same collection
+ instance. Due to the underlying relational model, collection-valued
properties
+ do not support null value semantics; Hibernate does not distinguish between
+ a null collection reference and an empty collection.
+ </para>
+
+ <para>
+ You shouldn't have to worry much about any of this. Use persistent
collections
+ the same way you use ordinary Java collections. Just make sure you understand
+ the semantics of bidirectional associations (discussed later).
+ </para>
+
+ </sect1>
+
+ <sect1 id="collections-mapping" revision="4">
+ <title>Collection mappings</title>
+
+ <para>
+ The Hibernate mapping element used for mapping a collection depends upon
+ the type of the interface. For example, a
<literal><set></literal>
+ element is used for mapping properties of type
<literal>Set</literal>.
+ </para>
+
+ <programlisting><![CDATA[<class name="Product">
+ <id name="serialNumber" column="productSerialNumber"/>
+ <set name="parts">
+ <key column="productSerialNumber" not-null="true"/>
+ <one-to-many class="Part"/>
+ </set>
+</class>]]></programlisting>
+
+ <para>
+ Apart from <literal><set></literal>, there is also
+ <literal><list></literal>,
<literal><map></literal>,
+ <literal><bag></literal>,
<literal><array></literal> and
+ <literal><primitive-array></literal> mapping
elements. The
+ <literal><map></literal> element is
representative:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="mappingcollection1" coords="2 65"/>
+ <area id="mappingcollection2" coords="3 65"/>
+ <area id="mappingcollection3" coords="4 65"/>
+ <area id="mappingcollection4" coords="5 65"/>
+ <area id="mappingcollection5" coords="6 65"/>
+ <area id="mappingcollection6" coords="7 65"/>
+ <area id="mappingcollection7" coords="8 65"/>
+ <area id="mappingcollection8" coords="9 65"/>
+ <area id="mappingcollection9" coords="10 65"/>
+ <area id="mappingcollection10" coords="11
65"/>
+ <area id="mappingcollection11" coords="12
65"/>
+ <area id="mappingcollection12" coords="13
65"/>
+ <area id="mappingcollection13" coords="14
65"/>
+ <area id="mappingcollection14" coords="15
65"/>
+ </areaspec>
+ <programlisting><![CDATA[<map
+ name="propertyName"
+ table="table_name"
+ schema="schema_name"
+ lazy="true|extra|false"
+ inverse="true|false"
+ cascade="all|none|save-update|delete|all-delete-orphan|delete-orphan"
+ sort="unsorted|natural|comparatorClass"
+ order-by="column_name asc|desc"
+ where="arbitrary sql where condition"
+ fetch="join|select|subselect"
+ batch-size="N"
+ access="field|property|ClassName"
+ optimistic-lock="true|false"
+ mutable="true|false"
+ node="element-name|."
+ embed-xml="true|false"
+>
+
+ <key .... />
+ <map-key .... />
+ <element .... />
+</map>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="mappingcollection1">
+ <para>
+ <literal>name</literal> the collection property name
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection2">
+ <para>
+ <literal>table</literal> (optional - defaults to
property name) the
+ name of the collection table (not used for one-to-many
associations)
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection3">
+ <para>
+ <literal>schema</literal> (optional) the name of a
table schema to
+ override the schema declared on the root element
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection4">
+ <para>
+ <literal>lazy</literal> (optional - defaults to
<literal>true</literal>)
+ may be used to disable lazy fetching and specify that the
association is
+ always eagerly fetched, or to enable "extra-lazy"
fetching where most
+ operations do not initialize the collection (suitable for very
large
+ collections)
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection5">
+ <para>
+ <literal>inverse</literal> (optional - defaults to
<literal>false</literal>)
+ mark this collection as the "inverse" end of a
bidirectional association
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection6">
+ <para>
+ <literal>cascade</literal> (optional - defaults to
<literal>none</literal>)
+ enable operations to cascade to child entities
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection7">
+ <para>
+ <literal>sort</literal> (optional) specify a sorted
collection with
+ <literal>natural</literal> sort order, or a given
comparator class
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection8">
+ <para>
+ <literal>order-by</literal> (optional, JDK1.4 only)
specify a table column (or columns)
+ that define the iteration order of the
<literal>Map</literal>, <literal>Set</literal>
+ or bag, together with an optional
<literal>asc</literal> or <literal>desc</literal>
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection9">
+ <para>
+ <literal>where</literal> (optional) specify an
arbitrary SQL <literal>WHERE</literal>
+ condition to be used when retrieving or removing the collection
(useful if the
+ collection should contain only a subset of the available data)
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection10">
+ <para>
+ <literal>fetch</literal> (optional, defaults to
<literal>select</literal>) Choose
+ between outer-join fetching, fetching by sequential select, and
fetching by sequential
+ subselect.
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection11">
+ <para>
+ <literal>batch-size</literal> (optional, defaults to
<literal>1</literal>) specify a
+ "batch size" for lazily fetching instances of this
collection.
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection12">
+ <para>
+ <literal>access</literal> (optional - defaults to
<literal>property</literal>): The
+ strategy Hibernate should use for accessing the collection
property value.
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection13">
+ <para>
+ <literal>optimistic-lock</literal> (optional -
defaults to <literal>true</literal>):
+ Species that changes to the state of the collection results in
increment of the
+ owning entity's version. (For one to many associations, it is
often reasonable to
+ disable this setting.)
+ </para>
+ </callout>
+ <callout arearefs="mappingcollection14">
+ <para>
+ <literal>mutable</literal> (optional - defaults to
<literal>true</literal>):
+ A value of <literal>false</literal> specifies that
the elements of the
+ collection never change (a minor performance optimization in some
cases).
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <sect2 id="collections-foreignkeys" >
+ <title>Collection foreign keys</title>
+
+ <para>
+ Collection instances are distinguished in the database by the foreign key
of
+ the entity that owns the collection. This foreign key is referred to as
the
+ <emphasis>collection key column</emphasis> (or columns) of
the collection
+ table. The collection key column is mapped by the
<literal><key></literal>
+ element.
+ </para>
+
+ <para>
+ There may be a nullability constraint on the foreign key column. For
most
+ collections, this is implied. For unidirectional one to many
associations,
+ the foreign key column is nullable by default, so you might need to
specify
+ <literal>not-null="true"</literal>.
+ </para>
+
+ <programlisting><![CDATA[<key
column="productSerialNumber"
not-null="true"/>]]></programlisting>
+
+ <para>
+ The foreign key constraint may use <literal>ON DELETE
CASCADE</literal>.
+ </para>
+
+ <programlisting><![CDATA[<key
column="productSerialNumber"
on-delete="cascade"/>]]></programlisting>
+
+ <para>
+ See the previous chapter for a full definition of the
<literal><key></literal>
+ element.
+ </para>
+
+ </sect2>
+
+ <sect2 id="collections-elements" >
+ <title>Collection elements</title>
+
+ <para>
+ Collections may contain almost any other Hibernate type, including all
basic types,
+ custom types, components, and of course, references to other entities.
This is an
+ important distinction: an object in a collection might be handled with
"value"
+ semantics (its lifecycle fully depends on the collection owner) or it
might be a
+ reference to another entity, with its own lifecycle. In the latter case,
only the
+ "link" between the two objects is considered to be state held
by the collection.
+ </para>
+
+ <para>
+ The contained type is referred to as the <emphasis>collection
element type</emphasis>.
+ Collection elements are mapped by
<literal><element></literal> or
+ <literal><composite-element></literal>, or in
the case of entity references,
+ with <literal><one-to-many></literal> or
<literal><many-to-many></literal>.
+ The first two map elements with value semantics, the next two are used to
map entity
+ associations.
+ </para>
+
+ </sect2>
+
+ <sect2 id="collections-indexed">
+ <title>Indexed collections</title>
+
+ <para>
+ All collection mappings, except those with set and bag semantics, need
an
+ <emphasis>index column</emphasis> in the collection table - a
column that maps to an
+ array index, or <literal>List</literal> index, or
<literal>Map</literal> key. The
+ index of a <literal>Map</literal> may be of any basic type,
mapped with
+ <literal><map-key></literal>, it may be an
entity reference mapped with
+ <literal><map-key-many-to-many></literal>, or
it may be a composite type,
+ mapped with
<literal><composite-map-key></literal>. The index of an array or
+ list is always of type <literal>integer</literal> and is
mapped using the
+ <literal><list-index></literal> element. The
mapped column contains
+ sequential integers (numbered from zero, by default).
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="index1" coords="2 45"/>
+ <area id="index2" coords="3 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<list-index
+ column="column_name"
+ base="0|1|..."/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="index1">
+ <para>
+ <literal>column_name</literal> (required): The name
of the column holding the
+ collection index values.
+ </para>
+ </callout>
+ <callout arearefs="index1">
+ <para>
+ <literal>base</literal> (optional, defaults to
<literal>0</literal>): The value
+ of the index column that corresponds to the first element of the
list or array.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <programlistingco>
+ <areaspec>
+ <area id="mapkey1" coords="2 45"/>
+ <area id="mapkey2" coords="3 45"/>
+ <area id="mapkey3" coords="4 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<map-key
+ column="column_name"
+ formula="any SQL expression"
+ type="type_name"
+ node="@attribute-name"
+ length="N"/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="mapkey1">
+ <para>
+ <literal>column</literal> (optional): The name of the
column holding the
+ collection index values.
+ </para>
+ </callout>
+ <callout arearefs="mapkey2">
+ <para>
+ <literal>formula</literal> (optional): A SQL formula
used to evaluate the
+ key of the map.
+ </para>
+ </callout>
+ <callout arearefs="mapkey3">
+ <para>
+ <literal>type</literal> (reguired): The type of the
map keys.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <programlistingco>
+ <areaspec>
+ <area id="indexmanytomany1" coords="2 45"/>
+ <area id="indexmanytomany2" coords="3 45"/>
+ <area id="indexmanytomany3" coords="3 45"/>
+ </areaspec>
+ <programlisting><![CDATA[<map-key-many-to-many
+ column="column_name"
+ formula="any SQL expression"
+ class="ClassName"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="indexmanytomany1">
+ <para>
+ <literal>column</literal> (optional): The name of the
foreign key
+ column for the collection index values.
+ </para>
+ </callout>
+ <callout arearefs="indexmanytomany2">
+ <para>
+ <literal>formula</literal> (optional): A SQL formula
used to evaluate the
+ foreign key of the map key.
+ </para>
+ </callout>
+ <callout arearefs="indexmanytomany3">
+ <para>
+ <literal>class</literal> (required): The entity class
used as the map key.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+
+ <para>
+ If your table doesn't have an index column, and you still wish to use
<literal>List</literal>
+ as the property type, you should map the property as a Hibernate
<emphasis><bag></emphasis>.
+ A bag does not retain its order when it is retrieved from the database,
but it may be
+ optionally sorted or ordered.
+ </para>
+
+ </sect2>
+
+ <para>
+ There are quite a range of mappings that can be generated for collections,
covering
+ many common relational models. We suggest you experiment with the schema
generation tool
+ to get a feeling for how various mapping declarations translate to database
tables.
+ </para>
+
+ <sect2 id="collections-ofvalues" revision="2">
+ <title>Collections of values and many-to-many associations</title>
+
+ <para>
+ Any collection of values or many-to-many association requires a dedicated
+ <emphasis>collection table</emphasis> with a foreign key column
or columns,
+ <emphasis>collection element column</emphasis> or columns and
possibly
+ an index column or columns.
+ </para>
+
+ <para>
+ For a collection of values, we use the
<literal><element></literal> tag.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="element1b" coords="2 50"/>
+ <area id="element2b" coords="3 50"/>
+ <area id="element3b" coords="4 50"/>
+ </areaspec>
+ <programlisting><![CDATA[<element
+ column="column_name"
+ formula="any SQL expression"
+ type="typename"
+ length="L"
+ precision="P"
+ scale="S"
+ not-null="true|false"
+ unique="true|false"
+ node="element-name"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="element1b">
+ <para>
+ <literal>column</literal> (optional): The name of the
column holding the
+ collection element values.
+ </para>
+ </callout>
+ <callout arearefs="element2b">
+ <para>
+ <literal>formula</literal> (optional): An SQL formula
used to evaluate the
+ element.
+ </para>
+ </callout>
+ <callout arearefs="element3b">
+ <para>
+ <literal>type</literal> (required): The type of the
collection element.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ A <emphasis>many-to-many association</emphasis> is specified
using the
+ <literal><many-to-many></literal> element.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="manytomany1" coords="2 60"/>
+ <area id="manytomany2" coords="3 60"/>
+ <area id="manytomany3" coords="4 60"/>
+ <area id="manytomany4" coords="5 60"/>
+ <area id="manytomany5" coords="6 60"/>
+ <area id="manytomany6" coords="7 60"/>
+ <area id="manytomany7" coords="8 60"/>
+ <area id="manytomany8" coords="9 60"/>
+ </areaspec>
+ <programlisting><![CDATA[<many-to-many
+ column="column_name"
+ formula="any SQL expression"
+ class="ClassName"
+ fetch="select|join"
+ unique="true|false"
+ not-found="ignore|exception"
+ entity-name="EntityName"
+ property-ref="propertyNameFromAssociatedClass"
+ node="element-name"
+ embed-xml="true|false"
+ />]]></programlisting>
+ <calloutlist>
+ <callout arearefs="manytomany1">
+ <para>
+ <literal>column</literal> (optional): The name of the
element foreign key column.
+ </para>
+ </callout>
+ <callout arearefs="manytomany2">
+ <para>
+ <literal>formula</literal> (optional): An SQL formula
used to evaluate the element
+ foreign key value.
+ </para>
+ </callout>
+ <callout arearefs="manytomany3">
+ <para>
+ <literal>class</literal> (required): The name of the
associated class.
+ </para>
+ </callout>
+ <callout arearefs="manytomany4">
+ <para>
+ <literal>fetch</literal> (optional - defaults to
<literal>join</literal>):
+ enables outer-join or sequential select fetching for this
association. This
+ is a special case; for full eager fetching (in a single
<literal>SELECT</literal>)
+ of an entity and its many-to-many relationships to other
entities, you would
+ enable <literal>join</literal> fetching not only of
the collection itself,
+ but also with this attribute on the
<literal><many-to-many></literal>
+ nested element.
+ </para>
+ </callout>
+ <callout arearefs="manytomany5">
+ <para>
+ <literal>unique</literal> (optional): Enable the DDL
generation of a unique
+ constraint for the foreign-key column. This makes the association
multiplicity
+ effectively one to many.
+ </para>
+ </callout>
+ <callout arearefs="manytomany6">
+ <para>
+ <literal>not-found</literal> (optional - defaults to
<literal>exception</literal>):
+ Specifies how foreign keys that reference missing rows will be
handled:
+ <literal>ignore</literal> will treat a missing row as a
null association.
+ </para>
+ </callout>
+ <callout arearefs="manytomany7">
+ <para>
+ <literal>entity-name</literal> (optional): The entity
name of the associated class,
+ as an alternative to <literal>class</literal>.
+ </para>
+ </callout>
+ <callout arearefs="manytomany8">
+ <para>
+ <literal>property-ref</literal>: (optional) The name
of a property of the associated
+ class that is joined to this foreign key. If not specified, the
primary key of
+ the associated class is used.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Some examples, first, a set of strings:
+ </para>
+
+ <programlisting><![CDATA[<set name="names"
table="person_names">
+ <key column="person_id"/>
+ <element column="person_name" type="string"/>
+</set>]]></programlisting>
+
+ <para>
+ A bag containing integers (with an iteration order determined by the
+ <literal>order-by</literal> attribute):
+ </para>
+
+ <programlisting><![CDATA[<bag name="sizes"
+ table="item_sizes"
+ order-by="size asc">
+ <key column="item_id"/>
+ <element column="size" type="integer"/>
+</bag>]]></programlisting>
+
+ <para>
+ An array of entities - in this case, a many to many association:
+ </para>
+
+ <programlisting><![CDATA[<array name="addresses"
+ table="PersonAddress"
+ cascade="persist">
+ <key column="personId"/>
+ <list-index column="sortOrder"/>
+ <many-to-many column="addressId" class="Address"/>
+</array>]]></programlisting>
+
+ <para>
+ A map from string indices to dates:
+ </para>
+
+ <programlisting><![CDATA[<map name="holidays"
+ table="holidays"
+ schema="dbo"
+ order-by="hol_name asc">
+ <key column="id"/>
+ <map-key column="hol_name" type="string"/>
+ <element column="hol_date" type="date"/>
+</map>]]></programlisting>
+
+ <para>
+ A list of components (discussed in the next chapter):
+ </para>
+
+ <programlisting><![CDATA[<list name="carComponents"
+ table="CarComponents">
+ <key column="carId"/>
+ <list-index column="sortOrder"/>
+ <composite-element class="CarComponent">
+ <property name="price"/>
+ <property name="type"/>
+ <property name="serialNumber" column="serialNum"/>
+ </composite-element>
+</list>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="collections-onetomany">
+ <title>One-to-many associations</title>
+
+ <para>
+ A <emphasis>one to many association</emphasis> links the tables
of two classes
+ via a foreign key, with no intervening collection table. This mapping loses
+ certain semantics of normal Java collections:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ An instance of the contained entity class may not belong to more
than
+ one instance of the collection
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ An instance of the contained entity class may not appear at more
than
+ one value of the collection index
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ An association from <literal>Product</literal> to
<literal>Part</literal> requires
+ existence of a foreign key column and possibly an index column to the
<literal>Part</literal>
+ table. A <literal><one-to-many></literal> tag
indicates that this is a one to many
+ association.
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="onetomany1" coords="2 60"/>
+ <area id="onetomany2" coords="3 60"/>
+ <area id="onetomany3" coords="4 60"/>
+ </areaspec>
+ <programlisting><![CDATA[<one-to-many
+ class="ClassName"
+ not-found="ignore|exception"
+ entity-name="EntityName"
+ node="element-name"
+ embed-xml="true|false"
+ />]]></programlisting>
+ <calloutlist>
+ <callout arearefs="onetomany1">
+ <para>
+ <literal>class</literal> (required): The name of the
associated class.
+ </para>
+ </callout>
+ <callout arearefs="onetomany2">
+ <para>
+ <literal>not-found</literal> (optional - defaults to
<literal>exception</literal>):
+ Specifies how cached identifiers that reference missing rows will be
handled:
+ <literal>ignore</literal> will treat a missing row as a
null association.
+ </para>
+ </callout>
+ <callout arearefs="onetomany3">
+ <para>
+ <literal>entity-name</literal> (optional): The entity
name of the associated class,
+ as an alternative to <literal>class</literal>.
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Notice that the <literal><one-to-many></literal>
element does not need to
+ declare any columns. Nor is it necessary to specify the
<literal>table</literal>
+ name anywhere.
+ </para>
+
+ <para>
+ <emphasis>Very important note:</emphasis> If the foreign key
column of a
+ <literal><one-to-many></literal> association is
declared <literal>NOT NULL</literal>,
+ you must declare the <literal><key></literal>
mapping
+ <literal>not-null="true"</literal> or
<emphasis>use a bidirectional association</emphasis>
+ with the collection mapping marked
<literal>inverse="true"</literal>. See the discussion
+ of bidirectional associations later in this chapter.
+ </para>
+
+ <para>
+ This example shows a map of <literal>Part</literal> entities by
name (where
+ <literal>partName</literal> is a persistent property of
<literal>Part</literal>).
+ Notice the use of a formula-based index.
+ </para>
+
+ <programlisting><![CDATA[<map name="parts"
+ cascade="all">
+ <key column="productId" not-null="true"/>
+ <map-key formula="partName"/>
+ <one-to-many class="Part"/>
+</map>]]></programlisting>
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="collections-advancedmappings">
+ <title>Advanced collection mappings</title>
+
+ <sect2 id="collections-sorted" revision="2">
+ <title>Sorted collections</title>
+
+ <para>
+ Hibernate supports collections implementing
<literal>java.util.SortedMap</literal> and
+ <literal>java.util.SortedSet</literal>. You must specify a
comparator in the mapping file:
+ </para>
+
+ <programlisting><![CDATA[<set name="aliases"
+ table="person_aliases"
+ sort="natural">
+ <key column="person"/>
+ <element column="name" type="string"/>
+</set>
+
+<map name="holidays" sort="my.custom.HolidayComparator">
+ <key column="year_id"/>
+ <map-key column="hol_name" type="string"/>
+ <element column="hol_date" type="date"/>
+</map>]]></programlisting>
+
+ <para>
+ Allowed values of the <literal>sort</literal> attribute are
<literal>unsorted</literal>,
+ <literal>natural</literal> and the name of a class implementing
+ <literal>java.util.Comparator</literal>.
+ </para>
+
+ <para>
+ Sorted collections actually behave like
<literal>java.util.TreeSet</literal> or
+ <literal>java.util.TreeMap</literal>.
+ </para>
+
+ <para>
+ If you want the database itself to order the collection elements use the
+ <literal>order-by</literal> attribute of
<literal>set</literal>, <literal>bag</literal>
+ or <literal>map</literal> mappings. This solution is only
available under
+ JDK 1.4 or higher (it is implemented using
<literal>LinkedHashSet</literal> or
+ <literal>LinkedHashMap</literal>). This performs the ordering in
the SQL query,
+ not in memory.
+ </para>
+
+ <programlisting><![CDATA[<set name="aliases"
table="person_aliases" order-by="lower(name) asc">
+ <key column="person"/>
+ <element column="name" type="string"/>
+</set>
+
+<map name="holidays" order-by="hol_date, hol_name">
+ <key column="year_id"/>
+ <map-key column="hol_name" type="string"/>
+ <element column="hol_date type="date"/>
+</map>]]></programlisting>
+
+ <para>
+ Note that the value of the <literal>order-by</literal> attribute
is an SQL ordering, not
+ a HQL ordering!
+ </para>
+
+ <para>
+ Associations may even be sorted by some arbitrary criteria at runtime using a
collection
+ <literal>filter()</literal>.
+ </para>
+
+ <programlisting><![CDATA[sortedUsers = s.createFilter( group.getUsers(),
"order by this.name" ).list();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="collections-bidirectional" revision="1">
+ <title>Bidirectional associations</title>
+
+ <para>
+ A <emphasis>bidirectional association</emphasis> allows
navigation from both
+ "ends" of the association. Two kinds of bidirectional association
are
+ supported:
+
+ <variablelist>
+ <varlistentry>
+ <term>one-to-many</term>
+ <listitem>
+ <para>
+ set or bag valued at one end, single-valued at the other
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>many-to-many</term>
+ <listitem>
+ <para>
+ set or bag valued at both ends
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </para>
+
+ <para>
+ You may specify a bidirectional many-to-many association simply by mapping
two
+ many-to-many associations to the same database table and declaring one end
as
+ <emphasis>inverse</emphasis> (which one is your choice, but it
can not be an
+ indexed collection).
+ </para>
+
+ <para>
+ Here's an example of a bidirectional many-to-many association; each
category can
+ have many items and each item can be in many categories:
+ </para>
+
+ <programlisting><![CDATA[<class name="Category">
+ <id name="id" column="CATEGORY_ID"/>
+ ...
+ <bag name="items" table="CATEGORY_ITEM">
+ <key column="CATEGORY_ID"/>
+ <many-to-many class="Item" column="ITEM_ID"/>
+ </bag>
+</class>
+
+<class name="Item">
+ <id name="id" column="CATEGORY_ID"/>
+ ...
+
+ <!-- inverse end -->
+ <bag name="categories" table="CATEGORY_ITEM"
inverse="true">
+ <key column="ITEM_ID"/>
+ <many-to-many class="Category" column="CATEGORY_ID"/>
+ </bag>
+</class>]]></programlisting>
+
+ <para>
+ As mudanças feitas somente de um lado da associação
<emphasis>não</emphasis> são
+ persistidas. Isto significa que o Hibernate tem duas representações na
memória
+ para cada associação bidirecional, uma associação de A para B e uma outra
+ associação de B para A. Isto é mais fácil de compreender se você pensa
+ sobre o modelo do objetos do Java e como nós criamos um relacionamento muitos
+ para muitos em Java:
+ </para>
+
+ <programlisting><![CDATA[
+category.getItems().add(item); // The category now "knows" about the
relationship
+item.getCategories().add(category); // The item now "knows" about the
relationship
+
+session.persist(item); // The relationship won't be saved!
+session.persist(category); // The relationship will be
saved]]></programlisting>
+
+ <para>
+ A outra ponta é usada salvar a representação em memória à base de dados.
+ </para>
+
+ <para>
+ Você pode definir uma associação bidirecional um para muitos através de uma
associação
+ um-para-muitos indicando as mesmas colunas da tabela que à associação
muitos-para-um e
+ declarando a propriedade
<literal>inverse="true"</literal>
+
+ </para>
+
+ <programlisting><![CDATA[<class name="Parent">
+ <id name="id" column="parent_id"/>
+ ....
+ <set name="children" inverse="true">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+ </set>
+</class>
+
+<class name="Child">
+ <id name="id" column="child_id"/>
+ ....
+ <many-to-one name="parent"
+ class="Parent"
+ column="parent_id"
+ not-null="true"/>
+</class>]]></programlisting>
+
+ <para>
+ Mapear apenas uma das pontas da associação com
<literal>inverse="true"</literal>
+ não afeta as operações em cascata, isso é um conceito ortogonal.
+ </para>
+
+ </sect2>
+
+ <sect2 id="collections-indexedbidirectional">
+ <title>Associações bidirecionais com coleções indexadas</title>
+ <para>
+ Uma associação bidirecional onde uma dos lados e representa pôr uma
+ <literal><list></literal> ou
<literal><map></literal> requer uma consideração
+ especial. Se houver uma propriedade da classe filha que faça o mapeamento da
coluna do
+ índice, sem problema, pode-se continuar usando
<literal>inverse="true"</literal> no
+ mapeamento da coleção.
+ </para>
+
+ <programlisting><![CDATA[<class name="Parent">
+ <id name="id" column="parent_id"/>
+ ....
+ <map name="children" inverse="true">
+ <key column="parent_id"/>
+ <map-key column="name"
+ type="string"/>
+ <one-to-many class="Child"/>
+ </map>
+</class>
+
+<class name="Child">
+ <id name="id" column="child_id"/>
+ ....
+ <property name="name"
+ not-null="true"/>
+ <many-to-one name="parent"
+ class="Parent"
+ column="parent_id"
+ not-null="true"/>
+</class>]]></programlisting>
+
+ <para>
+ Mas, se não houver nenhuma propriedade na classe filha, não podemos ver essa
associação
+ como verdadeiramente bidirecional (há uma informação disponível em um lado da
associação
+ que não está disponível no extremo oposto). Nesse caso, nos não podemos
mapear a coleção
+ usando <literal>inverse="true"</literal>. Nos devemos
usar o seguinte mapeamento:
+ </para>
+
+ <programlisting><![CDATA[<class name="Parent">
+ <id name="id" column="parent_id"/>
+ ....
+ <map name="children">
+ <key column="parent_id"
+ not-null="true"/>
+ <map-key column="name"
+ type="string"/>
+ <one-to-many class="Child"/>
+ </map>
+</class>
+
+<class name="Child">
+ <id name="id" column="child_id"/>
+ ....
+ <many-to-one name="parent"
+ class="Parent"
+ column="parent_id"
+ insert="false"
+ update="false"
+ not-null="true"/>
+</class>]]></programlisting>
+
+ <para>
+ Veja que neste mapeamento, que um dos lado da associação, a coleção, é
responsável pela
+ atualização da chave estrangeira. TODO: Isso realmente resulta em updates
desnecessários ?.
+ </para>
+
+ </sect2>
+
+ <sect2 id="collections-ternary">
+ <title>Associações Ternárias</title>
+
+ <para>
+ Há três meios possíveis de se mapear uma associação ternária. Uma é usar um
+ <literal>Map</literal> com uma associação como seu índice:
+ </para>
+
+ <programlisting><![CDATA[<map name="contracts">
+ <key column="employer_id" not-null="true"/>
+ <map-key-many-to-many column="employee_id"
class="Employee"/>
+ <one-to-many class="Contract"/>
+</map>]]></programlisting>
+
+ <programlisting><![CDATA[<map name="connections">
+ <key column="incoming_node_id"/>
+ <map-key-many-to-many column="outgoing_node_id"
class="Node"/>
+ <many-to-many column="connection_id" class="Connection"/>
+</map>]]></programlisting>
+
+ <para>
+ A segunda maneira é simplesmente remodelar a associação das classes da
entidade.
+ Esta é a maneira que nós usamos de uma maneira geral.
+ </para>
+
+ <para>
+ Uma alternativa final é usar os elementos compostos, que nós
+ discutiremos mais tarde.
+ </para>
+
+ </sect2>
+
+ <sect2 id="collections-idbag" revision="1">
+ <title><literal>Usando o
<idbag></literal></title>
+
+ <para>
+ Se você concorda com nossa visão que chaves compostas são uma coisa ruim e
que
+ as entidades devem ter identificadores sintéticos (surrogate keys), então
você
+ deve estar achando um pouco estranho que as associações muitos para muitos
+ usando coleções de valores que nós mostramos estejam mapeadas com chaves
+ compostas! Bem, este ponto é bastante discutível; um simples tabela de
associação
+ não parece se beneficiar muito de uma surrogate key (entretanto uma coleção
de
+ valores compostos <emphasis>sim</emphasis>). Opcionalmente, o
Hibernate prove
+ uma maneira de mapear uma associação muitos para muitos com uma coleção
+ de valores para uma tabela com uma surrogate key.
+ </para>
+
+ <para>
+ O elemento <literal><idbag></literal> permite
mapear um <literal>List</literal>
+ (ou uma <literal>Collection</literal> com uma semântica de bag.
+ </para>
+
+<programlisting><![CDATA[<idbag name="lovers"
table="LOVERS">
+ <collection-id column="ID" type="long">
+ <generator class="sequence"/>
+ </collection-id>
+ <key column="PERSON1"/>
+ <many-to-many column="PERSON2" class="Person"
fetch="join"/>
+</idbag>]]></programlisting>
+
+ <para>
+ Como você pode ver, um <literal><idbag></literal>
possui um gerador de id
+ sintético, igual uma classe de entidade! Uma surrogate key diferente é
associada
+ para cada elemento de coleção. Porém, o Hibernate não prove nenhum mecanismo
+ para descobrir qual a surrogate key de uma linha em particular.
+ </para>
+
+ <para>
+ Note que o desempenho de atualização de um
<literal><idbag></literal> é
+ <emphasis>much</emphasis> melhor que um
<literal><bag></literal> normal!
+ O Hibernate pode localizar uma linha individual eficazmente e atualizar ou
+ deletar individualmente, como um list, map ou set.
+ </para>
+
+ <para>
+ Na implementação atual, a estratégia de geração de identificador
<literal>native</literal>
+ não é suportada para identificadores de coleção usando o
<literal><idbag></literal>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <!--undocumenting this stuff -->
+
+ <!--sect1 id="collections-heterogeneous">
+ <title>Heterogeneous Associations</title>
+
+ <para>
+ The <literal><many-to-any></literal> and
<literal><index-many-to-any></literal>
+ elements provide for true heterogeneous associations. These mapping elements
work in the
+ same way as the <literal><any></literal> element -
and should also be used
+ rarely, if ever.
+ </para>
+
+ </sect1-->
+
+ <sect1 id="collections-example" revision="1">
+ <title>Exemplos de coleções</title>
+
+ <para>
+ As seções anteriores são uma grande confusão. Assim sendo vejamos uma
exemplo.
+ Essa classe:
+ </para>
+
+ <programlisting><![CDATA[package eg;
+import java.util.Set;
+
+public class Parent {
+ private long id;
+ private Set children;
+
+ public long getId() { return id; }
+ private void setId(long id) { this.id=id; }
+
+ private Set getChildren() { return children; }
+ private void setChildren(Set children) { this.children=children; }
+
+ ....
+ ....
+}]]></programlisting>
+
+ <para>
+ tem uma coleção de instancias de <literal>Child</literal>. Se
+ cada Child tiver no máximo um parent, o mapeamento natural é
+ uma associação um para muitos:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Parent">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <set name="children">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+ </set>
+ </class>
+
+ <class name="Child">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <property name="name"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Esse mapeamento gera a seguinte definição de tabelas
+ </para>
+
+ <programlisting><![CDATA[create table parent ( id bigint not null
primary key )
+create table child ( id bigint not null primary key, name varchar(255), parent_id bigint
)
+alter table child add constraint childfk0 (parent_id) references
parent]]></programlisting>
+
+ <para>
+ Se o parent for <emphasis>obrigatório</emphasis>, use uma
associação bidirecional
+ um para muitos:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Parent">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <set name="children" inverse="true">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+ </set>
+ </class>
+
+ <class name="Child">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <property name="name"/>
+ <many-to-one name="parent" class="Parent"
column="parent_id" not-null="true"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Repare na constraint <literal>NOT NULL</literal>:
+ </para>
+
+ <programlisting><![CDATA[create table parent ( id bigint not null
primary key )
+create table child ( id bigint not null
+ primary key,
+ name varchar(255),
+ parent_id bigint not null )
+alter table child add constraint childfk0 (parent_id) references
parent]]></programlisting>
+
+ <para>
+ Uma outra alternativa, no caso de você insistir que esta associação devea ser
+ unidirecional, você pode declarar a constraint como <literal>NOT
NULL</literal>
+ na tag <literal><key></literal> do mapeamento:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Parent">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <set name="children">
+ <key column="parent_id" not-null="true"/>
+ <one-to-many class="Child"/>
+ </set>
+ </class>
+
+ <class name="Child">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <property name="name"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Por outro lado, se uma child puder ter os múltiplos parents, a associação
+ apropriada é muitos-para-muitos:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Parent">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <set name="children" table="childset">
+ <key column="parent_id"/>
+ <many-to-many class="Child" column="child_id"/>
+ </set>
+ </class>
+
+ <class name="Child">
+ <id name="id">
+ <generator class="sequence"/>
+ </id>
+ <property name="name"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Definições das tabelas:
+ </para>
+
+ <programlisting><![CDATA[create table parent ( id bigint not null
primary key )
+create table child ( id bigint not null primary key, name varchar(255) )
+create table childset ( parent_id bigint not null,
+ child_id bigint not null,
+ primary key ( parent_id, child_id ) )
+alter table childset add constraint childsetfk0 (parent_id) references parent
+alter table childset add constraint childsetfk1 (child_id) references
child]]></programlisting>
+
+ <para>
+ For more examples and a complete walk-through a parent/child relationship
mapping,
+ see <xref linkend="example-parentchild"/>.
+ Para mais exemplos e um exemplo completo de mapeamento de relacionamento
+ de mestre/detalhe, veja <xref
linkend="example-parentchild"/>.
+ </para>
+
+ <para>
+ Até mesmo o mapeamento de associações mais exóticas são possíveis, nós
catalogaremos
+ todas as possibilidades no próximo capítulo.
+ </para>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/collection_mapping.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/component_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/component_mapping.xml 2006-08-14 14:43:45
UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/component_mapping.xml 2006-08-14 14:55:10
UTC (rev 10262)
@@ -0,0 +1,413 @@
+<chapter id="components">
+ <title>Mapeamento de Componentes</title>
+
+ <para>
+ A noção de <emphasis>componente</emphasis> é reusada em vários
contextos diferentes,
+ para propósitos diferentes, pelo Hibernate.
+
+
+ </para>
+
+ <sect1 id="components-dependentobjects" revision="2" >
+ <title>Objetos dependentes</title>
+
+ <para>
+ Um componente é um objeto contido que é persistido como um tipo de valor, não
uma
+ referência de entidade. O termo "componente" refere-se à noção de
composição da
+ orientação a objetos (não a componentes no nível de arquitetura). Por
exemplo, você
+ pode modelar uma pessoa desta maneira:
+ </para>
+
+ <programlisting><![CDATA[public class Person {
+ private java.util.Date birthday;
+ private Name name;
+ private String key;
+ public String getKey() {
+ return key;
+ }
+ private void setKey(String key) {
+ this.key=key;
+ }
+ public java.util.Date getBirthday() {
+ return birthday;
+ }
+ public void setBirthday(java.util.Date birthday) {
+ this.birthday = birthday;
+ }
+ public Name getName() {
+ return name;
+ }
+ public void setName(Name name) {
+ this.name = name;
+ }
+ ......
+ ......
+}]]></programlisting>
+
+<programlisting><![CDATA[public class Name {
+ char initial;
+ String first;
+ String last;
+ public String getFirst() {
+ return first;
+ }
+ void setFirst(String first) {
+ this.first = first;
+ }
+ public String getLast() {
+ return last;
+ }
+ void setLast(String last) {
+ this.last = last;
+ }
+ public char getInitial() {
+ return initial;
+ }
+ void setInitial(char initial) {
+ this.initial = initial;
+ }
+}]]></programlisting>
+
+ <para>
+ Agora <literal>Name</literal> pode ser persistido como um
componente
+ de <literal>Person</literal>. Note que
<literal>Name</literal> define métodos
+ getter e setter para suas propriedades persistentes, mas não necessita
declarar
+ nenhuma interface ou propriedades identificadoras.
+ </para>
+
+ <para>
+ Nosso mapeamento do Hibernate seria semelhante a isso
+ </para>
+
+ <programlisting><![CDATA[<class name="eg.Person"
table="person">
+ <id name="Key" column="pid" type="string">
+ <generator class="uuid"/>
+ </id>
+ <property name="birthday" type="date"/>
+ <component name="Name" class="eg.Name"> <!-- class
attribute optional -->
+ <property name="initial"/>
+ <property name="first"/>
+ <property name="last"/>
+ </component>
+</class>]]></programlisting>
+
+ <para>
+ A tabela pessoa teria as seguintes colunas
<literal>pid</literal>,
+ <literal>birthday</literal>,
+ <literal>initial</literal>,
+ <literal>first</literal> and
+ <literal>last</literal>.
+ </para>
+
+ <para>
+ Assim como todos tipos por valor, componentes não suportam referencias
cruzadas. Em
+ outras palavras, duas pessoas poderiam possuir o mesmo nome, mas os dois
objetos
+ pessoa poderiam conter dois objetos nome independentes, apenas com "o
mesmo" por valor.
+ A semântica dos valores null de um componente são <emphasis>ad
hoc</emphasis>. No
+ recarregameno do conteúdo do objeto, O Hibernate assumira que se todas as
colunas
+ do componente são null, então todo o componente é null. Isto seria o certo
para
+ a maioria dos propósitos.
+ </para>
+
+ <para>
+ As propriedades de um componente podem ser de qualquer tipo do
Hibernate(collections,
+ associações muitos-para-um, outros componentes, etc). Componentes agrupados
+ <emphasis>não </emphasis> devem ser consideros um uso exótico. O
Hibernate tem
+ a intenção de suportar um modelo de objetos muito bem granulado.
+ </para>
+
+ <para>
+ O elemento <literal><component></literal> permite
um subelemento
+ <literal><parent></literal> que mapeia uma
propriedade da classe componente
+ como uma referência de volta para a entidade que a contém.
+ </para>
+
+ <programlisting><![CDATA[<class name="eg.Person"
table="person">
+ <id name="Key" column="pid" type="string">
+ <generator class="uuid"/>
+ </id>
+ <property name="birthday" type="date"/>
+ <component name="Name" class="eg.Name"
unique="true">
+ <parent name="namedPerson"/> <!-- reference back to the Person
-->
+ <property name="initial"/>
+ <property name="first"/>
+ <property name="last"/>
+ </component>
+</class>]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="components-incollections" revision="1">
+ <title>Collections de objetos dependentes</title>
+
+ <para>
+ Collections de componentes são suportadadas(ex. uma array de
+ tipo <literal>Name</literal>). Declare a sua collection de
+ componentes substituindo a
tag<literal><element></literal>
+ pela tag <literal><composite-element></literal>.
+ </para>
+
+ <programlisting><![CDATA[<set name="someNames"
table="some_names" lazy="true">
+ <key column="id"/>
+ <composite-element class="eg.Name"> <!-- class attribute required
-->
+ <property name="initial"/>
+ <property name="first"/>
+ <property name="last"/>
+ </composite-element>
+</set>]]></programlisting>
+
+ <para>
+ Nota: se você definir um <literal>Set</literal> de elementos
compostos,
+ é muito importante implementar <literal>equals()</literal> e
+ <literal>hashCode()</literal> corretamente.
+ </para>
+
+ <para>
+ Elementos compostos podem conter componentes mas não collections. Se o
+ seu elemento composto contiver componentes , use a tag
+ <literal><nested-composite-element></literal> .
Este é um caso
+ bastante exótico – uma collections de componentes que por si própria
+ possui componentes. Neste momento você deve estar se perguntando se
+ uma associação de um-para-muitos seria mais apropriada. Tente remodelar
+ o elemento composto como uma entidade – mas note que mesmo pensando
+ que o modelo Java é o mesmo, o modelo relacional e a semântica de
+ persistência ainda são diferentes.
+ </para>
+
+ <para>
+ Por favor, note que um mapeamento de elemento composto não suporta
propriedades
+ capazes de serem null se você estiver usando um
<literal><set></literal>.
+ O Hibernate tem que usar cada valor das colunas para identificar um registro
+ quando estiver deletando objetos (não existe coluna chave primária separada
na
+ tabela de elemento composto), que não é possível com valores null.
+ Você tem que usar um dos dois, ou apenas propriedades não null em um elemento
+ composto ou escolher uma <literal><list></literal>,
+ <literal><map></literal>,
<literal><bag></literal> ou
+ <literal><idbag></literal>.
+ </para>
+
+ <para>
+ Um caso especial de elemento composto é um elemento composto com um elemento
+ <literal><many-to-one></literal> aninhado. Um
mapeamento como este
+ permite você a mapear colunas extras de uma tabela de associação de
+ muitos-para-muitos para a classe de elemento composto. A seguinte
+ associação de muitos-para-muitos de <literal>Order</literal> para
um
+ <literal>Item</literal> onde
<literal>purchaseDate</literal>,
+ <literal>price</literal> e
<literal>quantity</literal> são propriedades
+ da associação:
+ </para>
+
+ <programlisting><![CDATA[<class name="eg.Order" .... >
+ ....
+ <set name="purchasedItems" table="purchase_items"
lazy="true">
+ <key column="order_id">
+ <composite-element class="eg.Purchase">
+ <property name="purchaseDate"/>
+ <property name="price"/>
+ <property name="quantity"/>
+ <many-to-one name="item" class="eg.Item"/> <!--
class attribute is optional -->
+ </composite-element>
+ </set>
+</class>]]></programlisting>
+
+ <para>
+ Claro, que não pode ter uma referência para purchase no outro lado, para a
+ navegação da associação bidirecional. Lembre-se que componentes são tipos por
+ valor e não permitem referências compartilhadas. Uma classe
<literal>Purchase</literal>
+ simples pode estar no set de uma classe <literal>Order</literal>,
mas ela não
+ pode ser referenciada por <literal>Item</literal> no mesmo
momento.
+ </para>
+
+ <para>Até mesmo associações ternárias (ou quaternária, etc) são
possíveis:</para>
+
+
+ <programlisting><![CDATA[<class name="eg.Order" .... >
+ ....
+ <set name="purchasedItems" table="purchase_items"
lazy="true">
+ <key column="order_id">
+ <composite-element class="eg.OrderLine">
+ <many-to-one name="purchaseDetails
class="eg.Purchase"/>
+ <many-to-one name="item" class="eg.Item"/>
+ </composite-element>
+ </set>
+</class>]]></programlisting>
+
+ <para>
+ Elementos compostos podem aparecer em pesquisas usando a mesma
+ sintaxe assim como associações para outras entidades.
+ </para>
+
+ </sect1>
+
+ <sect1 id="components-asmapindex">
+ <title>Componentes como índices de Map</title>
+
+ <para>
+ O elemento <literal><composite-map-key></literal>
permite você mapear
+ uma classe componente como uma chave de um
<literal>Map</literal>. Tenha
+ certeza que você sobrescreveu <literal>hashCode()</literal> e
+ <literal>equals()</literal> corretamente na classe componente.
+ </para>
+ </sect1>
+
+ <sect1 id="components-compositeid" revision="1">
+ <title>. Componentes como identificadores compostos</title>
+
+ <para>
+ Você pode usar um componente como um identificador de uma classe entidade.
+ Sua classe componente deve satisfazer certos requisitos:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Ele deve implementar
<literal>java.io.Serializable</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Ele deve re-implementar <literal>equals()</literal> e
+ <literal>hashCode()</literal>, consistentemente com a
noção
+ de igualdade de chave composta do banco de dados.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ <emphasis>Nota: no Hibernate 3, o segundo requisito não é um requisito
absolutamente
+ necessário. Mas atenda ele de qualquer forma.</emphasis>
+ </para>
+
+ <para>
+ Você não pode usar um <literal>IdentifierGenerator</literal> para
gerar chaves compostas.
+ Ao invés disso o aplicativo deve gerenciar seus próprios identificadores.
+ </para>
+
+ <para>
+ Use a tag <literal><composite-id></literal> (com
elementos
+ <literal><key-property></literal> aninhados) no
lugar da declaração
+ <literal><id></literal> de costume. Por exemplo, a
classe
+ <literal>OrderLine</literal> possui uma chave primária que
depende da
+ chave primária (composta) de <literal>Order</literal>.
+ </para>
+
+ <programlisting><![CDATA[<class name="OrderLine">
+
+ <composite-id name="id" class="OrderLineId">
+ <key-property name="lineId"/>
+ <key-property name="orderId"/>
+ <key-property name="customerId"/>
+ </composite-id>
+
+ <property name="name"/>
+
+ <many-to-one name="order" class="Order"
+ insert="false" update="false">
+ <column name="orderId"/>
+ <column name="customerId"/>
+ </many-to-one>
+ ....
+
+</class>]]></programlisting>
+
+ <para>
+ Agora, qualquer chave estrangeira referenciando a tabela
<literal>OrderLine</literal>
+ também serão compostas. Você deve declarar isto em seus mapeamentos para
outras
+ classes. Uma associação para <literal>OrderLine</literal> seria
mapeada dessa forma:
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="orderLine"
class="OrderLine">
+<!-- the "class" attribute is optional, as usual -->
+ <column name="lineId"/>
+ <column name="orderId"/>
+ <column name="customerId"/>
+</many-to-one>]]></programlisting>
+
+ <para>
+ (Note que a tag <literal><column></literal> é uma
alternativa para o
+ atributo <literal>column</literal> por toda a parte.)
+
+
+ </para>
+
+ <para>
+ Uma associação <literal>many-to-many</literal> para
<literal>many-to-many</literal>
+ também usa a chave estrangeira composta:
+ </para>
+
+ <programlisting><![CDATA[<set name="undeliveredOrderLines">
+ <key column name="warehouseId"/>
+ <many-to-many class="OrderLine">
+ <column name="lineId"/>
+ <column name="orderId"/>
+ <column name="customerId"/>
+ </many-to-many>
+</set>]]></programlisting>
+
+ <para>
+ A collection de <literal>OrderLine</literal>s em
<literal>Order</literal> usaria:
+ </para>
+
+ <programlisting><![CDATA[<set name="orderLines"
inverse="true">
+ <key>
+ <column name="orderId"/>
+ <column name="customerId"/>
+ </key>
+ <one-to-many class="OrderLine"/>
+</set>]]></programlisting>
+
+ <para>
+ (O elemento <literal><one-to-many></literal>, como
de costume, não declara colunas.)
+
+
+ </para>
+
+ <para>
+ Se <literal>OrderLine</literal> possui uma collection, ela também
tem uma
+ chave estrangeira composta.
+ </para>
+
+ <programlisting><![CDATA[<class name="OrderLine">
+ ....
+ ....
+ <list name="deliveryAttempts">
+ <key> <!-- a collection inherits the composite key type -->
+ <column name="lineId"/>
+ <column name="orderId"/>
+ <column name="customerId"/>
+ </key>
+ <list-index column="attemptId" base="1"/>
+ <composite-element class="DeliveryAttempt">
+ ...
+ </composite-element>
+ </set>
+</class>]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="components-dynamic" revision="1">
+ <title>Componentes Dinâmicos</title>
+
+ <para>
+ Você pode até mesmo mapear uma propriedade do tipo
<literal>Map</literal>:
+ </para>
+
+ <programlisting><![CDATA[<dynamic-component
name="userAttributes">
+ <property name="foo" column="FOO"
type="string"/>
+ <property name="bar" column="BAR"
type="integer"/>
+ <many-to-one name="baz" class="Baz"
column="BAZ_ID"/>
+</dynamic-component>]]></programlisting>
+
+ <para>
+ A semântica de um mapeamento
<literal><dynamic-component></literal> é idêntica
+ à <literal><component></literal>. A vantagem deste
tipo de mapeamento é a
+ habilidade de determinar as propriedades atuais do bean no momento de deploy,
+ apenas editando o documento de mapeamento. A Manipulação em tempo de execução
do
+ documento de mapeamento também é possível, usando o parser DOM. Até melhor,
+ você pode acessar (e mudar) o metamodelo configuration-time do Hibernate
+ através do objeto <literal>Configuration</literal>.
+ </para>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/component_mapping.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/configuration.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/configuration.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/configuration.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1789 @@
+<chapter id="session-configuration" revision="1">
+
+ <title>Configuração</title>
+
+ <para>
+ Devido ao fato de o Hibernate ser projetado para operar em vários ambientes
diferentes,
+ há um grande número de parâmetros de configuração. Felizmente, a maioria tem
valores default
+ lógicos e o Hibernate é distribuído com um arquivo
<literal>hibernate.properties</literal>
+ de exemplo no <literal>etc/</literal> que mostra várias opções.
Apenas coloque o arquivo
+ de exemplo no seu classpath e personalize-o.
+ </para>
+
+ <sect1 id="configuration-programmatic" revision="1">
+ <title>1.11 Configuração programática</title>
+
+ <para>
+ Uma instância de
<literal>org.hibernate.cfg.Configuration</literal>
+ representa um conjunto inteiro de mapeamentos de tipos Java da aplicação para
+ um banco de dados SQL. O <literal>Configuration</literal> é usado
para construir
+ uma <literal>SessionFactory</literal> (imutável). Os mapeamentos
são compilados
+ a partir de arquivos de mapeamento XML.
+
+ </para>
+
+ <para>
+ Você pode obter uma instância <literal>Configuration</literal>
intanciando-
+ o diretamente e especificando documentos de mapeamento XML. Se o arquivo
+ de mapeamento estão no classpath, use use
<literal>addResource()</literal>:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addResource("Item.hbm.xml")
+ .addResource("Bid.hbm.xml");]]></programlisting>
+
+ <para>
+ Uma alternativa (às vezes melhor) é especificar a classe mapeada,
+ e permitir que o Hibernate encontre o documento de mapeamento para você:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addClass(org.hibernate.auction.Item.class)
+ .addClass(org.hibernate.auction.Bid.class);]]></programlisting>
+
+ <para>
+ Então o Hibernate procurará pelos arquivos de mapeamento chamados
+ <literal>/org/hibernate/auction/Item.hbm.xml</literal> e
+ <literal>/org/hibernate/auction/Bid.hbm.xml</literal> no
classpath.
+ Esta abordagem elimina qualquer nome de arquivo de difícil compreensão.
+ </para>
+
+ <para>
+ Uma <literal>Configuration</literal> também permite você
especificar
+ propriedades de configuração:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration()
+ .addClass(org.hibernate.auction.Item.class)
+ .addClass(org.hibernate.auction.Bid.class)
+ .setProperty("hibernate.dialect",
"org.hibernate.dialect.MySQLInnoDBDialect")
+ .setProperty("hibernate.connection.datasource",
"java:comp/env/jdbc/test")
+ .setProperty("hibernate.order_updates",
"true");]]></programlisting>
+
+ <para>
+ Este não é o único caminho para passar as propriedades de configuração
+ para o Hibernate. As várias opções incluem:
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ Passar uma instância de
<literal>java.util.Properties</literal>
+ para <literal>Configuration.setProperties()</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Colocar <literal>hibernate.properties</literal> no
diretório
+ raiz do classpath.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Determinar as propriedades do <literal>System</literal>
+ usando <literal>java -Dproperty=value</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Include <literal><property></literal>
elements in
+ <literal>hibernate.cfg.xml</literal> (discussed later).
+ Incluir elementos
<literal><property></literal> no
+ <literal>hibernate.cfg.xml</literal> (discutido mais
tarde).
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ <literal>hibernate.properties</literal> é o caminho mais facil
+ se você quer começar mais rápido.
+ </para>
+
+ <para>
+ O <literal>Configuration</literal> é entendido como um objeto
startup-time,
+ é descartado uma vez que a <literal>SessionFactory</literal> é
criada.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-sessionfactory">
+ <title>Obtendo uma SessionFactory</title>
+
+ <para>
+ Quando todos os mapeamentos têm sido analisados pelo
<literal>Configuration</literal>,
+ a aplicação deve obter uma factory para as instâncias da
<literal>Session</literal>.
+ O objetivo desta factory é ser compartilhado por todas as threads da
aplicação:
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sessions =
cfg.buildSessionFactory();]]></programlisting>
+
+ <para>
+ Hibernate permite sua aplicação instanciar mais do que uma
+ <literal>SessionFactory</literal>. Isto é útil se você está
usando mais
+ do que um banco de dados.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-hibernatejdbc" revision="1">
+ <title>Conexões JDBC</title>
+
+ <para>
+ Normalmente, você quer mandar criar a
<literal>SessionFactory</literal> criar um
+ pool de conexões JDBC para você. Se você seguir essa abordagem, a abertura de
uma
+ <literal>Session</literal> é tão simples quanto:
+
+ </para>
+
+ <programlisting><![CDATA[Session session = sessions.openSession(); //
open a new Session]]></programlisting>
+
+ <para>
+ Assim que você fizer algo que requer o acesso ao banco de dados, uma
+ conexão JDBC será obtida do pool.
+ </para>
+
+ <para>
+ Para esse trabalho, nós necessitamos passar algumas propriedades da conexão
JDBC
+ para o Hibernate. Todos os nomes de propriedades Hibernate e semânticas são
definidas
+ <literal>org.hibernate.cfg.Environment</literal>. Nós iremos
descrever agora
+ o mais importantes configurações de conexão JDBC.
+ </para>
+
+ <para>
+ O Hibernate obterá conexões( e pool) usando
<literal>java.sql.DriverManager</literal>
+ se você determinar as seguintes propriedades:
+ </para>
+
+ <table frame="topbot">
+ <title>Propriedades JDBC Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.connection.driver_class</literal>
+ </entry>
+ <entry>
+ <emphasis>Classe driver jdbc</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.url</literal>
+ </entry>
+ <entry>
+ <emphasis>URL jdbc</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.username</literal>
+ </entry>
+ <entry>
+ <emphasis>Usuário do banco de dados</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.password</literal>
+ </entry>
+ <entry>
+ <emphasis>Senha do usuário do banco de dados</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.pool_size</literal>
+ </entry>
+ <entry>
+ <emphasis>Número máximo de connecxões no pool</emphasis>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ O algoritmo de pool de conexões do próprio Hibernate entretanto é
completamente
+ rudimentar. A intenção dele e ajudar a iniciar e <emphasis>não para
usar em um
+ sistema de produção</emphasis> ou até para testar desempenho. Você
deveria usar
+ uma ferramente de pool de terceiros para conseguir melhor desempenho e
estabilidade.
+ Apenas especifique a propriedade
<literal>hibernate.connection.pool_size</literal>
+ com a definição do pool de conexões. Isto irá desligar o pool interno do
Hibernate.
+ Por exemplo, você pode gostar de usar C3P0.
+ </para>
+
+ <para>
+ O C3P0 é um pool conexão JDBC de código aberto distribuído junto com
+ Hibernate no diretório <literal>lib</literal>. O Hibernate
usará o
+ <literal>C3P0ConnectionProvider</literal> para o pool de conexão
se
+ você configurar a propriedade
<literal>hibernate.c3p0.*</literal>. Se você
+ gostar de usar Proxool consulte ao pacote
<literal>hibernate.properties</literal>
+ e o web site do Hibernate para mais informações.
+ </para>
+
+ <para>
+ Aqui é um exemplo de arquivo
<literal>hibernate.properties</literal> para C3P0:
+ </para>
+
+ <programlisting id="c3p0-configuration"
revision="1"><![CDATA[hibernate.connection.driver_class =
org.postgresql.Driver
+hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
+hibernate.connection.username = myuser
+hibernate.connection.password = secret
+hibernate.c3p0.min_size=5
+hibernate.c3p0.max_size=20
+hibernate.c3p0.timeout=1800
+hibernate.c3p0.max_statements=50
+hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
+
+ <para>
+ Para usar dentro de um servidor de aplicação, você deve configurar
+ o Hibernate para obter conexões de um application server
+ <literal>Datasource</literal> registrado no JNDI. Você
necessitará
+ determinar pelo menos uma das seguintes propriedades:
+ </para>
+
+ <table frame="topbot">
+ <title>Propriedades do Datasource do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.connection.datasource</literal>
+ </entry>
+ <entry>
+ <emphasis>Nome datasource JNDI</emphasis>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jndi.url</literal>
+ </entry>
+ <entry>
+ <emphasis>URL do fornecedor JNDI</emphasis> (opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jndi.class</literal>
+ </entry>
+ <entry>
+ <emphasis>Classe do JNDI
<literal>InitialContextFactory</literal></emphasis> (opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.username</literal>
+ </entry>
+ <entry>
+ <emphasis>Usuário do banco de dados</emphasis>
(opcional)
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.password</literal>
+ </entry>
+ <entry>
+ <emphasis>Senha do usuário do banco de dados</emphasis>
(opcional)
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ Eis um exemplo de arquivo <literal>hibernate.properties</literal>
para
+ um servidor de aplicação fornecedor de datasources JNDI:
+ </para>
+
+ <programlisting><![CDATA[hibernate.connection.datasource =
java:/comp/env/jdbc/test
+hibernate.transaction.factory_class = \
+ org.hibernate.transaction.JTATransactionFactory
+hibernate.transaction.manager_lookup_class = \
+ org.hibernate.transaction.JBossTransactionManagerLookup
+hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect]]></programlisting>
+
+ <para>
+ Conexões JDBC obtidas de um datasource JNDI irão automaticamente irão
participar
+ das transações gerenciadas pelo container no servidor de aplicação.
+ </para>
+
+ <para>
+ Arbitrariamente as propriedades de conexão podem ser acrescentandas ao
+ "<literal>hibernate.connnection</literal>" ao nome da
propriedade. Por exemplo,
+ você deve especificar o <literal>charSet</literal> usando
<literal>hibernate.connection.charSet</literal>.t.
+ </para>
+
+ <para>
+ Você pode definir sua própria estratégia de plugin para obter conexões JDBC
implementando
+ a interface
<literal>org.hibernate.connection.ConnectionProvider</literal>. Você pode
+ escolher uma implementação customizada setando
<literal>hibernate.connection.provider_class</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-optional" revision="1">
+ <title>Propriedades opcionais de configuração</title>
+
+ <para>
+ Há um grande número de outras propriedades que controlam o comportamento do
Hibernate
+ em tempo de execução. Todos são opcionais e tem valores default lógicos.
+ </para>
+
+ <para>
+ <emphasis>Aviso: algumas destas propriedades são somente a "nível
de sistema".</emphasis>
+ Propriedades nível de sistema podem ser determinados somente via
<literal>java -Dproperty=value</literal>
+ ou <literal>hibernate.properties</literal>. Elas
<emphasis>não</emphasis>podem ser
+ configuradas por outras técnicas descritas abaixo.
+ </para>
+
+ <table frame="topbot"
id="configuration-optional-properties" revision="8">
+ <title>Hibernate Configuration Properties</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.dialect</literal>
+ </entry>
+ <entry>
+ O nome da classe de um <literal>Dialeto</literal>
+ que permite o Hibernate gerar SQL otimizado para um banco de
+ dados relacional em particular.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>full.classname.of.Dialect</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.show_sql</literal>
+ </entry>
+ <entry>
+ Escreve todas as instruções SQL no console. Esta é uma
alternativa
+ a configurar a categoria de log
<literal>org.hibernate.SQL</literal>
+ para <literal>debug</literal>.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.format_sql</literal>
+ </entry>
+ <entry>
+ Imprime o SQL formatado no log e console.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_schema</literal>
+ </entry>
+ <entry>
+ Qualifica no sql gerado, os nome das tabelas sem qualificar
+ com schena/tablespace dado
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>SCHEMA_NAME</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_catalog</literal>
+ </entry>
+ <entry>
+ Qualifica no sql gerado, os nome das tabelas sem qualificar
+ com catálogo dado
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>CATALOG_NAME</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.session_factory_name</literal>
+ </entry>
+ <entry>
+ O <literal>SessionFactory</literal> irá
automaticamente
+ se ligar a este nome no JNDI depois de ter sido criado.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jndi/composite/name</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.max_fetch_depth</literal>
+ </entry>
+ <entry>
+ Estabelece a "profundidade" máxima para árvore
outer join fetch
+ para associações finais únicas(one-to-one,many-to-one).
+ Um <literal>0</literal> desativa por default a
busca outer join.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ Valores recomendados
entre<literal>0</literal> e <literal>3</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.default_batch_fetch_size</literal>
+ </entry>
+ <entry>
+ Determina um tamanho default para busca de associações em
lotes do Hibernate
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ Valores recomendados <literal>4</literal>,
<literal>8</literal>,
+ <literal>16</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.default_entity_mode</literal>
+ </entry>
+ <entry>
+ Determina um modo default para representação de entidades
+ para todas as sessões abertas desta
<literal>SessionFactory</literal>
+ <para>
+ <literal>dynamic-map</literal>,
<literal>dom4j</literal>,
+ <literal>pojo</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.order_updates</literal>
+ </entry>
+ <entry>
+ Força o Hibernate a ordenar os updates SQL pelo valor da
chave
+ primária dos itens a serem atualizados. Isto resultará em
menos
+ deadlocks nas transações em sistemas altamente concorrente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.generate_statistics</literal>
+ </entry>
+ <entry>
+ If enabled, Hibernate will collect statistics useful for
+ performance tuning.
+ Se habilitado, o Hibernate coletará estatísticas úties
+ para performance tuning dos bancos.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.use_identifer_rollback</literal>
+ </entry>
+ <entry>
+ Se habilitado, propriedades identificadoras geradas
+ serão zeradas para os valores default quando os
+ objetos forem apagados.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.use_sql_comments</literal>
+ </entry>
+ <entry>
+ Se ligado, o Hibernate irá gerar comentários dentro do SQL,
+ para facilitar o debugging, o valor default é
<literal>false</literal>.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-jdbc-properties"
revision="8">
+ <title>JDBC Hibernate e Propriedades de Conexão</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.fetch_size</literal>
+ </entry>
+ <entry>
+ Um valor maior que zero determina o tamanho do fetch
+ do JDBC( chamadas
<literal>Statement.setFetchSize()</literal>).
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.batch_size</literal>
+ </entry>
+ <entry>
+ Um valor maior que zero habilita uso de batch updates JDBC2
pelo Hibernate.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ valores recomentados entre
<literal>5</literal> e <literal>30</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.batch_versioned_data</literal>
+ </entry>
+ <entry>
+ Sete esta propriedade como
<literal>true</literal> se seu driver JDBC retorna
+ o número correto de linhas no
<literal>executeBatch()</literal> ( É usualmente
+ seguro tornar esta opção ligada). O Hibernate então irá usar
betched DML
+ para automaticamente versionar dados.
<literal>false</literal> por default.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.jdbc.factory_class</literal>
+ </entry>
+ <entry>
+ Escolher um <literal>Batcher</literal>
customizado. Muitas
+ aplicações não irão necessitar desta propriedade de
configuração
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>classname.of.Batcher</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_scrollable_resultset</literal>
+ </entry>
+ <entry>
+ Habilita o uso de JDBC2 scrollable resultsets pelo
Hibernate.
+ Essa propriedade somente é necessaria quando se usa
Conexeções
+ JDBC providas pelo usuário, caso contrário o Hibernate os os
+ metadados da conexão.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_streams_for_binary</literal>
+ </entry>
+ <entry>
+ Use streams para escrever/ler tipos
<literal>binary</literal>
+ ou <literal>serializable</literal> para/a o JDBC(
propriedade a nível de sistema).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jdbc.use_get_generated_keys</literal>
+ </entry>
+ <entry>
+ Possibilita o uso
<literal>PreparedStatement.getGeneratedKeys()</literal>
+ do JDBC3 para recuperar chaves geradas nativamente depois da
inserçãp.
+ Requer driver JDBC3+ e JRE1.4+, determine para false se seu
driver tem
+ problemas com gerador de indentificadores Hibernate. Por
default, tente
+ determinar o driver capaz de usar metadados da conexão.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.provider_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>ConnectionProvider</literal> personalizado
+ o qual proverá conexões JDBC para o Hibernate.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.ConnectionProvider</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.connection.isolation</literal>
+ </entry>
+ <entry>
+ Determina o nível de isolamento de uma transação JDBC.
+ Verifique <literal>java.sql.Connection</literal> para
valores
+ siginificativos mas note que a maior parte dos bancos de dados
+ não suportam todos os níveis de isolamento.
+ <para>
+ <emphasis role="strong">Ex.</emphasis>
+ <literal>1, 2, 4, 8</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.autocommit</literal>
+ </entry>
+ <entry>
+ Habilita autocommit para conexões no pool JDBC( não
recomendado).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.release_mode</literal>
+ </entry>
+ <entry>
+ Especifica quando o Hibernate deve liberar conexões JDBC. Por
default,
+ uma conexão JDBC é retida até a sessão está explicitamente
fechada
+ ou desconectada. Para um datasource JTA do servidor de
aplicação, você deve
+ usar <literal>after_statement</literal> para
forçar s liberação da conexões
+ depois de todas as chamadas JDBC. Para uma conexão não-JTA,
freqüentemente
+ faz sentido liberar a conexão ao fim de cada transação,
usando
+ <literal>after_transaction</literal>.
<literal>auto</literal> escolheremos
+ <literal>after_statement</literal> para as
estratégias de transaçãoes JTA e CMT
+ e <literal>after_transaction</literal> para as
estratégias de transação JDBC
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>auto</literal> (default) |
<literal>on_close</literal> |
+ <literal>after_transaction</literal> |
<literal>after_statement</literal>
+ </para>
+ <para>
+ Note that this setting only affects
<literal>Session</literal>s returned from
+
<literal>SessionFactory.openSession</literal>. For
<literal>Session</literal>s
+ obtained through
<literal>SessionFactory.getCurrentSession</literal>, the
+ <literal>CurrentSessionContext</literal>
implementation configured for use
+ controls the connection release mode for those
<literal>Session</literal>s.
+ See <xref
linkend="architecture-current-session"/>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.connection.<emphasis><propertyName></emphasis></literal>
+ </entry>
+ <entry>
+ Passa a propriedade JDBC
<literal>propertyName</literal>
+ para
<literal>DriverManager.getConnection()</literal>.
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.jndi.<emphasis><propertyName></emphasis></literal>
+ </entry>
+ <entry>
+ Passar a propriedade
<literal>propertyName</literal> para
+ o <literal>InitialContextFactory</literal> JNDI.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-cache-properties"
revision="7">
+ <title>Propriedades de Cachê do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.cache.provider_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>CacheProvider</literal> customizado.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.CacheProvider</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_minimal_puts</literal>
+ </entry>
+ <entry>
+ Otimizar operação de cachê de segundo nível para minimizar
escritas,
+ ao custo de leituras mais frequantes. Esta configuração é
mais útil
+ para cachês clusterizados e, no Hibernate3, é habilitado por
default
+ para implementações de cachê clusterizar.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_query_cache</literal>
+ </entry>
+ <entry>
+ Habilita a cache de consultas, Mesmo assim, consultas
individuais ainda tem que ser
+ habilitadas para o cache.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_second_level_cache</literal>
+ </entry>
+ <entry>
+ May be used to completely disable the second level cache,
which is enabled
+ by default for classes which specify a
<literal><cache></literal>
+ mapping.
+ Pode ser usada para desabilitar completamente ocache de
segundo nível,
+ o qual está habilitado por default para classes que
especificam
+ um mapeamento
<literal><cache></literal>.
+
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.query_cache_factory</literal>
+ </entry>
+ <entry>
+ O nome de uma classe que implementa a interface
+ <literal>QueryCache</literal> personalizada, por
+ default, um
<literal>StandardQueryCache</literal>
+ criado automaticamente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>classname.of.QueryCache</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.cache.region_prefix</literal>
+ </entry>
+ <entry>
+ Um prefixo para usar nos nomes da área especial
+ do cachê de segundo nível.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>prefix</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cache.use_structured_entries</literal>
+ </entry>
+ <entry>
+ Forces Hibernate to store data in the second-level cache
+ in a more human-friendly format.
+ Força o Hibernate armazenar dados no cachê se segundo
+ nível em um formato mais legivel.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true|false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot"
id="configuration-transaction-properties" revision="9">
+ <title>Propriedades de Transação do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.factory_class</literal>
+ </entry>
+ <entry>
+ O nome da clase de um a
<literal>TransactionFactory</literal>
+ para usar com API <literal>Transaction</literal>
+ ( por default JDBCTransactionFactory).
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.TransactionFactory</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>jta.UserTransaction</literal>
+ </entry>
+ <entry>
+ Um nome JNDI usado pelo
<literal>JTATransactionFactory</literal>
+ para obter uma <literal>UserTransaction</literal>
JTA a partir
+ do servidor de aplicação.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jndi/composite/name</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.manager_lookup_class</literal>
+ </entry>
+ <entry>
+ O nome da classe de um
<literal>TransactionManagerLookup</literal>
+ – requerido quando caching a nível JVM esta habilitado ou
quando
+ estivermos usando um generator hilo em um ambiente JTA.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+
<literal>classname.of.TransactionManagerLookup</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.flush_before_completion</literal>
+ </entry>
+ <entry>
+ Se habilitado, a sessão será automaticamente limpa antes da
fase de
+ conclusão da transação. É preferivel a gerência interna e
+ automática do contexto da sessão, veja
+ <xref
linkend="architecture-current-session"/>
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.transaction.auto_close_session</literal>
+ </entry>
+ <entry>
+ Se habilitado, a sessão será automaticamente fechada após a
fase de
+ conclusão da transação. É preferivel a gerência interna e
+ automática do contexto da sessão, veja
+ <xref
linkend="architecture-current-session"/>
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <table frame="topbot" id="configuration-misc-properties"
revision="10">
+ <title>Propriedades Variadas</title>
+ <tgroup cols="2">
+ <colspec colname="c1" colwidth="1*"/>
+ <colspec colname="c2" colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Nome da Propriedade</entry>
+ <entry>Propósito</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>
+
<literal>hibernate.current_session_context_class</literal>
+ </entry>
+ <entry>
+ Forneçe uma estratégia (personalizada) para extensão
+ da <literal>Session</literal>
"corrente". Veja
+ <xref
linkend="architecture-current-session"/> para
+ mais informação sobre estratégias internas.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>jta</literal> |
<literal>thread</literal> |
+ <literal>managed</literal> |
<literal>custom.Class</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.query.factory_class</literal>
+ </entry>
+ <entry>
+ Escolha a implementação de análise HQL.
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+
<literal>org.hibernate.hql.ast.ASTQueryTranslatorFactory</literal> or
+
<literal>org.hibernate.hql.classic.ClassicQueryTranslatorFactory</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.query.substitutions</literal>
+ </entry>
+ <entry>
+ Mapeamento a partir de símbolos em consultas HQL para
+ símbolos SQL( símbolos devem ser funções ou nome literais
+ , por exemplo).
+ <para>
+ <emphasis
role="strong">eg.</emphasis>
+ <literal>hqlLiteral=SQL_LITERAL,
hqlFunction=SQLFUNC</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+ <literal>hibernate.hbm2ddl.auto</literal>
+ </entry>
+ <entry>
+ Automaticamente valida ou exporta schema DDL para o banco de
+ dados quando o <literal>SessionFactory</literal>
é criads.
+ Com <literal>create-drop</literal>, o schema do
banco de dados
+ será excluido quando a
<literal>create-drop</literal> for
+ fechada esplicitamente.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>validate</literal> |
<literal>update</literal> |
+ <literal>create</literal> |
<literal>create-drop</literal>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry>
+
<literal>hibernate.cglib.use_reflection_optimizer</literal>
+ </entry>
+ <entry>
+ Habilita o uso de CGLIB em vez de reflexão em tempo de
execução
+ ( propriedade a nível de sistema). Reflexão pode algumas
vezes ser ú
+ til quando controlar erros, note que o Hibernate sempre irá
requerer a CGLIB
+ mesmo se você desligar o otimizador. Você não pode determinar
esta
+ propriedade no hibernate.cfg.xml.
+ <para>
+ <emphasis
role="strong">Ex.</emphasis>
+ <literal>true</literal> |
<literal>false</literal>
+ </para>
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <sect2 id="configuration-optional-dialects"
revision="1">
+ <title>Dialetos SQL</title>
+
+ <para>
+ Você deve sempre determinar a propriedade
<literal>hibernate.dialect</literal>
+ para a subclasse de
<literal>org.hibernate.dialect.Dialect</literal> correta de seu
+ banco de dados. Se você especificar um dialeto, Hibernate usará defaults
lógicos
+ para qualquer um das outras propriedades listadas abaixo, reduzindo o
esforço de
+ especificá-los manualmente.
+ </para>
+
+ <table frame="topbot" id="sql-dialects"
revision="2">
+ <title>Hibernate SQL Dialects
(<literal>hibernate.dialect</literal>)</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="2.5*"/>
+ <thead>
+ <row>
+ <entry>RDBMS</entry>
+ <entry>Dialect</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>DB2</entry>
<entry><literal>org.hibernate.dialect.DB2Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>DB2 AS/400</entry>
<entry><literal>org.hibernate.dialect.DB2400Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>DB2 OS390</entry>
<entry><literal>org.hibernate.dialect.DB2390Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>PostgreSQL</entry>
<entry><literal>org.hibernate.dialect.PostgreSQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL</entry>
<entry><literal>org.hibernate.dialect.MySQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL with InnoDB</entry>
<entry><literal>org.hibernate.dialect.MySQLInnoDBDialect</literal></entry>
+ </row>
+ <row>
+ <entry>MySQL with MyISAM</entry>
<entry><literal>org.hibernate.dialect.MySQLMyISAMDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Oracle (any version)</entry>
<entry><literal>org.hibernate.dialect.OracleDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Oracle 9i/10g</entry>
<entry><literal>org.hibernate.dialect.Oracle9Dialect</literal></entry>
+ </row>
+ <row>
+ <entry>Sybase</entry>
<entry><literal>org.hibernate.dialect.SybaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Sybase Anywhere</entry>
<entry><literal>org.hibernate.dialect.SybaseAnywhereDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Microsoft SQL Server</entry>
<entry><literal>org.hibernate.dialect.SQLServerDialect</literal></entry>
+ </row>
+ <row>
+ <entry>SAP DB</entry>
<entry><literal>org.hibernate.dialect.SAPDBDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Informix</entry>
<entry><literal>org.hibernate.dialect.InformixDialect</literal></entry>
+ </row>
+ <row>
+ <entry>HypersonicSQL</entry>
<entry><literal>org.hibernate.dialect.HSQLDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Ingres</entry>
<entry><literal>org.hibernate.dialect.IngresDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Progress</entry>
<entry><literal>org.hibernate.dialect.ProgressDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Mckoi SQL</entry>
<entry><literal>org.hibernate.dialect.MckoiDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Interbase</entry>
<entry><literal>org.hibernate.dialect.InterbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Pointbase</entry>
<entry><literal>org.hibernate.dialect.PointbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>FrontBase</entry>
<entry><literal>org.hibernate.dialect.FrontbaseDialect</literal></entry>
+ </row>
+ <row>
+ <entry>Firebird</entry>
<entry><literal>org.hibernate.dialect.FirebirdDialect</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-outerjoin"
revision="4">
+ <title>Recuperação por união externa (Outer Join
Fetching)</title>
+
+ <para>
+ Se seu banco de dados suporta Recuperação por união externa (Outer Join
Fetching) no estilo ANSI,
+ Oracle ou Sybase, A recuperação por união externa (Outer Join Fetching)
frequentemente aumentará
+ o desempenho limitando o número de chamadas (round trips) ao banco de
dados( ao custo de
+ possivelmente mais trabalho desempenhado pelo próprio banco de dados). A
recuperação por
+ união externa (Outer Join Fetching)permite um gráfico completo de objetos
conectados
+ por muitos-para-um, um-para-muitos, muitos-para-muitos e associações
um-para-um para ser
+ recuperadas em um simples instrução SQL SELECT .
+
+ </para>
+
+ <para>
+ A recuperação por união externa (Outer Join Fetching) pode ser
desabilitado
+ <emphasis>globalmente</emphasis> setando a propriedade
+ <literal>hibernate.max_fetch_depth</literal> para
<literal>0</literal>.
+ Uma valor 1 ou maior habilita o outer join fetching para associações
um-para-um
+ e muitos-para-umos cujos quais tem sido mapeado com
<literal>fetch="join"</literal>.
+ </para>
+
+ <para>
+ Veja <xref linkend="performance-fetching"/> para mais
informações.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-binarystreams"
revision="1">
+ <title>Fluxos Binários (Binary Streams)</title>
+
+ <para>
+ O Oracle limita o tamanho de arrays de
<literal>byte</literal> que pode ser
+ passado para/de o driver JDBC. Se você desejar usar grandes instâncias de
+ tipos <literal>binary</literal> ou
<literal>serializable</literal>, você
+ deve habilitar
<literal>hibernate.jdbc.use_streams_for_binary</literal>.
+ <emphasis>Essa é uma configuração que só pode ser feita a nível de
sistema.</emphasis>
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-cacheprovider"
revision="2">
+ <title>Cachê de segundo nível e query</title>
+
+ <para>
+ As propriedades prefixadas pelo
<literal>hibernate.cache</literal>
+ permite você usar um sistema de cachê de segundo nível
+ em um processo executado em clustercom Hibernate.
+ Veja <xref linkend="performance-cache"/> para mais
detalhes.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-querysubstitution">
+ <title>Substituições na Linguagem de Consulta</title>
+
+ <para>
+ Você pode definir novos símbolos de consulta Hibernate usando
+ <literal>hibernate.query.substitutions</literal>.
+ Por exemplo:
+ </para>
+
+ <programlisting>hibernate.query.substitutions true=1,
false=0</programlisting>
+
+ <para>
+ Faria com que os símbolos <literal>true</literal> e
<literal>false</literal>
+ passasem a ser traduzidos para literais inteiro no SQL gerado.
+ </para>
+
+ <programlisting>hibernate.query.substitutions
toLowercase=LOWER</programlisting>
+
+ <para>
+ permitirá você renomear a função <literal>LOWER</literal> no
SQL.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-statistics"
revision="2">
+ <title>Estatísticas do Hibernate</title>
+
+ <para>
+ If you enable
<literal>hibernate.generate_statistics</literal>, Hibernate will
+ expose a number of metrics that are useful when tuning a running system
via
+ <literal>SessionFactory.getStatistics()</literal>. Hibernate
can even be configured
+ to expose these statistics via JMX. Read the Javadoc of the interfaces
in
+ <literal>org.hibernate.stats</literal> for more information.
+
+ Se você habilitar
<literal>hibernate.generate_statistics</literal>, o Hibernate
+ exibirá um número de métricas bastante útil ao ajustar um sistema via
+ <literal>SessionFactory.getStatistics()</literal>. O
Hibernate pode até ser
+ configurado para exibir essas estatísticas via JMX. Leia o Javadoc da
interface
+ <literal>org.hibernate.stats</literal> para mais
informações.
+ </para>
+
+ </sect2>
+ </sect1>
+
+ <sect1 id="configuration-logging">
+ <title>Logging</title>
+
+ <para>
+ Hibernate registra vários eventos usando Apache commons-logging.
+ </para>
+
+ <para>
+ O serviço commons-logging direcionará a saída para o Apache Log4j
+ ( se você incluir <literal>log4j.jar</literal>r no seu classpath)
ou
+ JDK1.4 logging( se estiver em uso JDK1.4 ou maior). Você pode fazer o
+ download do Log4j a partir de
<literal>http://jakarta.apache.org</literal>.
+ Para usar Log4j você necessitará colocar um arquivo
+ <literal>log4j.properties</literal> no seu classpath, um exemplo
de arquivo
+ de propriedades é distribuído com o Hibernate no diretório
+ <literal>src/</literal>.
+
+ </para>
+
+ <para>
+ We strongly recommend that you familiarize yourself with Hibernate's log
+ messages. A lot of work has been put into making the Hibernate log as
+ detailed as possible, without making it unreadable. It is an essential
+ troubleshooting device. The most interesting log categories are the
+ following:
+
+ Nós recomendamos enfaticamente que você se familiarize-se com mensagens de
+ log do Hibernate. Uma parte do trabalho tem sido posto em fazer o log
+ Hibernate tão detalhado quanto possível, sem fazê-lo ilegível.
+ É um essencial dispositivos de controle de erros. As categorias de log
+ mais interessantes são as seguintes:
+ </para>
+
+ <table frame="topbot" id="log-categories"
revision="2">
+ <title>Categorias de Log do Hibernate</title>
+ <tgroup cols="2">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="2.5*"/>
+ <thead>
+ <row>
+ <entry>Categoria</entry>
+ <entry>Função</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>org.hibernate.SQL</literal></entry>
+ <entry>Registra todas as instruções SQL DML a medida
que elas são executadas</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.type</literal></entry>
+ <entry>Registra todos os parâmetros JDBC</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.tool.hbm2ddl</literal></entry>
+ <entry>Registra todas as instruções SQL DDL a medida
que elas são executadas</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.pretty</literal></entry>
+ <entry>
+ Log the state of all entities (max 20 entities)
associated
+ with the session at flush time
+ Registra o estado de todas as entidades (máximo 20
entidades)
+ associadas a session no momento da limpeza (flush).
+ </entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.cache</literal></entry>
+ <entry>Registra todas as atividades de cachê de segundo
nível</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction</literal></entry>
+ <entry>Registra atividades relacionada a
transação</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.jdbc</literal></entry>
+ <entry>Registra todas as requisições de recursos
JDBC</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.hql.ast.AST</literal></entry>
+ <entry>
+ Registra instruções SQL e HQL durante a análise da
consultas
+ </entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.secure</literal></entry>
+ <entry>Registra todas as requisições de autorização
JAAS</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate</literal></entry>
+ <entry>
+ Registra tudo ( uma parte das informações, mas muito
+ útil para controle de erros )
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ Quando desenvolver aplicações com Hibernate, você deve quase sempre trabalhar
com
+ debug <literal>debug</literal> para a categoria
<literal>org.hibernate.SQL</literal>,
+ ou, alternativamente, a com a propriedade
<literal>hibernate.show_sql</literal> habilitada.
+ </para>
+
+
+ </sect1>
+
+ <sect1 id="configuration-namingstrategy">
+ <title>Implementado uma
<literal>NamingStrategy</literal></title>
+
+ <para>
+ A interface <literal>org.hibernate.cfg.NamingStrategy</literal>
permite você
+ especificar um "padrão de nomeação" para objetos do banco de dados
e elementos schema.
+ </para>
+
+ <para>
+ Você deve criar regras para a geração automaticamente de identificadores
+ do banco de dados a partir de identificadores Java ou para processar
+ colunas "computadas" e nomes de tabelas dado o arquivo de
mapeamento
+ para nomes "físicos" de tabelas e colunas. Esta característica
ajuda a
+ reduzir a verbosidade do documento de mapeamento, eliminando interferências
+ repetitivas( <literal>TBL_</literal>prefixos, por exemplo). A
estratégia
+ default usada pelo Hibernate é completamente mínima.
+ </para>
+
+ <para>
+ Você pode especificar uma estratégia diferente ao chamar
+ <literal>Configuration.setNamingStrategy()</literal> antes de
adicionar
+ os mapeamentos:
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new Configuration()
+ .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
+ .addFile("Item.hbm.xml")
+ .addFile("Bid.hbm.xml")
+ .buildSessionFactory();]]></programlisting>
+
+ <para>
+ <literal>org.hibernate.cfg.ImprovedNamingStrategy</literal> é uma
estratégia
+ interna que pode ser um ponto de começo útil para algumas aplicações.
+ </para>
+
+ </sect1>
+
+ <sect1 id="configuration-xmlconfig" revision="2">
+ <title>Arquivo de configuração XML</title>
+
+ <para>
+ Uma maneira alternativa de configuração é especificar uma configuração
completa
+ em um arquivo chamado <literal>hibernate.cfg.xml</literal>. Este
arquivo pode
+ ser usado como um substituto para o arquivo
<literal>hibernate.properties</literal>
+ ou, se ambos estão presentes, sobrescrever propriedades.
+ </para>
+
+ <para>
+ The XML configuration file is by default expected to be in the root o
+ your <literal>CLASSPATH</literal>. Here is an example:
+ O arquivo XML de configuração é por default esperado para estar na
+ raiz do seu <literal>CLASSPATH</literal>. Veja um exemplo:
+ </para>
+
+ <programlisting><![CDATA[<?xml version='1.0'
encoding='utf-8'?>
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+
+ <!-- a SessionFactory instance listed as /jndi/name -->
+ <session-factory
+ name="java:hibernate/SessionFactory">
+
+ <!-- properties -->
+ <property
name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
+ <property
name="dialect">org.hibernate.dialect.MySQLDialect</property>
+ <property name="show_sql">false</property>
+ <property name="transaction.factory_class">
+ org.hibernate.transaction.JTATransactionFactory
+ </property>
+ <property
name="jta.UserTransaction">java:comp/UserTransaction</property>
+
+ <!-- mapping files -->
+ <mapping resource="org/hibernate/auction/Item.hbm.xml"/>
+ <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
+
+ <!-- cache settings -->
+ <class-cache class="org.hibernate.auction.Item"
usage="read-write"/>
+ <class-cache class="org.hibernate.auction.Bid"
usage="read-only"/>
+ <collection-cache collection="org.hibernate.auction.Item.bids"
usage="read-write"/>
+
+ </session-factory>
+
+</hibernate-configuration>]]></programlisting>
+
+ <para>
+ Como você pode ver, a vantagem deste enfoque é a externalização dos nomes dos
+ arquivos de mapeamento para configuração. O
<literal>hibernate.cfg.xml</literal>
+ também é mais conveniente caso você tenha que ajustar o cache do Hibernate.
+ Note que a escolha é sua em usar
<literal>hibernate.properties</literal> ou
+ <literal>hibernate.cfg.xml</literal>, ambos são equivalente, à
exceção dos benefícios
+ acima mencionados de usar a sintaxe de XML.
+ </para>
+
+ <para>
+ Com a configuração do XML, iniciar o Hibernate é então tão simples como
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new
Configuration().configure().buildSessionFactory();]]></programlisting>
+
+ <para>
+ You can pick a different XML configuration file using
+ </para>
+
+ <programlisting><![CDATA[SessionFactory sf = new Configuration()
+ .configure("catdb.cfg.xml")
+ .buildSessionFactory();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="configuration-j2ee" revision="1">
+ <title>Integração com servidores de aplicação J2EE</title>
+
+ <para>
+ O Hibernate tem os seguintes pontos da integração para o infraestrutura de
J2EE:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>DataSources gerenciados pelo container</emphasis>:
O Hibernate pode
+ usar conexões JDBC gerenciadas pelo Container e fornecidas pela JNDI.
Geralmente,
+ um <literal>TransactionManager</literal> compatível com JTA e
um
+ <literal>ResourceManager</literal> cuidam do gerenciamento da
transação ( CMT ),
+ especialmente em transações distribuídas manipuladas através de vários
DataSources.
+ Naturalmente, você também pode demarcar os limites das transações
programaticamente (BMT)
+ ou você poderia querer usar a API opcional do Hibernate
<literal>Transaction</literal>
+ para esta manter seu código portável.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Ligação (binding) automática a JNDI</emphasis>: O
Hibernate pode
+ associar sua <literal>SessionFactory</literal> a JNDI depois
de iniciado.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Ligação (binding) Session na JTA:</emphasis>
+ A <literal>Session</literal> do Hibernate pode
automaticamente ser ligada
+ ao escopo da transações JTA. Simplesmente localizando a
<literal>SessionFactory</literal>
+ da JNDI e obtendo a<literal>Session</literal> corrente. Deixe
o Hibernate cuidar
+ da limpeza e encerramento da <literal>Session</literal>
quando as transações JTA
+ terminarem. A Demarcação de transação pode ser declarativa (CMT) ou
+ programática(BMT/Transação do usuário).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>JMX deployment:</emphasis> Se você usa um JMX
servidor de
+ aplicações capaz (ex. Jboss AS), você pode fazer a instação do Hibernate
+ como um Mbean controlado. Isto evita ter que iniciar uma linha de
+ código para construir sua <literal>SessionFactory</literal>
de uma
+ <literal>Configuration</literal>. O container iniciará seu
+ <literal>HibernateService</literal>, e idealmente também
cuidará
+ das dependências de serviços (DataSources, têm que estar disponíveis
+ antes do Hibernate iniciar, etc.).
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Dependendo em seu ambiente, você poderia ter que ajustar a opção de
configuração
+ <literal>hibernate.connection.aggressive_release</literal> para
verdadeiro ( true ),
+ se seu servidor de aplicações lançar exeções "retenção de
conecção".
+ </para>
+
+ <sect2 id="configuration-optional-transactionstrategy"
revision="3">
+ <title>Configuração de estratégia de transação</title>
+
+ <para>
+ A API Hibernate <literal>Session</literal> é independente de
qualquer sistema de
+ demarcação de transação em sua arquitetura. Se você deixar o Hibernate
usar
+ a JDBC diretamente, através de um pool de conexões, você pode inicializar
e
+ encerrar suas transações chamando a API JDBC. Se você rodar em um
servidor de
+ aplicações J2EE, você poderá usar transações controladas por beans e
chamar
+ a API JTA e <literal>UserTransaction</literal> quando
necessário.
+
+ </para>
+
+ <para>
+ Para manter seu código portável entre estes dois ( e outros ) ambientes,
recomendamos
+ a API Hibernate <literal>Transaction</literal>, que envolve e
esconde o sistema subjacente.
+ Você tem que especificar um classe construtora para
<literal>Transaction</literal> instanciar
+ ajustando a propriedade de configuração do
<literal>hibernate.transaction.factory_class</literal>.
+
+ </para>
+
+ <para>
+ Existem três escolhas (internas) padrões:
+ </para>
+
+ <variablelist spacing="compact">
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.JDBCTransactionFactory</literal></term>
+ <listitem>
+ <para>delegada as transações (JDBC)a bases de dados
(Padrão)</para>
+
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.JTATransactionFactory</literal></term>
+ <listitem>
+ <para>
+ delegada a transação a um container gerenciador se a
transação
+ existente estiver de acordo neste contexto (ex: método bean
sessão EJB),
+ se não uma nova transação é iniciada e uma transação
controlado por
+ um bean é usada.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+
<term><literal>org.hibernate.transaction.CMTTransactionFactory</literal></term>
+ <listitem>
+ <para>delega para um container gerenciador de transações
JTA</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Você também pode definir suas próprias estratégias de transação ( para um
serviço de
+ transação CORBA por exemplo).
+ </para>
+
+ <para>
+ Algumas características no Hibernate (ex., o cache de segundo nível,
sessões contextuais
+ com JTA, etc.) requerem acesso a JTA
<literal>TransactionManager</literal> em um ambiente
+ controlado. Em um servidor de aplicação você tem que especificar como o
Hibernate pode
+ obter uma referência para a
<literal>TransactionManager</literal>, pois o J2EE não
+ padronize um mecanismo simples :
+ </para>
+
+ <table frame="topbot" id="jtamanagerlookup"
revision="1">
+ <title>Gerenciadores de transações JTA</title>
+ <tgroup cols="2">
+ <colspec colwidth="2.5*"/>
+ <colspec colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Transaction Factory</entry>
+ <entry align="center">Application
Server</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>org.hibernate.transaction.JBossTransactionManagerLookup</literal></entry>
+ <entry align="center">JBoss</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WeblogicTransactionManagerLookup</literal></entry>
+ <entry align="center">Weblogic</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WebSphereTransactionManagerLookup</literal></entry>
+ <entry
align="center">WebSphere</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</literal></entry>
+ <entry align="center">WebSphere
6</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.OrionTransactionManagerLookup</literal></entry>
+ <entry align="center">Orion</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.ResinTransactionManagerLookup</literal></entry>
+ <entry align="center">Resin</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JOTMTransactionManagerLookup</literal></entry>
+ <entry align="center">JOTM</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JOnASTransactionManagerLookup</literal></entry>
+ <entry align="center">JOnAS</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.JRun4TransactionManagerLookup</literal></entry>
+ <entry align="center">JRun4</entry>
+ </row>
+ <row>
+
<entry><literal>org.hibernate.transaction.BESTransactionManagerLookup</literal></entry>
+ <entry align="center">Borland
ES</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
+ <sect2 id="configuration-optional-jndi" revision="3">
+ <title><literal>SessionFactory</literal> ligada a
JNDI</title>
+
+ <para>
+ Uma <literal>SessionFactory</literal> de Hibernate ligada a
JNDI pode simplificar
+ a localização da fabrica e a criação de novas
<literal>Session</literal>s.
+ Observe que isto não relacionado a um
<literal>Datasource</literal> ligado
+ a JNDI, simplemente ambos usam o mesmo registro!
+ </para>
+
+ <para>
+ If you wish to have the <literal>SessionFactory</literal>
bound to a JNDI namespace, specify
+ a name (eg. <literal>java:hibernate/SessionFactory</literal>)
using the property
+ <literal>hibernate.session_factory_name</literal>. If this
property is omitted, the
+ <literal>SessionFactory</literal> will not be bound to JNDI.
(This is especially useful in
+ environments with a read-only JNDI default implementation, e.g. Tomcat.)
+ </para>
+
+ <para>
+ When binding the <literal>SessionFactory</literal> to JNDI,
Hibernate will use the values of
+ <literal>hibernate.jndi.url</literal>,
<literal>hibernate.jndi.class</literal> to instantiate
+ an initial context. If they are not specified, the default
<literal>InitialContext</literal>
+ will be used.
+ </para>
+
+ <para>
+ Hibernate will automatically place the
<literal>SessionFactory</literal> in JNDI after
+ you call <literal>cfg.buildSessionFactory()</literal>. This
means you will at least have
+ this call in some startup code (or utility class) in your application,
unless you use
+ JMX deployment with the <literal>HibernateService</literal>
(discussed later).
+ </para>
+
+ <para>
+ If you use a JNDI <literal>SessionFactory</literal>, an EJB
or any other class may
+ obtain the <literal>SessionFactory</literal> using a JNDI
lookup.
+ </para>
+
+ <para>
+ We recommend that you bind the
<literal>SessionFactory</literal> to JNDI in
+ a managend environment and use a <literal>static</literal>
singleton otherwise.
+ To shield your application code from these details, we also recommend to
hide the
+ actual lookup code for a <literal>SessionFactory</literal> in
a helper class,
+ such as <literal>HibernateUtil.getSessionFactory()</literal>.
Note that such a
+ class is also a convenient way to startup Hibernate—see chapter
1.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-j2ee-currentsession"
revision="4">
+ <title>Current Session context management with JTA</title>
+
+ <para>
+ The easiest way to handle <literal>Session</literal>s and
transactions is
+ Hibernates automatic "current"
<literal>Session</literal> management.
+ See the discussion of <xref
linkend="architecture-current-session">current sessions</xref>.
+ Using the <literal>"jta"</literal> session context,
if there is no Hibernate
+ <literal>Session</literal> associated with the current JTA
transaction, one will
+ be started and associated with that JTA transaction the first time you call
+ <literal>sessionFactory.getCurrentSession()</literal>. The
<literal>Session</literal>s
+ retrieved via <literal>getCurrentSession()</literal> in
<literal>"jta"</literal> context
+ will be set to automatically flush before the transaction completes, close
+ after the transaction completes, and aggressively release JDBC connections
+ after each statement. This allows the
<literal>Session</literal>s to
+ be managed by the lifecycle of the JTA transaction to which it is
associated,
+ keeping user code clean of such management concerns. Your code can either
use
+ JTA programmatically through <literal>UserTransaction</literal>,
or (recommended
+ for portable code) use the Hibernate
<literal>Transaction</literal> API to set
+ transaction boundaries. If you run in an EJB container, declarative
transaction
+ demarcation with CMT is preferred.
+ </para>
+
+ </sect2>
+
+ <sect2 id="configuration-j2ee-jmx" revision="1">
+ <title>JMX deployment</title>
+
+ <para>
+ The line <literal>cfg.buildSessionFactory()</literal> still
has to be executed
+ somewhere to get a <literal>SessionFactory</literal> into
JNDI. You can do this
+ either in a <literal>static</literal> initializer block (like
the one in
+ <literal>HibernateUtil</literal>) or you deploy Hibernate as
a <emphasis>managed
+ service</emphasis>.
+ </para>
+
+ <para>
+ Hibernate is distributed with
<literal>org.hibernate.jmx.HibernateService</literal>
+ for deployment on an application server with JMX capabilities, such as
JBoss AS.
+ The actual deployment and configuration is vendor specific. Here is an
example
+ <literal>jboss-service.xml</literal> for JBoss 4.0.x:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"?>
+<server>
+
+<mbean code="org.hibernate.jmx.HibernateService"
+ name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
+
+ <!-- Required services -->
+ <depends>jboss.jca:service=RARDeployer</depends>
+ <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
+
+ <!-- Bind the Hibernate service to JNDI -->
+ <attribute
name="JndiName">java:/hibernate/SessionFactory</attribute>
+
+ <!-- Datasource settings -->
+ <attribute name="Datasource">java:HsqlDS</attribute>
+ <attribute
name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
+
+ <!-- Transaction integration -->
+ <attribute name="TransactionStrategy">
+ org.hibernate.transaction.JTATransactionFactory</attribute>
+ <attribute name="TransactionManagerLookupStrategy">
+ org.hibernate.transaction.JBossTransactionManagerLookup</attribute>
+ <attribute
name="FlushBeforeCompletionEnabled">true</attribute>
+ <attribute name="AutoCloseSessionEnabled">true</attribute>
+
+ <!-- Fetching options -->
+ <attribute name="MaximumFetchDepth">5</attribute>
+
+ <!-- Second-level caching -->
+ <attribute name="SecondLevelCacheEnabled">true</attribute>
+ <attribute
name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>
+ <attribute name="QueryCacheEnabled">true</attribute>
+
+ <!-- Logging -->
+ <attribute name="ShowSqlEnabled">true</attribute>
+
+ <!-- Mapping files -->
+ <attribute
name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>
+
+</mbean>
+
+</server>]]></programlisting>
+
+ <para>
+ This file is deployed in a directory called
<literal>META-INF</literal> and packaged
+ in a JAR file with the extension <literal>.sar</literal>
(service archive). You also need
+ to package Hibernate, its required third-party libraries, your compiled
persistent classes,
+ as well as your mapping files in the same archive. Your enterprise beans
(usually session
+ beans) may be kept in their own JAR file, but you may include this EJB
JAR file in the
+ main service archive to get a single (hot-)deployable unit. Consult the
JBoss AS
+ documentation for more information about JMX service and EJB deployment.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/configuration.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/events.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/events.xml 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/events.xml 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,271 @@
+<chapter id="events">
+ <title>Interceptadores e Eventos</title>
+
+ <para>
+ É muito útil quando a aplicação precisa executar alguma "coisa" no
momento em
+ que o Hibernate executa uma de suas ações. Isso permite a implementação de
+ certas funções genéricas, assim como permite estender as funcionalidades do
+ Hibernate
+ </para>
+
+ <sect1 id="objectstate-interceptors" revision="3">
+ <title>Interceptadores</title>
+
+ <para>
+ A interface <literal>Interceptor</literal> permite fornecer
informações da session para o
+ aplicativo, permitindo ao aplicativo inspecionar e/ou manipular as
propriedades de um
+ objeto persistente antes de ser salvo, atualizado, excluído ou salvo. Um dos
possíveis usos é
+ gerar informações de auditoria. Por exemplo, o seguinte
<literal>Interceptor</literal> seta
+ automaticamente o atributo <literal>createTimestamp</literal>
quando um
+ <literal>Auditable</literal> é criada e atualiza o atributo
<literal>lastUpdateTimestamp</literal>
+ quando um <literal>Auditable</literal> é atualizado.
+ </para>
+
+ <para>
+ Você pode implementar <literal>Auditable</literal> diretamente ou
pode estender
+ <literal>EmptyInterceptor</literal>, sendo que a segunda é
considerada a melhor opção.
+ </para>
+
+ <programlisting><![CDATA[package org.hibernate.test;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Iterator;
+
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.Transaction;
+import org.hibernate.type.Type;
+
+public class AuditInterceptor extends EmptyInterceptor {
+
+ private int updates;
+ private int creates;
+ private int loads;
+
+ public void onDelete(Object entity,
+ Serializable id,
+ Object[] state,
+ String[] propertyNames,
+ Type[] types) {
+ // do nothing
+ }
+
+ public boolean onFlushDirty(Object entity,
+ Serializable id,
+ Object[] currentState,
+ Object[] previousState,
+ String[] propertyNames,
+ Type[] types) {
+
+ if ( entity instanceof Auditable ) {
+ updates++;
+ for ( int i=0; i < propertyNames.length; i++ ) {
+ if ( "lastUpdateTimestamp".equals( propertyNames[i] ) ) {
+ currentState[i] = new Date();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean onLoad(Object entity,
+ Serializable id,
+ Object[] state,
+ String[] propertyNames,
+ Type[] types) {
+ if ( entity instanceof Auditable ) {
+ loads++;
+ }
+ return false;
+ }
+
+ public boolean onSave(Object entity,
+ Serializable id,
+ Object[] state,
+ String[] propertyNames,
+ Type[] types) {
+
+ if ( entity instanceof Auditable ) {
+ creates++;
+ for ( int i=0; i<propertyNames.length; i++ ) {
+ if ( "createTimestamp".equals( propertyNames[i] ) ) {
+ state[i] = new Date();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void afterTransactionCompletion(Transaction tx) {
+ if ( tx.wasCommitted() ) {
+ System.out.println("Creations: " + creates + ", Updates:
" + updates, "Loads: " + loads);
+ }
+ updates=0;
+ creates=0;
+ loads=0;
+ }
+
+}]]></programlisting>
+
+ <para>
+ Os interceptadores podem ser aplicados em dois diferentes escopos:
+ No escopo da <literal>Session</literal> e no escopo
+ <literal>SessionFactory</literal>.
+ </para>
+
+ <para>
+ Um interceptador no escopo da <literal>Session</literal> é
definido quando
+ uma sessão é aberta usando o método sobrecarregado da
SessionFactory.openSession()
+ que aceita um <literal>Interceptor</literal> como parâmetro.
+ </para>
+
+ <programlisting><![CDATA[Session session = sf.openSession( new
AuditInterceptor() );]]></programlisting>
+
+ <para>
+ Um interceptador no escopo da <literal>SessionFactory</literal> é
definido no objeto
+ <literal>Configuration</literal> antes da
<literal>SessionFactory</literal> ser instanciada.
+ Nesse caso, o interceptador fornecido será aplicado para todas as sessões
abertas por aquela
+ <literal>SessionFactory</literal>; Isso apenas não ocorrerá caso
seja especificado um
+ interceptador no momento em que a sessão for aberta. Um interceptador no
escopo de
+ <literal>SessionFactory</literal> deve ser thread safe,
tomando-se o cuidado de não
+ armazenar atributos de estado específicos da sessão, pois, provavelmente,
múltiplas
+ sessões irão utilizar esse interceptador simultaneamente.
+ </para>
+
+ <programlisting><![CDATA[new Configuration().setInterceptor( new
AuditInterceptor() );]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="objectstate-events" revision="4">
+ <title>Sistema de Eventos</title>
+
+ <para>
+ Se você precisa executar uma ação em determinados eventos da camada de
persistência,
+ você também pode usar a arquitetura de <emphasis>event</emphasis>
do Hibernate3.
+ Um evento do sistema pode ser utilizado como complemento ou em
+ substituição a um interceptador.
+ </para>
+
+ <para>
+ Essencialmente todos os métodos da interface
<literal>Session</literal> possuem um evento
+ correlacionado. Se você tiver um <literal>LoadEvent</literal>, um
<literal>LoadEvent</literal>,
+ etc (consulte o DTD do XML de configuração ou o pacote
<literal>org.hibernate.event</literal>
+ para a lista completa dos tipos de eventos). Quando uma requisição é feita em
um desses métodos,
+ a <literal>Session</literal> do hibernate gera um evento
apropriado e o envia para o listener
+ de evento correspondente àquele tipo de evento. Esses listeners implementam a
mesma lógica
+ que aqueles métodos, trazendo os mesmos resultados. Entretanto, você é livre
para implementar
+ uma customização de um desses listeners (isto é, o
<literal>LoadEvent</literal> é processado
+ pela implementação registrada da interface
<literal>LoadEventListener</literal>), então sua
+ implementação vai ficar responsável por processar qualquer requisição
<literal>load()</literal>
+ feita pela <literal>Session</literal>.
+ </para>
+
+ <para>
+ Para todos os efeitos esses listeners deve ser considerados singletons; ou
seja, eles são
+ compartilhados entre as requisições, e assim sendo, não devem salvar nenhum
estado das
+ variáveis instanciadas.
+ </para>
+
+ <para>
+ Um listener personalizado deve implementar a interface referente ao evento a
ser
+ processado e/ou deve estender a classes base equivalente (ou mesmo os
listeners padrões
+ usados pelo Hibernate, eles não são declarados como finais com esse
objetivo). O listener
+ personalizado pode ser registrado programaticamente no objeto
<literal>Configuration</literal>,
+ ou declarativamente no XML de configuração do Hibernate (o registro do
listener no propertie
+ de configuração não é suportado). Aqui temos um exemplo de como carregar um
listener
+ personalizado:
+ </para>
+
+ <programlisting><![CDATA[public class MyLoadListener implements
LoadEventListener {
+ // this is the single method defined by the LoadEventListener interface
+ public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType)
+ throws HibernateException {
+ if ( !MySecurity.isAuthorized( event.getEntityClassName(), event.getEntityId() )
) {
+ throw MySecurityException("Unauthorized access");
+ }
+ }
+}]]></programlisting>
+
+ <para>
+ Você também precisa adicionar uma entrada no XML de configuração do Hibernate
para
+ registrar declarativamente qual listener deve se utilizado em conjunto com o
listener
+ padrão:
+ </para>
+
+<programlisting><![CDATA[<hibernate-configuration>
+ <session-factory>
+ ...
+ <event type="load">
+ <listener class="com.eg.MyLoadListener"/>
+ <listener
class="org.hibernate.event.def.DefaultLoadEventListener"/>
+ </event>
+ </session-factory>
+</hibernate-configuration>]]></programlisting>
+
+ <para>
+ Ou, você pode registrar o listener programaticamente:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = new Configuration();
+LoadEventListener[] stack = { new MyLoadListener(), new DefaultLoadEventListener() };
+cfg.EventListeners().setLoadEventListeners(stack);]]></programlisting>
+
+ <para>
+ Listeners registrados declarativamente não compartilham da mesma instancia.
Se o mesmo
+ nome da classe é utilizado em vários elementos e
<literal><listener/></literal>,
+ cada um vai resultar em uma instancia separada dessa classe. Se você tem a
necessidade
+ de compartilhar uma instancia de um listener entre diversos tipos de
listeners você
+ deve registrar o listener programaticamente.
+
+ </para>
+
+ <para>
+ Mas porque implementar uma interface e definir o tipo específico durante a
configuração?
+ Bem, um listener pode implementar vários listeners de evento. Com o tipo
sendo definido
+ durante o registro, fica fácil ligar ou desligar listeners personalizados
durante
+ a configuração.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-decl-security" revision="2">
+ <title>Hibernate declarative security</title>
+ <para>
+ Usually, declarative security in Hibernate applications is managed in a
session facade
+ layer. Now, Hibernate3 allows certain actions to be permissioned via JACC,
and authorized
+ via JAAS. This is optional functionality built on top of the event
architecture.
+ </para>
+
+ <para>
+ First, you must configure the appropriate event listeners, to enable the use
of JAAS
+ authorization.
+ </para>
+
+ <programlisting><![CDATA[<listener type="pre-delete"
class="org.hibernate.secure.JACCPreDeleteEventListener"/>
+<listener type="pre-update"
class="org.hibernate.secure.JACCPreUpdateEventListener"/>
+<listener type="pre-insert"
class="org.hibernate.secure.JACCPreInsertEventListener"/>
+<listener type="pre-load"
class="org.hibernate.secure.JACCPreLoadEventListener"/>]]></programlisting>
+
+ <para>
+ Note that <literal><listener type="..."
class="..."/></literal> is just a shorthand
+ for <literal><event type="..."><listener
class="..."/></event></literal>
+ when there is exactly one listener for a particular event type.
+ </para>
+
+ <para>
+ Next, still in <literal>hibernate.cfg.xml</literal>, bind the
permissions to roles:
+ </para>
+
+ <programlisting><![CDATA[<grant role="admin"
entity-name="User" actions="insert,update,read"/>
+<grant role="su" entity-name="User"
actions="*"/>]]></programlisting>
+
+ <para>
+ The role names are the roles understood by your JACC provider.
+ </para>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/events.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/example_mappings.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/example_mappings.xml 2006-08-14 14:43:45
UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/example_mappings.xml 2006-08-14 14:55:10
UTC (rev 10262)
@@ -0,0 +1,663 @@
+<chapter id="example-mappings">
+ <title>Exemplo: Vários Mapeamentos</title>
+
+ <para>
+ Este capitulo mostra algums mapeamentos de associações mais complexos.
+ </para>
+
+ <sect1 id="example-mappings-emp">
+ <title>Employer/Employee</title>
+
+ <para>
+ O modelo de seguinte relacionamento entre
<literal>Employer</literal> e
+ <literal>Employee</literal> utiliza uma entidade de classe atual
(<literal>Employment</literal>)
+ para representar a associação. Isto é feito porque pode-ser ter mais do que
um período de
+ trabalho para as duas partes envolvidas. Outros Componentes são usados para
modelar
+ valores monetários e os nomes do empregado.
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/EmployerEmployee.gif"
format="GIF" align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="../shared/images/EmployerEmployee.gif"
format="GIF" align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ Abaixo o código de um possível mapeamento:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Employer" table="employers">
+ <id name="id">
+ <generator class="sequence">
+ <param name="sequence">employer_id_seq</param>
+ </generator>
+ </id>
+ <property name="name"/>
+ </class>
+
+ <class name="Employment" table="employment_periods">
+
+ <id name="id">
+ <generator class="sequence">
+ <param name="sequence">employment_id_seq</param>
+ </generator>
+ </id>
+ <property name="startDate" column="start_date"/>
+ <property name="endDate" column="end_date"/>
+
+ <component name="hourlyRate" class="MonetaryAmount">
+ <property name="amount">
+ <column name="hourly_rate" sql-type="NUMERIC(12,
2)"/>
+ </property>
+ <property name="currency" length="12"/>
+ </component>
+
+ <many-to-one name="employer" column="employer_id"
not-null="true"/>
+ <many-to-one name="employee" column="employee_id"
not-null="true"/>
+
+ </class>
+
+ <class name="Employee" table="employees">
+ <id name="id">
+ <generator class="sequence">
+ <param name="sequence">employee_id_seq</param>
+ </generator>
+ </id>
+ <property name="taxfileNumber"/>
+ <component name="name" class="Name">
+ <property name="firstName"/>
+ <property name="initial"/>
+ <property name="lastName"/>
+ </component>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ E abaixo o esquema da tabela gerado pelo
<literal>SchemaExport</literal>.
+ </para>
+
+ <programlisting><![CDATA[create table employers (
+ id BIGINT not null,
+ name VARCHAR(255),
+ primary key (id)
+)
+
+create table employment_periods (
+ id BIGINT not null,
+ hourly_rate NUMERIC(12, 2),
+ currency VARCHAR(12),
+ employee_id BIGINT not null,
+ employer_id BIGINT not null,
+ end_date TIMESTAMP,
+ start_date TIMESTAMP,
+ primary key (id)
+)
+
+create table employees (
+ id BIGINT not null,
+ firstName VARCHAR(255),
+ initial CHAR(1),
+ lastName VARCHAR(255),
+ taxfileNumber VARCHAR(255),
+ primary key (id)
+)
+
+alter table employment_periods
+ add constraint employment_periodsFK0 foreign key (employer_id) references employers
+alter table employment_periods
+ add constraint employment_periodsFK1 foreign key (employee_id) references employees
+create sequence employee_id_seq
+create sequence employment_id_seq
+create sequence employer_id_seq]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="example-mappings-authorwork">
+ <title>Author/Work</title>
+
+ <para>
+ Considere o seguinte modelo de relacionamento entre
<literal>Work</literal>,
+ <literal>Author</literal> e
<literal>Person</literal>. Nós representamos o relacionamento
+ entre <literal>Work</literal> e
<literal>Author</literal> como uma associação
+ muitos-para-muitos. Nós escolhemos representar o relacionamento entre
<literal>Author</literal>
+ e <literal>Person</literal> como uma associação um-para-um. Outra
possibilidade seria ter
+ <literal>Author</literal> extendendo
<literal>Person</literal>.
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/AuthorWork.gif"
format="GIF" align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata fileref="../shared/images/AuthorWork.gif"
format="GIF" align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ O mapeamento do código seguinte representa corretamente estes
relacionamentos:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Work" table="works"
discriminator-value="W">
+
+ <id name="id" column="id">
+ <generator class="native"/>
+ </id>
+ <discriminator column="type" type="character"/>
+
+ <property name="title"/>
+ <set name="authors" table="author_work">
+ <key column name="work_id"/>
+ <many-to-many class="Author" column
name="author_id"/>
+ </set>
+
+ <subclass name="Book" discriminator-value="B">
+ <property name="text"/>
+ </subclass>
+
+ <subclass name="Song" discriminator-value="S">
+ <property name="tempo"/>
+ <property name="genre"/>
+ </subclass>
+
+ </class>
+
+ <class name="Author" table="authors">
+
+ <id name="id" column="id">
+ <!-- The Author must have the same identifier as the Person -->
+ <generator class="assigned"/>
+ </id>
+
+ <property name="alias"/>
+ <one-to-one name="person" constrained="true"/>
+
+ <set name="works" table="author_work"
inverse="true">
+ <key column="author_id"/>
+ <many-to-many class="Work" column="work_id"/>
+ </set>
+
+ </class>
+
+ <class name="Person" table="persons">
+ <id name="id" column="id">
+ <generator class="native"/>
+ </id>
+ <property name="name"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ There are four tables in this mapping. <literal>works</literal>,
+ <literal>authors</literal> and <literal>persons</literal>
hold work, author
+ and person data respectively. <literal>author_work</literal> is an
association
+ table linking authors to works. Heres the table schema, as generated by
+ <literal>SchemaExport</literal>.
+ Existem quatro tabelas neste mapeamento. <literal>works</literal>,
+ <literal>authors</literal> e <literal>persons</literal>
recebem os dados de work,
+ author e person, respectivamente. <literal>author_work</literal> é
uma tabela de
+ associação que liga authors à works. Abaixo o esquema das tabelas, gerados pelo
+ <literal>SchemaExport</literal>.
+ </para>
+
+ <programlisting><![CDATA[create table works (
+ id BIGINT not null generated by default as identity,
+ tempo FLOAT,
+ genre VARCHAR(255),
+ text INTEGER,
+ title VARCHAR(255),
+ type CHAR(1) not null,
+ primary key (id)
+)
+
+create table author_work (
+ author_id BIGINT not null,
+ work_id BIGINT not null,
+ primary key (work_id, author_id)
+)
+
+create table authors (
+ id BIGINT not null generated by default as identity,
+ alias VARCHAR(255),
+ primary key (id)
+)
+
+create table persons (
+ id BIGINT not null generated by default as identity,
+ name VARCHAR(255),
+ primary key (id)
+)
+
+alter table authors
+ add constraint authorsFK0 foreign key (id) references persons
+alter table author_work
+ add constraint author_workFK0 foreign key (author_id) references authors
+alter table author_work
+ add constraint author_workFK1 foreign key (work_id) references
works]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="example-mappings-customerorderproduct">
+ <title>Customer/Order/Product</title>
+
+ <para>
+ Agora considere um modelo de relacionamento entre
<literal>Customer</literal>,
+ <literal>Order</literal> e
<literal>LineItem</literal> e <literal>Product</literal>.
+ Existe uma associação um-para-muitos entre
<literal>Customer</literal> e
+ <literal>Order</literal>, mas como devemos representar
<literal>Order</literal> /
+ <literal>LineItem</literal> /
<literal>Product</literal>? Eu escolhi mapear LineItem
+ como uma classe de associação representando a associação muitos-para-muitos
entre
+ <literal>Order</literal> and
<literal>Product</literal>. No Hibernate, isto é conhecido
+ como um elemento composto.
+ </para>
+
+ <mediaobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/CustomerOrderProduct.gif"
format="GIF" align="center"/>
+ </imageobject>
+ <imageobject role="html">
+ <imagedata
fileref="../shared/images/CustomerOrderProduct.gif" format="GIF"
align="center"/>
+ </imageobject>
+ </mediaobject>
+
+ <para>
+ O código do mapeamento:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="Customer" table="customers">
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="name"/>
+ <set name="orders" inverse="true">
+ <key column="customer_id"/>
+ <one-to-many class="Order"/>
+ </set>
+ </class>
+
+ <class name="Order" table="orders">
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="date"/>
+ <many-to-one name="customer" column="customer_id"/>
+ <list name="lineItems" table="line_items">
+ <key column="order_id"/>
+ <list-index column="line_number"/>
+ <composite-element class="LineItem">
+ <property name="quantity"/>
+ <many-to-one name="product"
column="product_id"/>
+ </composite-element>
+ </list>
+ </class>
+
+ <class name="Product" table="products">
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="serialNumber"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ <literal>customers</literal>, <literal>orders</literal>,
<literal>line_items</literal> e
+ <literal>products</literal> recebem os dados de customer, order,
line_item e product,
+ respectivamente. <literal>line_items</literal> também atua como uma
tabela de associação
+ ligando orders com products.
+ </para>
+
+ <programlisting><![CDATA[create table customers (
+ id BIGINT not null generated by default as identity,
+ name VARCHAR(255),
+ primary key (id)
+)
+
+create table orders (
+ id BIGINT not null generated by default as identity,
+ customer_id BIGINT,
+ date TIMESTAMP,
+ primary key (id)
+)
+
+create table line_items (
+ line_number INTEGER not null,
+ order_id BIGINT not null,
+ product_id BIGINT,
+ quantity INTEGER,
+ primary key (order_id, line_number)
+)
+
+create table products (
+ id BIGINT not null generated by default as identity,
+ serialNumber VARCHAR(255),
+ primary key (id)
+)
+
+alter table orders
+ add constraint ordersFK0 foreign key (customer_id) references customers
+alter table line_items
+ add constraint line_itemsFK0 foreign key (product_id) references products
+alter table line_items
+ add constraint line_itemsFK1 foreign key (order_id) references
orders]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="misc">
+ <title>Exemplos variados de mapeamento</title>
+
+ <para>
+ Todos estes exemplos são retirados do conjunto de testes do Hibernate.
+ Lá, você encontrará vários outros exemplos úteis de mapeamentos.
+ Verifique o diretorio <literal>test</literal> da distribuição do
Hibernate.
+ </para>
+
+ <para>TODO: put words around this stuff</para>
+
+ <sect2 id="example-mappings-typed-onetone">
+ <title>Associação um-para-um "Tipadas"</title>
+<programlisting><![CDATA[<class name="Person">
+ <id name="name"/>
+ <one-to-one name="address"
+ cascade="all">
+ <formula>name</formula>
+ <formula>'HOME'</formula>
+ </one-to-one>
+ <one-to-one name="mailingAddress"
+ cascade="all">
+ <formula>name</formula>
+ <formula>'MAILING'</formula>
+ </one-to-one>
+</class>
+
+<class name="Address" batch-size="2"
+ check="addressType in ('MAILING', 'HOME',
'BUSINESS')">
+ <composite-id>
+ <key-many-to-one name="person"
+ column="personName"/>
+ <key-property name="type"
+ column="addressType"/>
+ </composite-id>
+ <property name="street" type="text"/>
+ <property name="state"/>
+ <property name="zip"/>
+</class>]]></programlisting>
+ </sect2>
+
+ <sect2 id="example-mappings-composite-key">
+ <title>Exemplo de chave composta</title>
+<programlisting><![CDATA[<class name="Customer">
+
+ <id name="customerId"
+ length="10">
+ <generator class="assigned"/>
+ </id>
+
+ <property name="name" not-null="true"
length="100"/>
+ <property name="address" not-null="true"
length="200"/>
+
+ <list name="orders"
+ inverse="true"
+ cascade="save-update">
+ <key column="customerId"/>
+ <index column="orderNumber"/>
+ <one-to-many class="Order"/>
+ </list>
+
+</class>
+
+<class name="Order" table="CustomerOrder"
lazy="true">
+ <synchronize table="LineItem"/>
+ <synchronize table="Product"/>
+
+ <composite-id name="id"
+ class="Order$Id">
+ <key-property name="customerId" length="10"/>
+ <key-property name="orderNumber"/>
+ </composite-id>
+
+ <property name="orderDate"
+ type="calendar_date"
+ not-null="true"/>
+
+ <property name="total">
+ <formula>
+ ( select sum(li.quantity*p.price)
+ from LineItem li, Product p
+ where li.productId = p.productId
+ and li.customerId = customerId
+ and li.orderNumber = orderNumber )
+ </formula>
+ </property>
+
+ <many-to-one name="customer"
+ column="customerId"
+ insert="false"
+ update="false"
+ not-null="true"/>
+
+ <bag name="lineItems"
+ fetch="join"
+ inverse="true"
+ cascade="save-update">
+ <key>
+ <column name="customerId"/>
+ <column name="orderNumber"/>
+ </key>
+ <one-to-many class="LineItem"/>
+ </bag>
+
+</class>
+
+<class name="LineItem">
+
+ <composite-id name="id"
+ class="LineItem$Id">
+ <key-property name="customerId" length="10"/>
+ <key-property name="orderNumber"/>
+ <key-property name="productId" length="10"/>
+ </composite-id>
+
+ <property name="quantity"/>
+
+ <many-to-one name="order"
+ insert="false"
+ update="false"
+ not-null="true">
+ <column name="customerId"/>
+ <column name="orderNumber"/>
+ </many-to-one>
+
+ <many-to-one name="product"
+ insert="false"
+ update="false"
+ not-null="true"
+ column="productId"/>
+
+</class>
+
+<class name="Product">
+ <synchronize table="LineItem"/>
+
+ <id name="productId"
+ length="10">
+ <generator class="assigned"/>
+ </id>
+
+ <property name="description"
+ not-null="true"
+ length="200"/>
+ <property name="price" length="3"/>
+ <property name="numberAvailable"/>
+
+ <property name="numberOrdered">
+ <formula>
+ ( select sum(li.quantity)
+ from LineItem li
+ where li.productId = productId )
+ </formula>
+ </property>
+
+</class>]]></programlisting>
+ </sect2>
+
+ <sect2 id="example-mappings-composite-key-manytomany">
+ <title>Mmuitos-para-muitos com atributo de chave composta
compartilhada</title>
+<programlisting><![CDATA[<class name="User"
table="`User`">
+ <composite-id>
+ <key-property name="name"/>
+ <key-property name="org"/>
+ </composite-id>
+ <set name="groups" table="UserGroup">
+ <key>
+ <column name="userName"/>
+ <column name="org"/>
+ </key>
+ <many-to-many class="Group">
+ <column name="groupName"/>
+ <formula>org</formula>
+ </many-to-many>
+ </set>
+</class>
+
+<class name="Group" table="`Group`">
+ <composite-id>
+ <key-property name="name"/>
+ <key-property name="org"/>
+ </composite-id>
+ <property name="description"/>
+ <set name="users" table="UserGroup"
inverse="true">
+ <key>
+ <column name="groupName"/>
+ <column name="org"/>
+ </key>
+ <many-to-many class="User">
+ <column name="userName"/>
+ <formula>org</formula>
+ </many-to-many>
+ </set>
+</class>
+]]></programlisting>
+ </sect2>
+
+ <sect2 id="example-mappings-content-discrimination">
+ <title>Conteúdo baseado em descriminação</title>
+<programlisting><![CDATA[<class name="Person"
+ discriminator-value="P">
+
+ <id name="id"
+ column="person_id"
+ unsaved-value="0">
+ <generator class="native"/>
+ </id>
+
+
+ <discriminator
+ type="character">
+ <formula>
+ case
+ when title is not null then 'E'
+ when salesperson is not null then 'C'
+ else 'P'
+ end
+ </formula>
+ </discriminator>
+
+ <property name="name"
+ not-null="true"
+ length="80"/>
+
+ <property name="sex"
+ not-null="true"
+ update="false"/>
+
+ <component name="address">
+ <property name="address"/>
+ <property name="zip"/>
+ <property name="country"/>
+ </component>
+
+ <subclass name="Employee"
+ discriminator-value="E">
+ <property name="title"
+ length="20"/>
+ <property name="salary"/>
+ <many-to-one name="manager"/>
+ </subclass>
+
+ <subclass name="Customer"
+ discriminator-value="C">
+ <property name="comments"/>
+ <many-to-one name="salesperson"/>
+ </subclass>
+
+</class>]]></programlisting>
+ </sect2>
+
+ <sect2 id="example-mappings-association-alternatekeys"
revision="2">
+ <title>Associações em chaves alternativas</title>
+<programlisting><![CDATA[<class name="Person">
+
+ <id name="id">
+ <generator class="hilo"/>
+ </id>
+
+ <property name="name" length="100"/>
+
+ <one-to-one name="address"
+ property-ref="person"
+ cascade="all"
+ fetch="join"/>
+
+ <set name="accounts"
+ inverse="true">
+ <key column="userId"
+ property-ref="userId"/>
+ <one-to-many class="Account"/>
+ </set>
+
+ <property name="userId" length="8"/>
+
+</class>
+
+<class name="Address">
+
+ <id name="id">
+ <generator class="hilo"/>
+ </id>
+
+ <property name="address" length="300"/>
+ <property name="zip" length="5"/>
+ <property name="country" length="25"/>
+ <many-to-one name="person" unique="true"
not-null="true"/>
+
+</class>
+
+<class name="Account">
+ <id name="accountId" length="32">
+ <generator class="uuid"/>
+ </id>
+
+ <many-to-one name="user"
+ column="userId"
+ property-ref="userId"/>
+
+ <property name="type" not-null="true"/>
+
+</class>]]></programlisting>
+ </sect2>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/example_mappings.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/example_parentchild.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/example_parentchild.xml 2006-08-14
14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/example_parentchild.xml 2006-08-14
14:55:10 UTC (rev 10262)
@@ -0,0 +1,361 @@
+<chapter id="example-parentchild">
+ <title>Example: Parent/Child</title>
+
+ <para>
+ One of the very first things that new users try to do with Hibernate is to model
a parent / child type
+ relationship. There are two different approaches to this. For various reasons the
most convenient
+ approach, especially for new users, is to model both
<literal>Parent</literal> and <literal>Child</literal>
+ as entity classes with a
<literal><one-to-many></literal> association from
<literal>Parent</literal>
+ to <literal>Child</literal>. (The alternative approach is to declare
the <literal>Child</literal> as a
+ <literal><composite-element></literal>.) Now, it turns
out that default semantics of a one to many
+ association (in Hibernate) are much less close to the usual semantics of a parent
/ child relationship than
+ those of a composite element mapping. We will explain how to use a
<emphasis>bidirectional one to many
+ association with cascades</emphasis> to model a parent / child relationship
efficiently and elegantly.
+ It's not at all difficult!
+ </para>
+
+ <sect1 id="example-parentchild-collections">
+ <title>A note about collections</title>
+
+ <para>
+ Hibernate collections are considered to be a logical part of their owning
entity; never of the
+ contained entities. This is a crucial distinction! It has the following
consequences:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ When we remove / add an object from / to a collection, the version number
of the collection owner
+ is incremented.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If an object that was removed from a collection is an instance of a value
type (eg, a composite
+ element), that object will cease to be persistent and its state will be
completely removed from
+ the database. Likewise, adding a value type instance to the collection
will cause its state to be
+ immediately persistent.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ On the other hand, if an entity is removed from a collection (a
one-to-many or many-to-many
+ association), it will not be deleted, by default. This behaviour is
completely consistent - a
+ change to the internal state of another entity should not cause the
associated entity to vanish!
+ Likewise, adding an entity to a collection does not cause that entity to
become persistent, by
+ default.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Instead, the default behaviour is that adding an entity to a collection
merely creates a link between
+ the two entities, while removing it removes the link. This is very
appropriate for all sorts of cases.
+ Where it is not appropriate at all is the case of a parent / child
relationship, where the life of the
+ child is bound to the lifecycle of the parent.
+ </para>
+
+ </sect1>
+
+ <sect1 id="example-parentchild-bidir">
+ <title>Bidirectional one-to-many</title>
+
+ <para>
+ Suppose we start with a simple
<literal><one-to-many></literal> association from
+ <literal>Parent</literal> to
<literal>Child</literal>.
+ </para>
+
+ <programlisting><![CDATA[<set name="children">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+</set>]]></programlisting>
+
+ <para>
+ If we were to execute the following code
+ </para>
+
+ <programlisting><![CDATA[Parent p = .....;
+Child c = new Child();
+p.getChildren().add(c);
+session.save(c);
+session.flush();]]></programlisting>
+
+ <para>
+ Hibernate would issue two SQL statements:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>an <literal>INSERT</literal> to create the record for
<literal>c</literal></para>
+ </listitem>
+ <listitem>
+ <para>
+ an <literal>UPDATE</literal> to create the link from
<literal>p</literal> to
+ <literal>c</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ This is not only inefficient, but also violates any <literal>NOT
NULL</literal> constraint on the
+ <literal>parent_id</literal> column. We can fix the nullability
constraint violation by specifying
+ <literal>not-null="true"</literal> in the collection
mapping:
+ </para>
+
+ <programlisting><![CDATA[<set name="children">
+ <key column="parent_id" not-null="true"/>
+ <one-to-many class="Child"/>
+</set>]]></programlisting>
+
+ <para>
+ However, this is not the recommended solution.
+ </para>
+ <para>
+ The underlying cause of this behaviour is that the link (the foreign key
<literal>parent_id</literal>)
+ from <literal>p</literal> to <literal>c</literal> is
not considered part of the state of the
+ <literal>Child</literal> object and is therefore not created in
the <literal>INSERT</literal>. So the
+ solution is to make the link part of the <literal>Child</literal>
mapping.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="parent"
column="parent_id" not-null="true"/>]]></programlisting>
+
+ <para>
+ (We also need to add the <literal>parent</literal> property to
the <literal>Child</literal> class.)
+ </para>
+
+ <para>
+ Now that the <literal>Child</literal> entity is managing the
state of the link, we tell the collection
+ not to update the link. We use the <literal>inverse</literal>
attribute.
+ </para>
+
+ <programlisting><![CDATA[<set name="children"
inverse="true">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+</set>]]></programlisting>
+
+ <para>
+ The following code would be used to add a new
<literal>Child</literal>
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+Child c = new Child();
+c.setParent(p);
+p.getChildren().add(c);
+session.save(c);
+session.flush();]]></programlisting>
+
+ <para>
+ And now, only one SQL <literal>INSERT</literal> would be issued!
+ </para>
+
+ <para>
+ To tighten things up a bit, we could create an
<literal>addChild()</literal> method of
+ <literal>Parent</literal>.
+ </para>
+
+ <programlisting><![CDATA[public void addChild(Child c) {
+ c.setParent(this);
+ children.add(c);
+}]]></programlisting>
+
+ <para>
+ Now, the code to add a <literal>Child</literal> looks like
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+Child c = new Child();
+p.addChild(c);
+session.save(c);
+session.flush();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="example-parentchild-cascades">
+ <title>Cascading lifecycle</title>
+
+ <para>
+ The explicit call to <literal>save()</literal> is still
annoying. We will address this by
+ using cascades.
+ </para>
+
+ <programlisting><![CDATA[<set name="children"
inverse="true" cascade="all">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+</set>]]></programlisting>
+
+ <para>
+ This simplifies the code above to
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+Child c = new Child();
+p.addChild(c);
+session.flush();]]></programlisting>
+
+ <para>
+ Similarly, we don't need to iterate over the children when saving or
deleting a <literal>Parent</literal>.
+ The following removes <literal>p</literal> and all its children
from the database.
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+session.delete(p);
+session.flush();]]></programlisting>
+
+ <para>
+ However, this code
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+Child c = (Child) p.getChildren().iterator().next();
+p.getChildren().remove(c);
+c.setParent(null);
+session.flush();]]></programlisting>
+
+ <para>
+ will not remove <literal>c</literal> from the database; it will
ony remove the link to <literal>p</literal>
+ (and cause a <literal>NOT NULL</literal> constraint violation,
in this case). You need to explicitly
+ <literal>delete()</literal> the
<literal>Child</literal>.
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) session.load(Parent.class,
pid);
+Child c = (Child) p.getChildren().iterator().next();
+p.getChildren().remove(c);
+session.delete(c);
+session.flush();]]></programlisting>
+
+ <para>
+ Now, in our case, a <literal>Child</literal> can't really
exist without its parent. So if we remove
+ a <literal>Child</literal> from the collection, we really do
want it to be deleted. For this, we must
+ use <literal>cascade="all-delete-orphan"</literal>.
+ </para>
+
+ <programlisting><![CDATA[<set name="children"
inverse="true" cascade="all-delete-orphan">
+ <key column="parent_id"/>
+ <one-to-many class="Child"/>
+</set>]]></programlisting>
+
+ <para>
+ Note: even though the collection mapping specifies
<literal>inverse="true"</literal>, cascades are
+ still processed by iterating the collection elements. So if you require that
an object be saved,
+ deleted or updated by cascade, you must add it to the collection. It is not
enough to simply call
+ <literal>setParent()</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="example-parentchild-update">
+ <title>Cascades and
<literal>unsaved-value</literal></title>
+
+ <para>
+ Suppose we loaded up a <literal>Parent</literal> in one
<literal>Session</literal>, made some changes
+ in a UI action and wish to persist these changes in a new session by calling
<literal>update()</literal>.
+ The <literal>Parent</literal> will contain a collection of
childen and, since cascading update is enabled,
+ Hibernate needs to know which children are newly instantiated and which
represent existing rows in the
+ database. Lets assume that both <literal>Parent</literal> and
<literal>Child</literal> have genenerated
+ identifier properties of type <literal>Long</literal>. Hibernate
will use the identifier and
+ version/timestamp property value to determine which of the children are new.
(See
+ <xref linkend="objectstate-saveorupdate"/>.)
<emphasis>In Hibernate3, it is no longer necessary to specify
+ an <literal>unsaved-value</literal>
explicitly.</emphasis>
+ </para>
+
+ <para>
+ The following code will update <literal>parent</literal> and
<literal>child</literal> and insert
+ <literal>newChild</literal>.
+ </para>
+
+ <programlisting><![CDATA[//parent and child were both loaded in a
previous session
+parent.addChild(child);
+Child newChild = new Child();
+parent.addChild(newChild);
+session.update(parent);
+session.flush();]]></programlisting>
+
+ <para>
+ Well, that's all very well for the case of a generated identifier, but
what about assigned identifiers
+ and composite identifiers? This is more difficult, since Hibernate can't
use the identifier property to
+ distinguish between a newly instantiated object (with an identifier assigned
by the user) and an
+ object loaded in a previous session. In this case, Hibernate will either use
the timestamp or version
+ property, or will actually query the second-level cache or, worst case, the
database, to see if the
+ row exists.
+ </para>
+
+ <!-- undocumenting
+ <para>
+ There is one further possibility. The
<literal>Interceptor</literal> method named
+ <literal>isUnsaved()</literal> lets the application implement
its own strategy for distinguishing
+ newly instantiated objects. For example, you could define a base class for
your persistent classes.
+ </para>
+
+ <programlisting><![CDATA[public class Persistent {
+ private boolean _saved = false;
+ public void onSave() {
+ _saved=true;
+ }
+ public void onLoad() {
+ _saved=true;
+ }
+ ......
+ public boolean isSaved() {
+ return _saved;
+ }
+}]]></programlisting>
+
+ <para>
+ (The <literal>saved</literal> property is non-persistent.)
+ Now implement <literal>isUnsaved()</literal>, along with
<literal>onLoad()</literal>
+ and <literal>onSave()</literal> as follows.
+ </para>
+
+ <programlisting><![CDATA[public Boolean isUnsaved(Object entity) {
+ if (entity instanceof Persistent) {
+ return new Boolean( !( (Persistent) entity ).isSaved() );
+ }
+ else {
+ return null;
+ }
+}
+
+public boolean onLoad(Object entity,
+ Serializable id,
+ Object[] state,
+ String[] propertyNames,
+ Type[] types) {
+
+ if (entity instanceof Persistent) ( (Persistent) entity ).onLoad();
+ return false;
+}
+
+public boolean onSave(Object entity,
+ Serializable id,
+ Object[] state,
+ String[] propertyNames,
+ Type[] types) {
+
+ if (entity instanceof Persistent) ( (Persistent) entity ).onSave();
+ return false;
+}]]></programlisting>
+
+ <para>
+ Don't worry; in Hibernate3 you don't need to write any of this kind of code if
you don't want to.
+ </para>
+ -->
+ </sect1>
+
+ <sect1 id="example-parentchild-conclusion">
+ <title>Conclusion</title>
+
+ <para>
+ There is quite a bit to digest here and it might look confusing first time
around. However, in practice,
+ it all works out very nicely. Most Hibernate applications use the parent /
child pattern in many places.
+ </para>
+
+ <para>
+ We mentioned an alternative in the first paragraph. None of the above issues
exist in the case of
+ <literal><composite-element></literal> mappings,
which have exactly the semantics of a parent / child
+ relationship. Unfortunately, there are two big limitations to composite
element classes: composite elements
+ may not own collections, and they should not be the child of any entity
other than the unique parent.
+ </para>
+
+ </sect1>
+
+</chapter>
\ No newline at end of file
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/example_parentchild.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/example_weblog.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/example_weblog.xml 2006-08-14 14:43:45
UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/example_weblog.xml 2006-08-14 14:55:10
UTC (rev 10262)
@@ -0,0 +1,430 @@
+<chapter id="example-weblog">
+ <title>Example: Weblog Application</title>
+
+ <sect1 id="example-weblog-classes">
+ <title>Persistent Classes</title>
+
+ <para>
+ The persistent classes represent a weblog, and an item posted
+ in a weblog. They are to be modelled as a standard parent/child
+ relationship, but we will use an ordered bag, instead of a set.
+ </para>
+
+ <programlisting><![CDATA[package eg;
+
+import java.util.List;
+
+public class Blog {
+ private Long _id;
+ private String _name;
+ private List _items;
+
+ public Long getId() {
+ return _id;
+ }
+ public List getItems() {
+ return _items;
+ }
+ public String getName() {
+ return _name;
+ }
+ public void setId(Long long1) {
+ _id = long1;
+ }
+ public void setItems(List list) {
+ _items = list;
+ }
+ public void setName(String string) {
+ _name = string;
+ }
+}]]></programlisting>
+
+ <programlisting><![CDATA[package eg;
+
+import java.text.DateFormat;
+import java.util.Calendar;
+
+public class BlogItem {
+ private Long _id;
+ private Calendar _datetime;
+ private String _text;
+ private String _title;
+ private Blog _blog;
+
+ public Blog getBlog() {
+ return _blog;
+ }
+ public Calendar getDatetime() {
+ return _datetime;
+ }
+ public Long getId() {
+ return _id;
+ }
+ public String getText() {
+ return _text;
+ }
+ public String getTitle() {
+ return _title;
+ }
+ public void setBlog(Blog blog) {
+ _blog = blog;
+ }
+ public void setDatetime(Calendar calendar) {
+ _datetime = calendar;
+ }
+ public void setId(Long long1) {
+ _id = long1;
+ }
+ public void setText(String string) {
+ _text = string;
+ }
+ public void setTitle(String string) {
+ _title = string;
+ }
+}]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="example-weblog-mappings">
+ <title>Hibernate Mappings</title>
+
+ <para>
+ The XML mappings should now be quite straightforward.
+ </para>
+
+ <programlisting><![CDATA[<?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="eg">
+
+ <class
+ name="Blog"
+ table="BLOGS">
+
+ <id
+ name="id"
+ column="BLOG_ID">
+
+ <generator class="native"/>
+
+ </id>
+
+ <property
+ name="name"
+ column="NAME"
+ not-null="true"
+ unique="true"/>
+
+ <bag
+ name="items"
+ inverse="true"
+ order-by="DATE_TIME"
+ cascade="all">
+
+ <key column="BLOG_ID"/>
+ <one-to-many class="BlogItem"/>
+
+ </bag>
+
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <programlisting><![CDATA[<?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="eg">
+
+ <class
+ name="BlogItem"
+ table="BLOG_ITEMS"
+ dynamic-update="true">
+
+ <id
+ name="id"
+ column="BLOG_ITEM_ID">
+
+ <generator class="native"/>
+
+ </id>
+
+ <property
+ name="title"
+ column="TITLE"
+ not-null="true"/>
+
+ <property
+ name="text"
+ column="TEXT"
+ not-null="true"/>
+
+ <property
+ name="datetime"
+ column="DATE_TIME"
+ not-null="true"/>
+
+ <many-to-one
+ name="blog"
+ column="BLOG_ID"
+ not-null="true"/>
+
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="example-weblog-code">
+ <title>Hibernate Code</title>
+
+ <para>
+ The following class demonstrates some of the kinds of things
+ we can do with these classes, using Hibernate.
+ </para>
+
+ <programlisting><![CDATA[package eg;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.List;
+
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+
+public class BlogMain {
+
+ private SessionFactory _sessions;
+
+ public void configure() throws HibernateException {
+ _sessions = new Configuration()
+ .addClass(Blog.class)
+ .addClass(BlogItem.class)
+ .buildSessionFactory();
+ }
+
+ public void exportTables() throws HibernateException {
+ Configuration cfg = new Configuration()
+ .addClass(Blog.class)
+ .addClass(BlogItem.class);
+ new SchemaExport(cfg).create(true, true);
+ }
+
+ public Blog createBlog(String name) throws HibernateException {
+
+ Blog blog = new Blog();
+ blog.setName(name);
+ blog.setItems( new ArrayList() );
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ session.persist(blog);
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return blog;
+ }
+
+ public BlogItem createBlogItem(Blog blog, String title, String text)
+ throws HibernateException {
+
+ BlogItem item = new BlogItem();
+ item.setTitle(title);
+ item.setText(text);
+ item.setBlog(blog);
+ item.setDatetime( Calendar.getInstance() );
+ blog.getItems().add(item);
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ session.update(blog);
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return item;
+ }
+
+ public BlogItem createBlogItem(Long blogid, String title, String text)
+ throws HibernateException {
+
+ BlogItem item = new BlogItem();
+ item.setTitle(title);
+ item.setText(text);
+ item.setDatetime( Calendar.getInstance() );
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ Blog blog = (Blog) session.load(Blog.class, blogid);
+ item.setBlog(blog);
+ blog.getItems().add(item);
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return item;
+ }
+
+ public void updateBlogItem(BlogItem item, String text)
+ throws HibernateException {
+
+ item.setText(text);
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ session.update(item);
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ }
+
+ public void updateBlogItem(Long itemid, String text)
+ throws HibernateException {
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ try {
+ tx = session.beginTransaction();
+ BlogItem item = (BlogItem) session.load(BlogItem.class, itemid);
+ item.setText(text);
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ }
+
+ public List listAllBlogNamesAndItemCounts(int max)
+ throws HibernateException {
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ List result = null;
+ try {
+ tx = session.beginTransaction();
+ Query q = session.createQuery(
+ "select blog.id, blog.name, count(blogItem) " +
+ "from Blog as blog " +
+ "left outer join blog.items as blogItem " +
+ "group by blog.name, blog.id " +
+ "order by max(blogItem.datetime)"
+ );
+ q.setMaxResults(max);
+ result = q.list();
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return result;
+ }
+
+ public Blog getBlogAndAllItems(Long blogid)
+ throws HibernateException {
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ Blog blog = null;
+ try {
+ tx = session.beginTransaction();
+ Query q = session.createQuery(
+ "from Blog as blog " +
+ "left outer join fetch blog.items " +
+ "where blog.id = :blogid"
+ );
+ q.setParameter("blogid", blogid);
+ blog = (Blog) q.uniqueResult();
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return blog;
+ }
+
+ public List listBlogsAndRecentItems() throws HibernateException {
+
+ Session session = _sessions.openSession();
+ Transaction tx = null;
+ List result = null;
+ try {
+ tx = session.beginTransaction();
+ Query q = session.createQuery(
+ "from Blog as blog " +
+ "inner join blog.items as blogItem " +
+ "where blogItem.datetime > :minDate"
+ );
+
+ Calendar cal = Calendar.getInstance();
+ cal.roll(Calendar.MONTH, false);
+ q.setCalendar("minDate", cal);
+
+ result = q.list();
+ tx.commit();
+ }
+ catch (HibernateException he) {
+ if (tx!=null) tx.rollback();
+ throw he;
+ }
+ finally {
+ session.close();
+ }
+ return result;
+ }
+}]]></programlisting>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/example_weblog.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/filters.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/filters.xml 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/filters.xml 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,128 @@
+<chapter id="filters">
+ <title>Filtrando dados</title>
+
+ <para>
+ O Hibernate3 provê um novo método inovador para manusear dados com regras de
"visibilidade".
+ Um <emphasis>Filtro do Hibernate</emphasis> é um filtro global,
nomeado e parametrizado que pode
+ se habilitado ou não dentro de um Session do Hibernate.
+ </para>
+
+ <sect1 id="objectstate-filters">
+ <title>Filtros do Hibernate</title>
+
+ <para>
+ O Hibernate tem a habilidade de pré definir os critérios do filtro e anexar
esses filtros no
+ nível da classe e no nível da coleção. Um critério do filtro é a habilidade
de definir uma
+ cláusula restritiva muito semelhante ao atributo "where" disponível
para a classe e várias
+ coleções. A não ser que essas condições de filtros podem ser parametrizadas.
A aplicação
+ pode, então, fazer uma decisão em tempo de execução se os filtros definidos
devem estar
+ habilitados e quais valores seus parâmetros devem ter. Os filtros podem ser
usados como
+ Views de bancos de dados, mas com parametros internos à aplicação.
+ </para>
+
+ <para>
+ Para usar esses filtros, eles primeiramente devem ser definidos e anexados
aos elementos do
+ mapeamento apropriados. Para definir um filtro, use o elemento
<literal><filter-def/></literal>
+ dentro do elemento
<literal><hibernate-mapping/></literal>:
+ </para>
+
+ <programlisting><![CDATA[<filter-def name="myFilter">
+ <filter-param name="myFilterParam" type="string"/>
+</filter-def>]]></programlisting>
+
+ <para>
+ Então esse filtro pode ser anexo à uma classe:
+ </para>
+
+ <programlisting><![CDATA[<class name="myClass" ...>
+ ...
+ <filter name="myFilter" condition=":myFilterParam =
MY_FILTERED_COLUMN"/>
+</class>]]></programlisting>
+
+ <para>
+ ou em uma coleção:
+ </para>
+
+ <programlisting><![CDATA[<set ...>
+ <filter name="myFilter" condition=":myFilterParam =
MY_FILTERED_COLUMN"/>
+</set>]]></programlisting>
+
+ <para>
+ ou mesmo para ambos (ou muitos de cada) ao mesmo tempo.
+ </para>
+
+ <para>
+ Os métodos na <literal>Session</literal> são:
<literal>enableFilter(String filterName)</literal>,
+ <literal>getEnabledFilter(String filterName)</literal>, e
<literal>disableFilter(String filterName)</literal>.
+ Por padrão, os filtros não são habilitados dentro de qualquer session; Eles
devem ser explicitamente
+ habilitados usando o método
<literal>Session.enabledFilter()</literal>, que retorna uma instância da
+ interface <literal>Filter</literal>. Usando o filtro simples
definido acima, o código se pareceria
+ com o seguinte:
+ </para>
+
+
<programlisting><![CDATA[session.enableFilter("myFilter").setParameter("myFilterParam",
"some-value");]]></programlisting>
+
+ <para>
+ Veja que os métodos da interface org.hibernate.Filter permite o encadeamento
de funções, comum à maioria das funções do Hibernate.
+ </para>
+
+ <para>
+ Um exemplo completo, usando dados temporais com um padrão efetivo de registro
de datas:
+ </para>
+
+ <programlisting><![CDATA[<filter-def
name="effectiveDate">
+ <filter-param name="asOfDate" type="date"/>
+</filter-def>
+
+<class name="Employee" ...>
+...
+ <many-to-one name="department" column="dept_id"
class="Department"/>
+ <property name="effectiveStartDate" type="date"
column="eff_start_dt"/>
+ <property name="effectiveEndDate" type="date"
column="eff_end_dt"/>
+...
+ <!--
+ Note that this assumes non-terminal records have an eff_end_dt set to
+ a max db date for simplicity-sake
+ -->
+ <filter name="effectiveDate"
+ condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
+</class>
+
+<class name="Department" ...>
+...
+ <set name="employees" lazy="true">
+ <key column="dept_id"/>
+ <one-to-many class="Employee"/>
+ <filter name="effectiveDate"
+ condition=":asOfDate BETWEEN eff_start_dt and eff_end_dt"/>
+ </set>
+</class>]]></programlisting>
+
+ <para>
+ Para garantir que você sempre tenha registro efetivos, simplesmente habilite
o filtro
+ na session antes de recuperar os dados dos empregados:
+ </para>
+
+<programlisting><![CDATA[Session session = ...;
+session.enabledFilter("effectiveDate").setParameter("asOfDate", new
Date());
+List results = session.createQuery("from Employee as e where e.salary >
:targetSalary")
+ .setLong("targetSalary", new Long(1000000))
+ .list();
+]]></programlisting>
+
+ <para>
+ No HQL acima, mesmo que mencionamos apenas uma restrição de salário nos
resultados, por causa
+ do filtro habilitado, a consulta retornará apenas os funcionários ativos cujo
salário é maior
+ que um milhão de dólares.
+ </para>
+
+ <para>
+ Nota: se você planeja usar filtros com outer join (por HQL ou por load
fetching) seja cuidadoso
+ na direção da expressão de condição. É mais seguro configura-lo com para um
left outer join;
+ geralmente, coloque o parâmetro primeiro seguido pelo nome da coluna após o
operador.
+ </para>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/filters.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/inheritance_mapping.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/inheritance_mapping.xml 2006-08-14
14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/inheritance_mapping.xml 2006-08-14
14:55:10 UTC (rev 10262)
@@ -0,0 +1,501 @@
+<chapter id="inheritance">
+ <title>Mapeamento de Herança</title>
+
+ <sect1 id="inheritance-strategies" revision="3">
+ <title> As três estratégias</title>
+
+ <para>
+ O Hibernate suporta as três estratégias básicas de mapeamento de herança:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ tabela por hierarquia de classes
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ tabela por subclasse
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ tabela por classe concreta
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Adicionalmente, o Hibernate suporta uma quarta, um tipo levemente
+ diferente de polimorfismo:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ polimorfismo implícito
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ É possível usar diferentes estratégias de mapeamento para diferentes
+ ramificações da mesma hierarquia de herança, e então fazer uso do
+ polimorfismo implícito para alcançar polimorfismo através da
+ hierarquia completa. De qualquer forma, O Hibernate não suporta a
+ mistura de mapeamentos
<literal><subclass></literal>,
+ and <literal><joined-subclass></literal> e
+ <literal><union-subclass></literal> dentro do mesmo
elemento
+ raiz <literal><class></literal>. É possível usar
junto às estratégias
+ tabela por hierarquia e a tabela por subclasse, abaixo do mesmo elemento
+ <literal><class></literal>, combinando os elementos
+ <literal><subclass></literal> e
<literal><join></literal>
+ (veja abaixo).
+
+ </para>
+
+ <para>
+ É possível definir mapeamentos <literal>subclass</literal>,
<literal>union-subclass</literal>,
+ e <literal>joined-subclass</literal> em documentos de mapeamento
separados, diretamente abaixo de
+ <literal>hibernate-mapping</literal>. Isso permite a você
estender uma hierarquia de classes
+ apenas adicionando um novo arquivo de mapeamento. Você deve especificar um
atributo
+ <literal>extends</literal> no mapeamento da subclasse, nomeando
uma superclasse previamente
+ mapeada. Nota: Anteriormente esta característica fazia o ordenamento dos
documentos de
+ mapeamento importantes. Desde o Hibernate3, o ordenamento dos arquivos de
mapeamento não
+ importa quando usamos a palavra chave extends. O ordenamento dentro de um
arquivo de mapeamento
+ simples ainda necessita ser definido como superclasse antes de subclasse.
+ </para>
+
+ <programlisting><![CDATA[
+ <hibernate-mapping>
+ <subclass name="DomesticCat" extends="Cat"
discriminator-value="D">
+ <property name="name" type="string"/>
+ </subclass>
+ </hibernate-mapping>]]></programlisting>
+
+
+ <sect2 id="inheritance-tableperclass" >
+ <title>Tabela por hierarquia de classes</title>
+
+ <para>
+ Suponha que tenhamos uma interface <literal>Payment</literal>,
com sua
+ implementação <literal>CreditCardPayment</literal>,
<literal>CashPayment</literal>,
+ <literal>ChequePayment</literal>. O mapeamento da tabela por
hierarquia
+ seria parecido com:
+ </para>
+
+ <programlisting><![CDATA[<class name="Payment"
table="PAYMENT">
+ <id name="id" type="long" column="PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <discriminator column="PAYMENT_TYPE" type="string"/>
+ <property name="amount" column="AMOUNT"/>
+ ...
+ <subclass name="CreditCardPayment"
discriminator-value="CREDIT">
+ <property name="creditCardType" column="CCTYPE"/>
+ ...
+ </subclass>
+ <subclass name="CashPayment" discriminator-value="CASH">
+ ...
+ </subclass>
+ <subclass name="ChequePayment"
discriminator-value="CHEQUE">
+ ...
+ </subclass>
+</class>]]></programlisting>
+
+ <para>
+ Exactly one table is required. There is one big limitation of this mapping
+ strategy: columns declared by the subclasses, such as
<literal>CCTYPE</literal>,
+ may not have <literal>NOT NULL</literal> constraints.
+ </para>
+
+ </sect2>
+
+ <sect2 id="inheritance-tablepersubclass">
+ <title>Tabela por subclasse</title>
+
+ <para>
+ Um mapeamento de tabela por subclasse seria parecido com:
+ </para>
+
+ <programlisting><![CDATA[<class name="Payment"
table="PAYMENT">
+ <id name="id" type="long" column="PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="amount" column="AMOUNT"/>
+ ...
+ <joined-subclass name="CreditCardPayment"
table="CREDIT_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ <property name="creditCardType" column="CCTYPE"/>
+ ...
+ </joined-subclass>
+ <joined-subclass name="CashPayment" table="CASH_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ ...
+ </joined-subclass>
+ <joined-subclass name="ChequePayment"
table="CHEQUE_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ ...
+ </joined-subclass>
+</class>]]></programlisting>
+
+ <para>
+ Quatro tabelas são necessárias. As três tabelas subclasses possuem
+ associação de chave primária para a tabela de superclasse
+ (então o modelo relacional é atualmente uma associação de
+ um-para-um).
+ </para>
+
+ </sect2>
+
+ <sect2 id="inheritance-tablepersubclass-discriminator"
revision="2">
+ <title>Tabela por subclasse, usando um discriminador</title>
+
+ <para>
+ Note que a implementação de tabela por subclasse do Hibernate não
+ necessita de coluna de discriminador. Outro mapeador objeto/relacional
+ usa uma implementação diferente de tabela por subclasse, que necessita
+ uma coluna com o tipo discriminador na tabela da superclasse. A
+ abordagem escolhida pelo Hibernate é muito mais difícil de implementar,
+ porém de forma argumentável mais correto de um ponto de vista relacional.
+ Se você deseja utilizar uma coluna discriminadora com a estratégia
+ tabela por subclasse, você pode combinar o uso de
+ <literal><subclass></literal> e
<literal><join></literal>,
+ dessa maneira:
+ </para>
+
+ <programlisting><![CDATA[<class name="Payment"
table="PAYMENT">
+ <id name="id" type="long" column="PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <discriminator column="PAYMENT_TYPE" type="string"/>
+ <property name="amount" column="AMOUNT"/>
+ ...
+ <subclass name="CreditCardPayment"
discriminator-value="CREDIT">
+ <join table="CREDIT_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ <property name="creditCardType" column="CCTYPE"/>
+ ...
+ </join>
+ </subclass>
+ <subclass name="CashPayment" discriminator-value="CASH">
+ <join table="CASH_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ ...
+ </join>
+ </subclass>
+ <subclass name="ChequePayment"
discriminator-value="CHEQUE">
+ <join table="CHEQUE_PAYMENT" fetch="select">
+ <key column="PAYMENT_ID"/>
+ ...
+ </join>
+ </subclass>
+</class>]]></programlisting>
+
+ <para>
+ The optional <literal>fetch="select"</literal>
declaration tells Hibernate
+ not to fetch the <literal>ChequePayment</literal> subclass data
using an
+ outer join when querying the superclass.
+A declaração opcional fetch=”select” diz ao Hibernate para não buscar os dados da
subclasse ChequePayment, quando usar um outer join pesquisando pela superclasse.
+ </para>
+
+ </sect2>
+
+ <sect2 id="inheritance-mixing-tableperclass-tablepersubclass">
+ <title>. Misturando tabela por hierarquia de classes com tabela por
subclasse</title>
+
+ <para>
+ Você pode até mesmo misturar a estratégia de tabela por hierarquia e
+ tabela por subclasse usando esta abordagem:
+ </para>
+
+ <programlisting><![CDATA[<class name="Payment"
table="PAYMENT">
+ <id name="id" type="long" column="PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <discriminator column="PAYMENT_TYPE" type="string"/>
+ <property name="amount" column="AMOUNT"/>
+ ...
+ <subclass name="CreditCardPayment"
discriminator-value="CREDIT">
+ <join table="CREDIT_PAYMENT">
+ <property name="creditCardType" column="CCTYPE"/>
+ ...
+ </join>
+ </subclass>
+ <subclass name="CashPayment" discriminator-value="CASH">
+ ...
+ </subclass>
+ <subclass name="ChequePayment"
discriminator-value="CHEQUE">
+ ...
+ </subclass>
+</class>]]></programlisting>
+
+ <para>
+ Para qualquer uma dessas estratégias de mapeamento, uma associação
+ polimórfica para a classe raiz <literal>Payment</literal> deve
ser
+ mapeada usando <literal><many-to-one></literal>.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="payment"
column="PAYMENT_ID" class="Payment"/>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="inheritance-tableperconcrete" revision="2">
+ <title>Tabela por classe concreta</title>
+
+ <para>
+ Existem duas formas que poderíamos usar a respeito da estratégia de
+ mapeamento de tabela por classe concreta. A primeira é usar
+ <literal><union-subclass></literal>..
+ </para>
+
+ <programlisting><![CDATA[<class name="Payment">
+ <id name="id" type="long" column="PAYMENT_ID">
+ <generator class="sequence"/>
+ </id>
+ <property name="amount" column="AMOUNT"/>
+ ...
+ <union-subclass name="CreditCardPayment"
table="CREDIT_PAYMENT">
+ <property name="creditCardType" column="CCTYPE"/>
+ ...
+ </union-subclass>
+ <union-subclass name="CashPayment" table="CASH_PAYMENT">
+ ...
+ </union-subclass>
+ <union-subclass name="ChequePayment"
table="CHEQUE_PAYMENT">
+ ...
+ </union-subclass>
+</class>]]></programlisting>
+
+ <para>
+ Três tabelas estão envolvidas para as subclasses. Cada tabela define
+ colunas para todas as propriedades da classe, incluindo propriedades
herdadas.
+ </para>
+
+ <para>
+ A limitação dessa abordagem é que se uma propriedade é mapeada na
+ superclasse, o nome da coluna deve ser o mesmo em todas as tabelas das
+ subclasses. (Nós devemos melhorar isto em um futuro release do Hibernate).
+ A estratégia do gerador de identidade não é permitida em união de
+ subclasses(union-subclass) herdadas, na verdade a fonte de chave
+ primária deve ser compartilhada através de todas subclasses unidas da
+ hierarquia.
+
+ </para>
+
+ <para>
+ Se sua superclasse é abstrata, mapeie ela com
<literal>abstract="true"</literal>.
+ Claro, que se ela não for abstrata, uma tabela (padrão para
<literal>PAYMENT</literal>
+ no exemplo acima) adicional é necessária para segurar as instâncias da
superclasse.
+ </para>
+
+ </sect2>
+
+ <sect2 id="inheritance-tableperconcreate-polymorphism">
+ <title>Tabela por classe concreta, usando polimorfismo
implícito</title>
+
+ <para>
+ Uma abordagem alternativa é fazer uso de polimorfismo implícito:
+ </para>
+
+ <programlisting><![CDATA[<class name="CreditCardPayment"
table="CREDIT_PAYMENT">
+ <id name="id" type="long"
column="CREDIT_PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="amount" column="CREDIT_AMOUNT"/>
+ ...
+</class>
+
+<class name="CashPayment" table="CASH_PAYMENT">
+ <id name="id" type="long"
column="CASH_PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="amount" column="CASH_AMOUNT"/>
+ ...
+</class>
+
+<class name="ChequePayment" table="CHEQUE_PAYMENT">
+ <id name="id" type="long"
column="CHEQUE_PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="amount" column="CHEQUE_AMOUNT"/>
+ ...
+</class>]]></programlisting>
+
+ <para>
+ Veja que em nenhum lugar mencionamos a interface
<literal>Payment</literal>
+ explicitamente. Também preste atenção que propriedades de
<literal>Payment</literal>
+ são mapeadas em cada uma das subclasses. Se você quer evitar duplicação,
+ considere usar entidades de XML (ex. (e.g. <literal>[ <!ENTITY
allproperties
+ SYSTEM "allproperties.xml"> ]</literal> na declaração
do <literal>DOCTYPE</literal>
+ e <literal>&allproperties;</literal> no mapeamento).
+ </para>
+
+ <para>
+ A desvantagem dessa abordagem é que o Hibernate não gera
<literal>UNION</literal>s
+ SQL quando executa pesquisas polimórficas.
+ </para>
+
+ <para>
+ Para essa estratégia, uma associação polimórfica para
<literal>Payment</literal>
+ geralmente é mapeada usando
<literal><any></literal>.
+ </para>
+
+ <programlisting><![CDATA[<any name="payment"
meta-type="string" id-type="long">
+ <meta-value value="CREDIT" class="CreditCardPayment"/>
+ <meta-value value="CASH" class="CashPayment"/>
+ <meta-value value="CHEQUE" class="ChequePayment"/>
+ <column name="PAYMENT_CLASS"/>
+ <column name="PAYMENT_ID"/>
+</any>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="inheritace-mixingpolymorphism">
+ <title>Misturando polimorfismo implícito com outros mapeamentos de
herança</title>
+
+ <para>
+ Ainda existe uma coisa para ser observada com respeito a este mapeamento.
+ Desde que as subclasses sejam mapeadas em seu próprio elemento
+ <literal><class></literal> (e desde que
<literal>Payment</literal> seja
+ apenas uma interface), cada uma das subclasses pode ser facilmente parte de
uma
+ outra hierarquia de herança! (E você ainda pode usar pesquisas polimórficas
+ em cima da interface <literal>Payment</literal>.)
+
+ </para>
+
+ <programlisting><![CDATA[<class name="CreditCardPayment"
table="CREDIT_PAYMENT">
+ <id name="id" type="long"
column="CREDIT_PAYMENT_ID">
+ <generator class="native"/>
+ </id>
+ <discriminator column="CREDIT_CARD" type="string"/>
+ <property name="amount" column="CREDIT_AMOUNT"/>
+ ...
+ <subclass name="MasterCardPayment"
discriminator-value="MDC"/>
+ <subclass name="VisaPayment" discriminator-value="VISA"/>
+</class>
+
+<class name="NonelectronicTransaction"
table="NONELECTRONIC_TXN">
+ <id name="id" type="long" column="TXN_ID">
+ <generator class="native"/>
+ </id>
+ ...
+ <joined-subclass name="CashPayment" table="CASH_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ <property name="amount" column="CASH_AMOUNT"/>
+ ...
+ </joined-subclass>
+ <joined-subclass name="ChequePayment"
table="CHEQUE_PAYMENT">
+ <key column="PAYMENT_ID"/>
+ <property name="amount" column="CHEQUE_AMOUNT"/>
+ ...
+ </joined-subclass>
+</class>]]></programlisting>
+
+ <para>
+ Mais uma vez, nós não mencionamos <literal>Payment</literal>
explicitamente.
+ Se nós executarmos uma pesquisa em cima da interface
<literal>Payment</literal> –
+ por exemplo, <literal>from Payment</literal> – o Hibernate
retorna
+ automaticamente instâncias de
<literal>CreditCardPayment</literal> (e suas
+ subclasses, desde que elas também implementem
<literal>Payment</literal>),
+ <literal>CashPayment</literal> e
<literal>ChequePayment</literal> mas
+ não as instâncias de
<literal>NonelectronicTransaction</literal>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="inheritance-limitations">
+ <title>Limitações</title>
+
+ <para>
+ Existem certas limitações para a abordagem do "polimorfismo
implícito"
+ comparada com a estratégia de mapeamento da tabela por classe concreta.
+ Existe uma limitação um tanto menos restritiva para mapeamentos
+ <literal><union-subclass></literal>.
+
+ </para>
+
+ <para>
+ A tabela seguinte demonstra as limitações do mapeamento de tabela
+ por classe concreta e do polimorfismo implícito no Hibernate.
+ </para>
+
+ <table frame="topbot">
+ <title>Features of inheritance mappings</title>
+ <tgroup cols='8' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <colspec colname='c3' colwidth="1*"/>
+ <colspec colname='c4' colwidth="1*"/>
+ <colspec colname='c5' colwidth="1*"/>
+ <colspec colname='c6' colwidth="1*"/>
+ <colspec colname='c7' colwidth="1*"/>
+ <colspec colname='c8' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Estratégia de Herança</entry>
+ <entry>muitos-para-um Polimórfico</entry>
+ <entry>um-para-um Polimórfico</entry>
+ <entry>um-para-muitos Polimórfico</entry>
+ <entry>muitos-para-muitos Polimórfico</entry>
+ <entry><literal>load()/get()</literal> Polimórfico
</entry>
+ <entry>Pesquisas Polimórficas</entry>
+ <entry>Joins polimórficos</entry>
+ <entry>Outer join fetching</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>table per class-hierarchy</entry>
+
<entry><literal><many-to-one></literal></entry>
+
<entry><literal><one-to-one></literal></entry>
+
<entry><literal><one-to-many></literal></entry>
+
<entry><literal><many-to-many></literal></entry>
+ <entry><literal>s.get(Payment.class,
id)</literal></entry>
+ <entry><literal>from Payment p</literal></entry>
+ <entry><literal>from Order o join o.payment
p</literal></entry>
+ <entry><emphasis>supported</emphasis></entry>
+ </row>
+ <row>
+ <entry>table per subclass</entry>
+
<entry><literal><many-to-one></literal></entry>
+
<entry><literal><one-to-one></literal></entry>
+
<entry><literal><one-to-many></literal></entry>
+
<entry><literal><many-to-many></literal></entry>
+ <entry><literal>s.get(Payment.class,
id)</literal></entry>
+ <entry><literal>from Payment p</literal></entry>
+ <entry><literal>from Order o join o.payment
p</literal></entry>
+ <entry><emphasis>supported</emphasis></entry>
+ </row>
+ <row>
+ <entry>table per concrete-class (union-subclass)</entry>
+
<entry><literal><many-to-one></literal></entry>
+
<entry><literal><one-to-one></literal></entry>
+ <entry><literal><one-to-many></literal>
(for <literal>inverse="true"</literal> only)</entry>
+
<entry><literal><many-to-many></literal></entry>
+ <entry><literal>s.get(Payment.class,
id)</literal></entry>
+ <entry><literal>from Payment p</literal></entry>
+ <entry><literal>from Order o join o.payment
p</literal></entry>
+ <entry><emphasis>supported</emphasis></entry>
+ </row>
+ <row>
+ <entry>table per concrete class (implicit
polymorphism)</entry>
+
<entry><literal><any></literal></entry>
+ <entry><emphasis>not
supported</emphasis></entry>
+ <entry><emphasis>not
supported</emphasis></entry>
+
<entry><literal><many-to-any></literal></entry>
+ <entry><literal>s.createCriteria(Payment.class).add(
Restrictions.idEq(id) ).uniqueResult()</literal></entry>
+ <entry><literal>from Payment p</literal></entry>
+ <entry><emphasis>not
supported</emphasis></entry>
+ <entry><emphasis>not
supported</emphasis></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/inheritance_mapping.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/performance.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/performance.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/performance.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1384 @@
+<chapter id="performance">
+ <title>Aumentando a performance</title>
+
+ <sect1 id="performance-fetching" revision="2">
+ <title>Estratégias de Fetching</title>
+
+ <para>
+ Uma <emphasis>estratégia de fetching</emphasis> é a estratégia
que o Hibernate
+ irá usar para buscar objetos associados se a aplicação precisar navegar pela
associação.
+ Estratégias de Fetch podem ser declaradas nos metadados de mapeamento O/R, ou
sobrescritos
+ por uma query HQL ou query com <literal>Criteria</literal>.
+ </para>
+
+ <para>
+ Hibernate3 define as seguintes estratégias de fetching:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Join fetching</emphasis> - o Hibernate busca o
objeto
+ ou coleção associada no mesmo <literal>SELECT</literal>,
usando um
+ <literal>OUTER JOIN</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Select fetching</emphasis> - um segundo
<literal>SELECT</literal> é
+ usado para buscar a entidade ou coleção associada. A menos que você
desabilite
+ lazy fetching especificando
<literal>lazy="false"</literal>, esse segundo SELECT
+ será executado apenas quando você acessar a associação.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Subselect fetching</emphasis> - um segundo
<literal>SELECT</literal> será
+ usado para buscar as coleções associadas de todas as entidades
buscadas na query ou
+ fetch anterior. A menos que você desabilite lazy fetching
especificando
+ <literal>lazy="false"</literal>, esse segundo
SELECT será executado apenas quando
+ você acessar a associação.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Batch fetching</emphasis> - uma opção de
otimização para o Select
+ Fetching – O Hibernate busca um lote de instâncias ou entidades
usando um único
+ <literal>SELECT</literal>, especificando uma lista de
chaves primárias ou chaves
+ estrangeiras.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ O Hibernate distingue também entre:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Immediate fetching</emphasis> - uma associação,
coleção ou atributo é buscado
+ como ela é carregada (Qual SQL é usado). Não se confuda com eles! Nós
usamos fetch para melhorar a performance. Nós podemos usar lazy para definir um contrato
para qual dado é sempre disponível em qualquer instância desanexada de uma classe
qualquer.
+ imediatamente, quando o pai é carregado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Lazy collection fetching</emphasis> - a coleção
é buscada quando a
+ aplicação invoca uma operação sobre aquela coleção (Esse é o padrão
para coleções)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>"Extra-lazy" collection
fetching</emphasis> - elementos individuais de uma
+ coleção são acessados do banco de dados quando preciso. O Hibernate
tenta não buscar
+ a coleção inteira dentro da memória ao menos que seja absolutamente
preciso.
+ (indicado para coleções muito grandes)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Proxy fetching</emphasis> - uma associação de
um valor é carregada quando um método
+ diferente do getter do identificador é invocado sobre o objeto
associado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>"No-proxy" fetching</emphasis> - uma
associação de um valor é carregada quando
+ a variável da instância é carregada. Comparada com a proxy fetching,
esse método é menos
+ preguiçoso (lazy)(a associação é carregada somente quando o
identificador é acessada)
+ mas é mais transparente, já que não há proxies visíveis para a
aplicação.
+ Esse método requer instrumentação de bytecodes em build-time e é
raramente necessário.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Lazy attribute fetching</emphasis> - um
atributo ou associação de um valor é
+ carregada quanto a varíavel da instância é acessada. Esse método
requer instrumentação
+ de bytecodes em build-time e é raramente necessário.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Nós temos aqui duas noções ortogonais:
<emphasis>quando</emphasis> a associação é carregada e
+ <emphasis>como </emphasis> ela é carregada (Qual SQL é usado).
Não se confuda com eles! Nós
+ usamos <literal>fetch</literal> para melhorar a performance. Nós
podemos usar lazy para
+ definir um contrato para qual dado é sempre disponível em qualquer instância
desconectada
+ de uma classe qualquer.
+ </para>
+
+ <sect2 id="performance-fetching-lazy">
+ <title>Trabalhando com associações preguiçosas (lazy)</title>
+
+ <para>
+ Por padrão, o Hibernate3 usa busca preguiçosa para coleções e busca
preguiçosa
+ com proxy para associações de um valor. Esses padrões fazem sentido para
quase
+ todas as associações em quase todas a aplicações.
+ </para>
+
+ <para>
+ <emphasis>Veja:</emphasis> se voce setar
+ <literal>hibernate.default_batch_fetch_size</literal>, O
Hibernate irá usar otimização
+ de carregamento em lote para o carregamento preguiçoso(Essa otimização
pode ser também
+ habilitada em um nível mais fino).
+ </para>
+
+ <para>
+ Porém, a busca preguiçosa tem um problema que você precisar saber. Acesso
a associações
+ preguiçosas fora do contexto de uma sessão aberta do Hibernate irá
resultar numa exceção.
+ Por exemplo:
+ </para>
+
+ <programlisting><![CDATA[s = sessions.openSession();
+Transaction tx = s.beginTransaction();
+
+User u = (User) s.createQuery("from User u where u.name=:userName")
+ .setString("userName", userName).uniqueResult();
+Map permissions = u.getPermissions();
+
+tx.commit();
+s.close();
+
+Integer accessLevel = (Integer) permissions.get("accounts"); //
Error!]]></programlisting>
+
+ <para>
+ Como a coleção de permissões não foi inicializada quando a
<literal>Session</literal>
+ foi fechada, a coleção não poderá carregar o seu estado. O Hibernate não
suporta
+ inicialização preguiçosa para objetos desconectados. Para consertar isso,
é necessário
+ mover o código que carrega a coleção para antes da transação ser
comitada.
+ </para>
+
+ <para>
+ Alternativamente, nós podemos usar uma coleção ou associação não
preguiçosa,
+ especificando <literal>lazy="false"</literal> para
o mapeamento da associação.
+ Porém, é pretendido que a inicialização preguiçosa seja usada por quase
todas as
+ coleções e associações. Se você definir muitas associações não
preguiçosas em seu
+ modelo de objetos, o Hibernate irá precisar carregar o banco de dados
inteiro na memória
+ em cada transação!
+ </para>
+
+ <para>
+ Por outro lado, nós geralmente escolhemos join fetching (que é não
preguiçosa por natureza)
+ ao invés de select fetching em uma transação particular. Nós iremos ver
como customizar
+ a estratégoa de busca. No Hibernate3, os mecanismos para escolher a
estratégia de fetching
+ são identicos para as associações simples e para coleções.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-fetching-custom" revision="4">
+ <title>Personalizando as estratégias de busca</title>
+
+ <para>
+ O select fetching (o padrão) é extremamente vunerável para N+1 problemas
em select,
+ então nós iremos querer habilitar o join fetching no documento de
mapeamento:
+ </para>
+
+ <programlisting><![CDATA[<set name="permissions"
+ fetch="join">
+ <key column="userId"/>
+ <one-to-many class="Permission"/>
+</set]]></programlisting>
+
+ <programlisting><![CDATA[<many-to-one name="mother"
class="Cat" fetch="join"/>]]></programlisting>
+
+ <para>
+ A estratégia de <literal>fetch</literal> definida no
documento de mapeamento afeta:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ recupera via <literal>get()</literal> ou
<literal>load()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Recuperações que acontecem implicitamente quando navegamos por uma
associação
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Criteria</literal> queries
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ buscas por HQL se buscar por <literal>subselect</literal>
for usado
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Independentemente da estratégia de busca que você usar, o grafo não
preguiçoso definido
+ será garantidamente carregado na memória. Note que isso irá resultar em
diversos selects
+ imediatos sendo usados em um HQL em particular.
+ </para>
+
+ <para>
+ Usualmente não usamos documentos de mapeamento para customizar as buscas.
Ao invés disso,
+ nós deixamos o comportamento padrão e sobrescrevemos isso em uma
transação em particular,
+ usando <literal>left join fetch</literal> no HQL. Isso diz ao
Hibernate para buscar a associação
+ inteira no primeiro select, usando um outer join. Na API de busca
<literal>Criteria</literal>,
+ você irá usar
<literal>setFetchMode(FetchMode.JOIN)</literal>.
+ </para>
+
+ <para>
+ Se você quiser mudar a estratégia de busca usada pelo
<literal>get()</literal>
+ ou <literal>load()</literal>, simplesmente use uma query
<literal>Criteria</literal>,
+ por exemplo:
+ </para>
+
+ <programlisting><![CDATA[User user = (User)
session.createCriteria(User.class)
+ .setFetchMode("permissions", FetchMode.JOIN)
+ .add( Restrictions.idEq(userId) )
+ .uniqueResult();]]></programlisting>
+
+ <para>
+ (Isto é o equivalente do Hibernate para o que algumas soluções ORM
chamam de "plano de busca")
+ </para>
+
+ <para>
+ Um meio totalmente diferente de evitar problemas com selects N+1 é usar
um cache de segundo nível.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-fetching-proxies" revision="2">
+ <title>Proxies de associação single-ended</title>
+
+ <para>
+ A recuperação preguiçosa para coleções é implementada usando uma
implementação
+ própria do Hibernate para coleções persistentes. Porém, um mecanismo
diferente é
+ necessário para comportamento preguiçoso para associações de um lado só.
A entidade
+ alvo da associação precisa usar um proxy. O Hibernate implementa proxies
para inicialização
+ preguiçosa em objetos persistentes usando manipulação de bytecode
+ (via a excelente biblioteca CGLIB).
+ </para>
+
+ <para>
+ Por padrão, o Hibernate3 gera proxies (na inicialização) para todas as
classes
+ persistentes que usem eles para habilitar recuperaçãopreguiçosa de
associações
+ <literal>many-to-one</literal> e
<literal>one-to-one</literal>.
+ </para>
+
+ <para>
+ O arquivo de mapeamento deve declaram uma interface para usar como
interface de proxy
+ para aquela classe, com o atributo <literal>proxy</literal>.
Por padrão, o Hibernate usa
+ uma subclasse dessa classe. <emphasis>Note que a classe a ser usada
via proxy precisa
+ implementar o construtor padrão com pelo menos visibilidade de package.
Nós recomendamos
+ esse construtor para todas as classes persistentes!</emphasis>
+ </para>
+
+ <para>
+ Existe alguns truques que você deve saber quando extender esse
comportamento para classes
+ polimórficas, dessa maneira:
+ </para>
+
+ <programlisting><![CDATA[<class name="Cat"
proxy="Cat">
+ ......
+ <subclass name="DomesticCat">
+ .....
+ </subclass>
+</class>]]></programlisting>
+
+ <para>
+ Primeiramente, instâncias de <literal>Cat</literal> nunca
seráo convertidas
+ para <literal>DomesticCat</literal>, mesmo que a instância em
questão seja uma
+ estância de <literal>DomesticCat</literal>:
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) session.load(Cat.class,
id); // instantiate a proxy (does not hit the db)
+if ( cat.isDomesticCat() ) { // hit the db to initialize the proxy
+ DomesticCat dc = (DomesticCat) cat; // Error!
+ ....
+}]]></programlisting>
+
+ <para>
+ É possível quebrar o proxy <literal>==</literal>.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) session.load(Cat.class,
id); // instantiate a Cat proxy
+DomesticCat dc =
+ (DomesticCat) session.load(DomesticCat.class, id); // acquire new DomesticCat
proxy!
+System.out.println(cat==dc); //
false]]></programlisting>
+
+ <para>
+ Porém a situação não é tão ruim como parece. Mesmo quando temos duas
referências para
+ objetos proxies diferentes, a instância deles será o mesmo objeto
+ </para>
+
+ <programlisting><![CDATA[cat.setWeight(11.0); // hit the db to
initialize the proxy
+System.out.println( dc.getWeight() ); // 11.0]]></programlisting>
+
+ <para>
+ Terceiro, Você não pode usar um proxy CGLIB em uma classe
<literal>final</literal>
+ ou com qualquer método <literal>final</literal>.
+ </para>
+
+ <para>
+ Finalmente, se o seu objeto persistente adquirir qualquer recursto
durante a instanciação
+ (em inicializadores ou construtor padrão), então esses recursos serão
adquiridos pelo proxy
+ também. A classe de proxy é uma subclasse da classe persistente.
+ </para>
+
+ <para>
+ Esses problemas são todos devido a limitação fundamental do modelo de
herança simples do Java.
+ Se você quiser evitar esse problemas em suas classes persistentes você
deve imeplementar uma
+ interface que declare seus métodos de negócio. Você deve especificar
essas interfaces no arquivo
+ de mapeamento. Ex:
+ </para>
+
+ <programlisting><![CDATA[<class name="CatImpl"
proxy="Cat">
+ ......
+ <subclass name="DomesticCatImpl" proxy="DomesticCat">
+ .....
+ </subclass>
+</class>]]></programlisting>
+
+ <para>
+ onde <literal>CatImpl</literal> implementa a interface
<literal>Cat</literal> e
+ <literal>DomesticCatImpl</literal> implementa a interface
<literal>DomesticCat</literal>.
+ Então proxies para instâncias de <literal>Cat</literal> e
<literal>DomesticCat</literal>
+ serão retornadas por <literal>load()</literal> ou
<literal>iterate()</literal>.
+ (Note que <literal>list()</literal> geralmente não retorna
proxies).
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) session.load(CatImpl.class,
catid);
+Iterator iter = session.iterate("from CatImpl as cat where
cat.name='fritz'");
+Cat fritz = (Cat) iter.next();]]></programlisting>
+
+ <para>
+ Relacionamentos são também carregados preguiçosamente. Isso significa que
você precisa declarar
+ qualquer propriedade como sendo do tipo
<literal>Cat</literal>, e não <literal>CatImpl</literal>.
+ </para>
+
+ <para>
+ Algumas operações <emphasis>não</emphasis> requerem
inicialização por proxy:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>equals()</literal>, se a classe persistente
não sobrescrever
+ <literal>equals()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>hashCode()</literal>, se a classe
persistente não sobrescrever
+ <literal>hashCode()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O método getter do identificador
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ O Hibernate irá detectar classes persistentes que sobrescrevem
+ <literal>equals()</literal> ou
<literal>hashCode()</literal>.
+ </para>
+
+ <para>
+ Escolhendo <literal>lazy="no-proxy"</literal> ao
invés do padrão
+ <literal>lazy="proxy"</literal>, podemos evitar
problemas associados com typecasting.
+ Porém, iremos precisar de instrumentação de bytecode em tempo de
compilação e todas
+ as operações irão resultar em iniciazações de proxy imediatas.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-fetching-initialization"
revision="1">
+ <title>Inicializando coleções e proxies</title>
+
+ <para>
+ Será lançada uma
<literal>LazyInitializationException</literal> se uma coleção não
inicializada
+ ou proxy é acessado fora do escopo da
<literal>Session</literal>, isto é, quando a entidade que
+ contém a coleção ou tem a referência ao proxy estiver no estado
destachado.
+ </para>
+
+ <para>
+ Algumas vezes precisamos garantir qie o proxy ou coleção é inicializado
antes de se fechar a
+ <literal>Session</literal>. Claro que sempre podemos forçar a
inicialização chamando
+ <literal>cat.getSex()</literal> ou
<literal>cat.getKittens().size()</literal>, por exemplo.
+ Mas isto parece confuso para quem lê o código e não é conveniente para
códigos genéricos.
+ </para>
+
+ <para>
+ Os métodos estáticos
<literal>Hibernate.initialize()</literal> e
<literal>Hibernate.isInitialized()</literal>
+ possibilitam a aplicação uma maneira conveniente de trabalhar com
coleções inicializadas preguiçosamente e
+ proxies. <literal>Hibernate.initialize(cat)</literal> irá
forçar a inicialização de um proxy,
+ <literal>cat</literal>, contanto que a
<literal>Session</literal> esteja ainda aberta.
+ <literal>Hibernate.initialize( cat.getKittens() )</literal>
tem um efeito similar para a coleção de
+ kittens.
+ </para>
+
+ <para>
+ Outra opção é manter a <literal>Session</literal> aberta até
que todas as coleções e
+ proxies necessários sejam carregados. Em algumas arquiteturas de
aplicações, particularmente
+ onde o código que acessa os dados usando Hibernate e o código que usa os
dados estão em diferentes
+ camadas da aplicação ou diferentes processos físicos, será um problema
garantir que a
+ <literal>Session</literal> esteja aberta quando uma coleção
for inicializada. Existem dois
+ caminhos básicos para lidar com esse problema:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Em aplicações web, um filtro servlet pode ser usado para fechar a
+ <literal>Session</literal> somente no final da
requisição do usuário, já que a
+ renderização da visão estará completa (o pattern
<emphasis>Open Session In View</emphasis>).
+ Claro, que isto cria a necessidade de um correto manuseio de
exceções na infraestrutura
+ de sua aplicação. É vitalmente importante que a
<literal>Session</literal> esteja fechada
+ e a transação terminada antes de retornar para o usuário, mesmo
que uma exceção ocorra
+ durante a renderização da view. Veja o Wiki do Hibernate para
exemplos do pattern
+ "Open Session In View"
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Em uma aplicação com uma camada de negócios separada, a lógica de
negócios deve
+ "preparar" todas as coleções que serão usadas pela
camada web antes de retornar.
+ Isto sgnifica que a camada de negócios deve carregar todos os
dados e retorná-los
+ já inicializados para a camada de apresentação. Usualmente a
aplicação chama
+ <literal>Hibernate.initialize()</literal> para cada
coleção que será usada pela
+ camada web (essa chamada de método deve ocorrer antes da sessão
ser fechada ou
+ retornar a coleção usando uma consulta Hibernate com uma cláusula
<literal>FETCH</literal>
+ ou um <literal>FetchMode.JOIN</literal> na
<literal>Criteria</literal>. Fica muito
+ mais fácil se você adotar o pattern
<emphasis>Command</emphasis> ao invés do
+ <emphasis>Session Facade</emphasis>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Você também pode anexar um objeto prevaimente carregado em uma
nova
+ <literal>Session</literal>
<literal>merge()</literal> or <literal>lock()</literal>
+ antes de acessar coleções não inicializadas (ou outros proxies).
O Hibernate não faz
+ e certamente <literal>não deve</literal> isso
automaticamente pois isso introduziria
+ semantica em transações ad hoc.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ As vezes você não quer inicializar uma coleção muito grande, mas precisa
de algumas
+ informações (como o tamanho) ou alguns de seus dados.
+ </para>
+
+ <para>
+ Você pode usar um filtro de coleção para saber seu tamanho sem a
inicializar:
+ </para>
+
+ <programlisting><![CDATA[( (Integer) s.createFilter( collection,
"select count(*)" ).list().get(0) ).intValue()]]></programlisting>
+
+ <para>
+ O método <literal>createFilter()</literal> é usado também
para retornar algus dados de uma
+ coleção eficientemente sem precisar inicializar a coleção inteira:
+ </para>
+
+ <programlisting><![CDATA[s.createFilter( lazyCollection,
"").setFirstResult(0).setMaxResults(10).list();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="performance-fetching-batch">
+ <title>Usando busca em lote</title>
+
+ <para>
+ O Hibernate pode fazer uso eficiente de busca em lote, isto é, o
Hibernate pode carregar diversos
+ proxies não inicializados se um proxy é acessado (ou coleções. A busca em
lote é uma otimização da
+ estratégia de select fetching). Existe duas maneiras em que você pode
usar busca em lote: no nível
+ da classe ou no nível da coleção.
+ </para>
+
+ <para>
+ A recuperação em lote para classes/entidades é mais fácil de entender.
Imagine que você tem a seguinte
+ situação em tempo de execução: Você tem 25 instâncias de
<literal>Cat</literal> carregadas em uma
+ <literal>Session</literal>, cada
<literal>Cat</literal> tem uma referência ao seu
<literal>owner</literal>,
+ que é da classe <literal>Person</literal>. A classe
<literal>Person</literal> é mapeada com um proxy,
+ <literal>lazy="true"</literal>. Se você iterar
sobre todos os Cat's e chamar <literal>getOwner()</literal>
+ em cada, o Hibernate irá por padrão executar 25 comandos
<literal>SELECT()</literal>, para buscar os
+ proxies de owners. Você pode melhorar esse comportamento especificando um
<literal>batch-size</literal>
+ no mapeamento da classe <literal>Person</literal>:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person"
batch-size="10">...</class>]]></programlisting>
+
+ <para>
+ O Hibernate irá executar agora apenas três consultas, buscando por vez,
10, 10 e 5 Person.
+ </para>
+
+ <para>
+ Você também pode habilitar busca em lote de uma coleção. Por exemplo, se
cada <literal>Person</literal>
+ tem uma coleção preguiçosa de <literal>Cat</literal>s, e 10
pessoas estão já carregados em uma
+ <literal>Sesssion</literal>, serão gerados 10
<literal>SELECT</literal>s ao se iterar todas as
+ pessoas, um para cada chamada de
<literal>getCats()</literal>.. Se você habilitar busca em lote
+ para a coleção de <literal>cats</literal> no mapeamento da
classe <literal>Person</literal>,
+ o Hibernate pode fazer uma pré carga das coleções:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <set name="cats" batch-size="3">
+ ...
+ </set>
+</class>]]></programlisting>
+
+ <para>
+ Com um <literal>batch-size</literal>de 8, o Hibernate irá
carregar 3, 3, 3, 1 coleções em 4
+ <literal>SELECT</literal>s. Novamente, o valor do atributo
depende do número esperado de coleções
+ não inicialiadas em determinada <literal>Session</literal>.
+ </para>
+
+ <para>
+ A busca em lote de coleções é particularmente útil quando você tem uma
árvore encadeada de
+ items, ex. o típico padrão bill-of-materials (Se bem que um
<emphasis>conjunto encadeado</emphasis>
+ ou <emphasis>caminho materializado </emphasis> pode ser uma
opção melhor para árvores com mais
+ leitura)
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-fetching-subselect">
+ <title>Usando subselect fetching</title>
+
+ <para>
+ Se uma coleção ou proxy simples precisa ser recuperado, o Hibernate
carrega todos eles
+ rodando novamente a query original em um subselect. Isso funciona da
mesma maneira que busca
+ em lote, sem carregar tanto.
+ </para>
+
+ <!-- TODO: Write more about this -->
+
+ </sect2>
+
+ <sect2 id="performance-fetching-lazyproperties">
+ <title>Usando busca preguiçosa de propriedade</title>
+
+ <para>
+ O Hibernate3 suporta a carga posterior de propriedades individuais. Essa
técnica de otimização
+ também conhecida como <emphasis>fetch groups</emphasis>.
Veja que isso é mais uma funcionalidade
+ de marketing já que na prática, é mais importante otimização nas leituras
dos registros do
+ que na leitura das colunas. Porém, carregar apenas algumas propriedades
de uma classe pode
+ ser útil em casos extremos, onde tabelas legadas podem ter centenas de
colunas e o modelo
+ de dados não pode ser melhorado.
+ </para>
+
+ <para>
+ Para habilitar a carga posterior de propriedade, é preciso setar o
atributo
+ <literal>lazy</literal> no seu mapeamento de propriedade:
+ </para>
+
+ <programlisting><![CDATA[<class name="Document">
+ <id name="id">
+ <generator class="native"/>
+ </id>
+ <property name="name" not-null="true"
length="50"/>
+ <property name="summary" not-null="true"
length="200" lazy="true"/>
+ <property name="text" not-null="true" length="2000"
lazy="true"/>
+</class>]]></programlisting>
+
+ <para>
+ A carga posterior de propriedades requer instrumentação de bytecode! Se
suas classes
+ persistentes não forem melhoradas, o Hibernate irá ignorar
silenciosamente essa
+ configuração e usará busca imediatamente.
+ </para>
+
+ <para>
+ Para instrumentação de bytecode, use a seguinte tarefa do Ant:
+ </para>
+
+ <programlisting><![CDATA[<target name="instrument"
depends="compile">
+ <taskdef name="instrument"
classname="org.hibernate.tool.instrument.InstrumentTask">
+ <classpath path="${jar.path}"/>
+ <classpath path="${classes.dir}"/>
+ <classpath refid="lib.class.path"/>
+ </taskdef>
+
+ <instrument verbose="true">
+ <fileset dir="${testclasses.dir}/org/hibernate/auction/model">
+ <include name="*.class"/>
+ </fileset>
+ </instrument>
+</target>]]></programlisting>
+
+ <para>
+ A different (better?) way to avoid unnecessary column reads, at least
for
+ read-only transactions is to use the projection features of HQL or
Criteria
+ queries. This avoids the need for buildtime bytecode processing and is
+ certainly a prefered solution.
+ </para>
+
+ <para>
+ You may force the usual eager fetching of properties using
<literal>fetch all
+ properties</literal> in HQL.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="performance-cache" revision="1">
+ <title>The Second Level Cache</title>
+
+ <para>
+ A Hibernate <literal>Session</literal> is a transaction-level
cache of persistent data. It is
+ possible to configure a cluster or JVM-level
(<literal>SessionFactory</literal>-level) cache on
+ a class-by-class and collection-by-collection basis. You may even plug in a
clustered cache. Be
+ careful. Caches are never aware of changes made to the persistent store by
another application
+ (though they may be configured to regularly expire cached data).
+ </para>
+
+ <para revision="1">
+ You have the option to tell Hibernate which caching implementation to use by
+ specifying the name of a class that implements
<literal>org.hibernate.cache.CacheProvider</literal>
+ using the property
<literal>hibernate.cache.provider_class</literal>. Hibernate
+ comes bundled with a number of built-in integrations with open-source cache
providers
+ (listed below); additionally, you could implement your own and plug it in as
+ outlined above. Note that versions prior to 3.2 defaulted to use EhCache as
the
+ default cache provider; that is no longer the case as of 3.2.
+ </para>
+
+ <table frame="topbot" id="cacheproviders"
revision="1">
+ <title>Cache Providers</title>
+ <tgroup cols='5' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="3*"/>
+ <colspec colname='c3' colwidth="1*"/>
+ <colspec colname='c4' colwidth="1*"/>
+ <colspec colname='c5' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Cache</entry>
+ <entry>Provider class</entry>
+ <entry>Type</entry>
+ <entry>Cluster Safe</entry>
+ <entry>Query Cache Supported</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Hashtable (not intended for production use)</entry>
+
<entry><literal>org.hibernate.cache.HashtableCacheProvider</literal></entry>
+ <entry>memory</entry>
+ <entry></entry>
+ <entry>yes</entry>
+ </row>
+ <row>
+ <entry>EHCache</entry>
+
<entry><literal>org.hibernate.cache.EhCacheProvider</literal></entry>
+ <entry>memory, disk</entry>
+ <entry></entry>
+ <entry>yes</entry>
+ </row>
+ <row>
+ <entry>OSCache</entry>
+
<entry><literal>org.hibernate.cache.OSCacheProvider</literal></entry>
+ <entry>memory, disk</entry>
+ <entry></entry>
+ <entry>yes</entry>
+ </row>
+ <row>
+ <entry>SwarmCache</entry>
+
<entry><literal>org.hibernate.cache.SwarmCacheProvider</literal></entry>
+ <entry>clustered (ip multicast)</entry>
+ <entry>yes (clustered invalidation)</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>JBoss TreeCache</entry>
+
<entry><literal>org.hibernate.cache.TreeCacheProvider</literal></entry>
+ <entry>clustered (ip multicast), transactional</entry>
+ <entry>yes (replication)</entry>
+ <entry>yes (clock sync req.)</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <sect2 id="performance-cache-mapping" revision="2">
+ <title>Cache mappings</title>
+
+ <para>
+ The <literal><cache></literal> element of a
class or collection mapping has the
+ following form:
+ </para>
+
+ <programlistingco>
+ <areaspec>
+ <area id="cache1" coords="2 70"/>
+ <area id="cache2" coords="3 70"/>
+ <area id="cache3" coords="4 70"/>
+ </areaspec>
+ <programlisting><![CDATA[<cache
+ usage="transactional|read-write|nonstrict-read-write|read-only"
+ region="RegionName"
+ include="all|non-lazy"
+/>]]></programlisting>
+ <calloutlist>
+ <callout arearefs="cache1">
+ <para>
+ <literal>usage</literal> (required) specifies the
caching strategy:
+ <literal>transactional</literal>,
+ <literal>read-write</literal>,
+ <literal>nonstrict-read-write</literal> or
+ <literal>read-only</literal>
+ </para>
+ </callout>
+ <callout arearefs="cache2">
+ <para>
+ <literal>region</literal> (optional, defaults to
the class or
+ collection role name) specifies the name of the second level
cache
+ region
+ </para>
+ </callout>
+ <callout arearefs="cache3">
+ <para>
+ <literal>include</literal> (optional, defaults to
<literal>all</literal>)
+ <literal>non-lazy</literal> specifies that
properties of the entity mapped
+ with <literal>lazy="true"</literal> may
not be cached when attribute-level
+ lazy fetching is enabled
+ </para>
+ </callout>
+ </calloutlist>
+ </programlistingco>
+
+ <para>
+ Alternatively (preferrably?), you may specify
<literal><class-cache></literal> and
+ <literal><collection-cache></literal> elements
in <literal>hibernate.cfg.xml</literal>.
+ </para>
+
+ <para>
+ The <literal>usage</literal> attribute specifies a
<emphasis>cache concurrency strategy</emphasis>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-cache-readonly">
+ <title>Strategy: read only</title>
+
+ <para>
+ If your application needs to read but never modify instances of a
persistent class, a
+ <literal>read-only</literal> cache may be used. This is the
simplest and best performing
+ strategy. It's even perfectly safe for use in a cluster.
+ </para>
+
+ <programlisting><![CDATA[<class name="eg.Immutable"
mutable="false">
+ <cache usage="read-only"/>
+ ....
+</class>]]></programlisting>
+
+ </sect2>
+
+
+ <sect2 id="performance-cache-readwrite">
+ <title>Strategy: read/write</title>
+
+ <para>
+ If the application needs to update data, a
<literal>read-write</literal> cache might be appropriate.
+ This cache strategy should never be used if serializable transaction
isolation level is required.
+ If the cache is used in a JTA environment, you must specify the property
+
<literal>hibernate.transaction.manager_lookup_class</literal>, naming a
strategy for obtaining the
+ JTA <literal>TransactionManager</literal>. In other
environments, you should ensure that the transaction
+ is completed when <literal>Session.close()</literal> or
<literal>Session.disconnect()</literal> is called.
+ If you wish to use this strategy in a cluster, you should ensure that the
underlying cache implementation
+ supports locking. The built-in cache providers do
<emphasis>not</emphasis>.
+ </para>
+
+ <programlisting><![CDATA[<class name="eg.Cat" ....
>
+ <cache usage="read-write"/>
+ ....
+ <set name="kittens" ... >
+ <cache usage="read-write"/>
+ ....
+ </set>
+</class>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="performance-cache-nonstrict">
+ <title>Strategy: nonstrict read/write</title>
+
+ <para>
+ If the application only occasionally needs to update data (ie. if it is
extremely unlikely that two
+ transactions would try to update the same item simultaneously) and strict
transaction isolation is
+ not required, a <literal>nonstrict-read-write</literal> cache
might be appropriate. If the cache is
+ used in a JTA environment, you must specify
<literal>hibernate.transaction.manager_lookup_class</literal>.
+ In other environments, you should ensure that the transaction is
completed when
+ <literal>Session.close()</literal> or
<literal>Session.disconnect()</literal> is called.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-cache-transactional">
+ <title>Strategy: transactional</title>
+
+ <para>
+ The <literal>transactional</literal> cache strategy provides
support for fully transactional cache
+ providers such as JBoss TreeCache. Such a cache may only be used in a JTA
environment and you must
+ specify
<literal>hibernate.transaction.manager_lookup_class</literal>.
+ </para>
+
+ </sect2>
+
+ <para>
+ None of the cache providers support all of the cache concurrency strategies.
The following table shows
+ which providers are compatible with which concurrency strategies.
+ </para>
+
+ <table frame="topbot">
+ <title>Cache Concurrency Strategy Support</title>
+ <tgroup cols='5' align='left' colsep='1'
rowsep='1'>
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="1*"/>
+ <colspec colname='c3' colwidth="1*"/>
+ <colspec colname='c4' colwidth="1*"/>
+ <colspec colname='c5' colwidth="1*"/>
+ <thead>
+ <row>
+ <entry>Cache</entry>
+ <entry>read-only</entry>
+ <entry>nonstrict-read-write</entry>
+ <entry>read-write</entry>
+ <entry>transactional</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Hashtable (not intended for production use)</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>EHCache</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>OSCache</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>SwarmCache</entry>
+ <entry>yes</entry>
+ <entry>yes</entry>
+ <entry></entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry>JBoss TreeCache</entry>
+ <entry>yes</entry>
+ <entry></entry>
+ <entry></entry>
+ <entry>yes</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect1>
+
+ <sect1 id="performance-sessioncache" revision="2">
+ <title>Managing the caches</title>
+
+ <para>
+ Whenever you pass an object to <literal>save()</literal>,
<literal>update()</literal>
+ or <literal>saveOrUpdate()</literal> and whenever you retrieve an
object using
+ <literal>load()</literal>, <literal>get()</literal>,
<literal>list()</literal>,
+ <literal>iterate()</literal> or
<literal>scroll()</literal>, that object is added
+ to the internal cache of the <literal>Session</literal>.
+ </para>
+ <para>
+ When <literal>flush()</literal> is subsequently called, the state
of that object will
+ be synchronized with the database. If you do not want this synchronization to
occur or
+ if you are processing a huge number of objects and need to manage memory
efficiently,
+ the <literal>evict()</literal> method may be used to remove the
object and its collections
+ from the first-level cache.
+ </para>
+
+ <programlisting><![CDATA[ScrollableResult cats =
sess.createQuery("from Cat as cat").scroll(); //a huge result set
+while ( cats.next() ) {
+ Cat cat = (Cat) cats.get(0);
+ doSomethingWithACat(cat);
+ sess.evict(cat);
+}]]></programlisting>
+
+ <para>
+ The <literal>Session</literal> also provides a
<literal>contains()</literal> method to determine
+ if an instance belongs to the session cache.
+ </para>
+
+ <para>
+ To completely evict all objects from the session cache, call
<literal>Session.clear()</literal>
+ </para>
+
+ <para>
+ For the second-level cache, there are methods defined on
<literal>SessionFactory</literal> for
+ evicting the cached state of an instance, entire class, collection instance
or entire collection
+ role.
+ </para>
+
+ <programlisting><![CDATA[sessionFactory.evict(Cat.class, catId); //evict
a particular Cat
+sessionFactory.evict(Cat.class); //evict all Cats
+sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular
collection of kittens
+sessionFactory.evictCollection("Cat.kittens"); //evict all kitten
collections]]></programlisting>
+
+ <para>
+ The <literal>CacheMode</literal> controls how a particular
session interacts with the second-level
+ cache.
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <literal>CacheMode.NORMAL</literal> - read items from and write
items to the second-level cache
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>CacheMode.GET</literal> - read items from the
second-level cache, but don't write to
+ the second-level cache except when updating data
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>CacheMode.PUT</literal> - write items to the
second-level cache, but don't read from
+ the second-level cache
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>CacheMode.REFRESH</literal> - write items to the
second-level cache, but don't read from
+ the second-level cache, bypass the effect of
<literal>hibernate.cache.use_minimal_puts</literal>, forcing
+ a refresh of the second-level cache for all items read from the database
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ To browse the contents of a second-level or query cache region, use the
<literal>Statistics</literal>
+ API:
+ </para>
+
+ <programlisting><![CDATA[Map cacheEntries =
sessionFactory.getStatistics()
+ .getSecondLevelCacheStatistics(regionName)
+ .getEntries();]]></programlisting>
+
+ <para>
+ You'll need to enable statistics, and, optionally, force Hibernate to
keep the cache entries in a
+ more human-understandable format:
+ </para>
+
+ <programlisting><![CDATA[hibernate.generate_statistics true
+hibernate.cache.use_structured_entries true]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="performance-querycache" revision="1">
+ <title>The Query Cache</title>
+
+ <para>
+ Query result sets may also be cached. This is only useful for queries that
are run
+ frequently with the same parameters. To use the query cache you must first
enable it:
+ </para>
+
+ <programlisting><![CDATA[hibernate.cache.use_query_cache
true]]></programlisting>
+
+ <para>
+ This setting causes the creation of two new cache regions - one holding
cached query
+ result sets
(<literal>org.hibernate.cache.StandardQueryCache</literal>), the other
+ holding timestamps of the most recent updates to queryable tables
+ (<literal>org.hibernate.cache.UpdateTimestampsCache</literal>).
Note that the query
+ cache does not cache the state of the actual entities in the result set; it
caches
+ only identifier values and results of value type. So the query cache should
always be
+ used in conjunction with the second-level cache.
+ </para>
+
+ <para>
+ Most queries do not benefit from caching, so by default queries are not
cached. To
+ enable caching, call <literal>Query.setCacheable(true)</literal>.
This call allows
+ the query to look for existing cache results or add its results to the cache
when
+ it is executed.
+ </para>
+
+ <para>
+ If you require fine-grained control over query cache expiration policies, you
may
+ specify a named cache region for a particular query by calling
+ <literal>Query.setCacheRegion()</literal>.
+ </para>
+
+ <programlisting><![CDATA[List blogs = sess.createQuery("from Blog
blog where blog.blogger = :blogger")
+ .setEntity("blogger", blogger)
+ .setMaxResults(15)
+ .setCacheable(true)
+ .setCacheRegion("frontpages")
+ .list();]]></programlisting>
+
+ <para>
+ If the query should force a refresh of its query cache region, you should
call
+ <literal>Query.setCacheMode(CacheMode.REFRESH)</literal>. This is
particularly useful
+ in cases where underlying data may have been updated via a separate process
(i.e.,
+ not modified through Hibernate) and allows the application to selectively
refresh
+ particular query result sets. This is a more efficient alternative to
eviction of
+ a query cache region via
<literal>SessionFactory.evictQueries()</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="performance-collections">
+ <title>Understanding Collection performance</title>
+
+ <para>
+ We've already spent quite some time talking about collections.
+ In this section we will highlight a couple more issues about
+ how collections behave at runtime.
+ </para>
+
+ <sect2 id="performance-collections-taxonomy">
+ <title>Taxonomy</title>
+
+ <para>Hibernate defines three basic kinds of collections:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>collections of values</para>
+ </listitem>
+ <listitem>
+ <para>one to many associations</para>
+ </listitem>
+ <listitem>
+ <para>many to many associations</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ This classification distinguishes the various table and foreign key
+ relationships but does not tell us quite everything we need to know
+ about the relational model. To fully understand the relational structure
+ and performance characteristics, we must also consider the structure of
+ the primary key that is used by Hibernate to update or delete collection
+ rows. This suggests the following classification:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>indexed collections</para>
+ </listitem>
+ <listitem>
+ <para>sets</para>
+ </listitem>
+ <listitem>
+ <para>bags</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ All indexed collections (maps, lists, arrays) have a primary key
consisting
+ of the <literal><key></literal> and
<literal><index></literal>
+ columns. In this case collection updates are usually extremely efficient
-
+ the primary key may be efficiently indexed and a particular row may be
efficiently
+ located when Hibernate tries to update or delete it.
+ </para>
+
+ <para>
+ Sets have a primary key consisting of
<literal><key></literal> and element
+ columns. This may be less efficient for some types of collection element,
particularly
+ composite elements or large text or binary fields; the database may not
be able to index
+ a complex primary key as efficently. On the other hand, for one to many
or many to many
+ associations, particularly in the case of synthetic identifiers, it is
likely to be just
+ as efficient. (Side-note: if you want
<literal>SchemaExport</literal> to actually create
+ the primary key of a <literal><set></literal>
for you, you must declare all columns
+ as <literal>not-null="true"</literal>.)
+ </para>
+
+ <para>
+ <literal><idbag></literal> mappings define a
surrogate key, so they are
+ always very efficient to update. In fact, they are the best case.
+ </para>
+
+ <para>
+ Bags are the worst case. Since a bag permits duplicate element values and
has no
+ index column, no primary key may be defined. Hibernate has no way of
distinguishing
+ between duplicate rows. Hibernate resolves this problem by completely
removing
+ (in a single <literal>DELETE</literal>) and recreating the
collection whenever it
+ changes. This might be very inefficient.
+ </para>
+
+ <para>
+ Note that for a one-to-many association, the "primary key" may
not be the physical
+ primary key of the database table - but even in this case, the above
classification
+ is still useful. (It still reflects how Hibernate "locates"
individual rows of the
+ collection.)
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-collections-mostefficientupdate">
+ <title>Lists, maps, idbags and sets are the most efficient collections
to update</title>
+
+ <para>
+ From the discussion above, it should be clear that indexed collections
+ and (usually) sets allow the most efficient operation in terms of
adding,
+ removing and updating elements.
+ </para>
+
+ <para>
+ There is, arguably, one more advantage that indexed collections have over
sets for
+ many to many associations or collections of values. Because of the
structure of a
+ <literal>Set</literal>, Hibernate doesn't ever
<literal>UPDATE</literal> a row when
+ an element is "changed". Changes to a
<literal>Set</literal> always work via
+ <literal>INSERT</literal> and
<literal>DELETE</literal> (of individual rows). Once
+ again, this consideration does not apply to one to many associations.
+ </para>
+
+ <para>
+ After observing that arrays cannot be lazy, we would conclude that lists,
maps and
+ idbags are the most performant (non-inverse) collection types, with sets
not far
+ behind. Sets are expected to be the most common kind of collection in
Hibernate
+ applications. This is because the "set" semantics are most
natural in the relational
+ model.
+ </para>
+
+ <para>
+ However, in well-designed Hibernate domain models, we usually see that
most collections
+ are in fact one-to-many associations with
<literal>inverse="true"</literal>. For these
+ associations, the update is handled by the many-to-one end of the
association, and so
+ considerations of collection update performance simply do not apply.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-collections-mostefficentinverse">
+ <title>Bags and lists are the most efficient inverse
collections</title>
+
+ <para>
+ Just before you ditch bags forever, there is a particular case in which
bags (and also lists)
+ are much more performant than sets. For a collection with
<literal>inverse="true"</literal>
+ (the standard bidirectional one-to-many relationship idiom, for example)
we can add elements
+ to a bag or list without needing to initialize (fetch) the bag elements!
This is because
+ <literal>Collection.add()</literal> or
<literal>Collection.addAll()</literal> must always
+ return true for a bag or <literal>List</literal> (unlike a
<literal>Set</literal>). This can
+ make the following common code much faster.
+ </para>
+
+ <programlisting><![CDATA[Parent p = (Parent) sess.load(Parent.class,
id);
+Child c = new Child();
+c.setParent(p);
+p.getChildren().add(c); //no need to fetch the collection!
+sess.flush();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="performance-collections-oneshotdelete">
+ <title>One shot delete</title>
+
+ <para>
+ Occasionally, deleting collection elements one by one can be extremely
inefficient. Hibernate
+ isn't completely stupid, so it knows not to do that in the case of an
newly-empty collection
+ (if you called <literal>list.clear()</literal>, for example).
In this case, Hibernate will
+ issue a single <literal>DELETE</literal> and we are done!
+ </para>
+
+ <para>
+ Suppose we add a single element to a collection of size twenty and then
remove two elements.
+ Hibernate will issue one <literal>INSERT</literal> statement
and two <literal>DELETE</literal>
+ statements (unless the collection is a bag). This is certainly
desirable.
+ </para>
+
+ <para>
+ However, suppose that we remove eighteen elements, leaving two and then
add thee new elements.
+ There are two possible ways to proceed
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>delete eighteen rows one by one and then insert three
rows</para>
+ </listitem>
+ <listitem>
+ <para>remove the whole collection (in one SQL
<literal>DELETE</literal>) and insert
+ all five current elements (one by one)</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Hibernate isn't smart enough to know that the second option is
probably quicker in this case.
+ (And it would probably be undesirable for Hibernate to be that smart;
such behaviour might
+ confuse database triggers, etc.)
+ </para>
+
+ <para>
+ Fortunately, you can force this behaviour (ie. the second strategy) at
any time by discarding
+ (ie. dereferencing) the original collection and returning a newly
instantiated collection with
+ all the current elements. This can be very useful and powerful from time
to time.
+ </para>
+
+ <para>
+ Of course, one-shot-delete does not apply to collections mapped
<literal>inverse="true"</literal>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="performance-monitoring" revision="1">
+ <title>Monitoring performance</title>
+
+ <para>
+ Optimization is not much use without monitoring and access to performance
numbers.
+ Hibernate provides a full range of figures about its internal operations.
+ Statistics in Hibernate are available per
<literal>SessionFactory</literal>.
+ </para>
+
+ <sect2 id="performance-monitoring-sf" revision="2">
+ <title>Monitoring a SessionFactory</title>
+
+ <para>
+ You can access <literal>SessionFactory</literal> metrics in
two ways.
+ Your first option is to call
<literal>sessionFactory.getStatistics()</literal> and
+ read or display the <literal>Statistics</literal> yourself.
+ </para>
+
+ <para>
+ Hibernate can also use JMX to publish metrics if you enable the
+ <literal>StatisticsService</literal> MBean. You may enable a
single MBean for all your
+ <literal>SessionFactory</literal> or one per factory. See the
following code for
+ minimalistic configuration examples:
+ </para>
+
+ <programlisting><![CDATA[// MBean service registration for a
specific SessionFactory
+Hashtable tb = new Hashtable();
+tb.put("type", "statistics");
+tb.put("sessionFactory", "myFinancialApp");
+ObjectName on = new ObjectName("hibernate", tb); // MBean object name
+
+StatisticsService stats = new StatisticsService(); // MBean implementation
+stats.setSessionFactory(sessionFactory); // Bind the stats to a SessionFactory
+server.registerMBean(stats, on); // Register the Mbean on the
server]]></programlisting>
+
+
+<programlisting><![CDATA[// MBean service registration for all
SessionFactory's
+Hashtable tb = new Hashtable();
+tb.put("type", "statistics");
+tb.put("sessionFactory", "all");
+ObjectName on = new ObjectName("hibernate", tb); // MBean object name
+
+StatisticsService stats = new StatisticsService(); // MBean implementation
+server.registerMBean(stats, on); // Register the MBean on the
server]]></programlisting>
+
+ <para>
+ TODO: This doesn't make sense: In the first case, we retrieve and use
the MBean directly. In the second one, we must give
+ the JNDI name in which the session factory is held before using it. Use
+
<literal>hibernateStatsBean.setSessionFactoryJNDIName("my/JNDI/Name")</literal>
+ </para>
+ <para>
+ You can (de)activate the monitoring for a
<literal>SessionFactory</literal>
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ at configuration time, set
<literal>hibernate.generate_statistics</literal> to
<literal>false</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+ <itemizedlist>
+ <listitem>
+ <para>
+ at runtime:
<literal>sf.getStatistics().setStatisticsEnabled(true)</literal>
+ or
<literal>hibernateStatsBean.setStatisticsEnabled(true)</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Statistics can be reset programatically using the
<literal>clear()</literal> method.
+ A summary can be sent to a logger (info level) using the
<literal>logSummary()</literal>
+ method.
+ </para>
+
+ </sect2>
+
+ <sect2 id="performance-monitoring-metrics"
revision="1">
+ <title>Metrics</title>
+
+ <para>
+ Hibernate provides a number of metrics, from very basic to the
specialized information
+ only relevant in certain scenarios. All available counters are described
in the
+ <literal>Statistics</literal> interface API, in three
categories:
+ </para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ Metrics related to the general
<literal>Session</literal> usage, such as
+ number of open sessions, retrieved JDBC connections, etc.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Metrics related to he entities, collections, queries, and caches
as a
+ whole (aka global metrics),
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Detailed metrics related to a particular entity, collection,
query or
+ cache region.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ For exampl,e you can check the cache hit, miss, and put ratio of
entities, collections
+ and queries, and the average time a query needs. Beware that the number
of milliseconds
+ is subject to approximation in Java. Hibernate is tied to the JVM
precision, on some
+ platforms this might even only be accurate to 10 seconds.
+ </para>
+
+ <para>
+ Simple getters are used to access the global metrics (i.e. not tied to a
particular entity,
+ collection, cache region, etc.). You can access the metrics of a
particular entity, collection
+ or cache region through its name, and through its HQL or SQL
representation for queries. Please
+ refer to the <literal>Statistics</literal>,
<literal>EntityStatistics</literal>,
+ <literal>CollectionStatistics</literal>,
<literal>SecondLevelCacheStatistics</literal>,
+ and <literal>QueryStatistics</literal> API Javadoc for more
information. The following
+ code shows a simple example:
+ </para>
+
+ <programlisting><![CDATA[Statistics stats =
HibernateUtil.sessionFactory.getStatistics();
+
+double queryCacheHitCount = stats.getQueryCacheHitCount();
+double queryCacheMissCount = stats.getQueryCacheMissCount();
+double queryCacheHitRatio =
+ queryCacheHitCount / (queryCacheHitCount + queryCacheMissCount);
+
+log.info("Query Hit ratio:" + queryCacheHitRatio);
+
+EntityStatistics entityStats =
+ stats.getEntityStatistics( Cat.class.getName() );
+long changes =
+ entityStats.getInsertCount()
+ + entityStats.getUpdateCount()
+ + entityStats.getDeleteCount();
+log.info(Cat.class.getName() + " changed " + changes + "times"
);]]></programlisting>
+
+ <para>
+ To work on all entities, collections, queries and region caches, you can
retrieve
+ the list of names of entities, collections, queries and region caches
with the
+ following methods: <literal>getQueries()</literal>,
<literal>getEntityNames()</literal>,
+ <literal>getCollectionRoleNames()</literal>, and
+ <literal>getSecondLevelCacheRegionNames()</literal>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+</chapter>
\ No newline at end of file
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/performance.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/persistent_classes.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/persistent_classes.xml 2006-08-14
14:43:45 UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/persistent_classes.xml 2006-08-14
14:55:10 UTC (rev 10262)
@@ -0,0 +1,531 @@
+<chapter id="persistent-classes" revision="2">
+ <title>Persistent Classes</title>
+
+ <para>
+ Persistent classes are classes in an application that implement the entities
+ of the business problem (e.g. Customer and Order in an E-commerce application).
+ Not all instances of a persistent class are considered to be in the persistent
+ state - an instance may instead be transient or detached.
+ </para>
+
+ <para>
+ Hibernate works best if these classes follow some simple rules, also known
+ as the Plain Old Java Object (POJO) programming model. However, none of these
+ rules are hard requirements. Indeed, Hibernate3 assumes very little about
+ the nature of your persistent objects. You may express a domain model in other
+ ways: using trees of <literal>Map</literal> instances, for example.
+ </para>
+
+ <sect1 id="persistent-classes-pojo">
+ <title>A simple POJO example</title>
+
+ <para>
+ Most Java applications require a persistent class representing felines.
+ </para>
+
+ <programlisting><![CDATA[package eg;
+import java.util.Set;
+import java.util.Date;
+
+public class Cat {
+ private Long id; // identifier
+
+ private Date birthdate;
+ private Color color;
+ private char sex;
+ private float weight;
+ private int litterId;
+
+ private Cat mother;
+ private Set kittens = new HashSet();
+
+ private void setId(Long id) {
+ this.id=id;
+ }
+ public Long getId() {
+ return id;
+ }
+
+ void setBirthdate(Date date) {
+ birthdate = date;
+ }
+ public Date getBirthdate() {
+ return birthdate;
+ }
+
+ void setWeight(float weight) {
+ this.weight = weight;
+ }
+ public float getWeight() {
+ return weight;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+ void setColor(Color color) {
+ this.color = color;
+ }
+
+ void setSex(char sex) {
+ this.sex=sex;
+ }
+ public char getSex() {
+ return sex;
+ }
+
+ void setLitterId(int id) {
+ this.litterId = id;
+ }
+ public int getLitterId() {
+ return litterId;
+ }
+
+ void setMother(Cat mother) {
+ this.mother = mother;
+ }
+ public Cat getMother() {
+ return mother;
+ }
+ void setKittens(Set kittens) {
+ this.kittens = kittens;
+ }
+ public Set getKittens() {
+ return kittens;
+ }
+
+ // addKitten not needed by Hibernate
+ public void addKitten(Cat kitten) {
+ kitten.setMother(this);
+ kitten.setLitterId( kittens.size() );
+ kittens.add(kitten);
+ }
+}]]></programlisting>
+
+ <para>
+ There are four main rules to follow here:
+ </para>
+
+
+ <sect2 id="persistent-classes-pojo-constructor"
revision="1">
+ <title>Implement a no-argument constructor</title>
+
+ <para>
+ <literal>Cat</literal> has a no-argument constructor. All
persistent classes must
+ have a default constructor (which may be non-public) so that Hibernate
can instantiate
+ them using <literal>Constructor.newInstance()</literal>. We
strongly recommend having a
+ default constructor with at least
<emphasis>package</emphasis> visibility for runtime proxy
+ generation in Hibernate.
+ </para>
+ </sect2>
+
+ <sect2 id="persistent-classes-pojo-identifier"
revision="2">
+ <title>Provide an identifier property (optional)</title>
+
+ <para>
+ <literal>Cat</literal> has a property called
<literal>id</literal>. This property
+ maps to the primary key column of a database table. The property might
have been called
+ anything, and its type might have been any primitive type, any primitive
"wrapper"
+ type, <literal>java.lang.String</literal> or
<literal>java.util.Date</literal>. (If
+ your legacy database table has composite keys, you can even use a
user-defined class
+ with properties of these types - see the section on composite identifiers
later.)
+ </para>
+
+ <para>
+ The identifier property is strictly optional. You can leave them off and
let Hibernate
+ keep track of object identifiers internally. We do not recommend this,
however.
+ </para>
+
+ <para>
+ In fact, some functionality is available only to classes which declare
an
+ identifier property:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Transitive reattachment for detached objects (cascade update or
cascade
+ merge) - see <xref
linkend="objectstate-transitive"/>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Session.saveOrUpdate()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Session.merge()</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ We recommend you declare consistently-named identifier properties on
persistent
+ classes. We further recommend that you use a nullable (ie. non-primitive)
type.
+ </para>
+ </sect2>
+
+ <sect2 id="persistent-classes-pojo-final">
+ <title>Prefer non-final classes (optional)</title>
+ <para>
+ A central feature of Hibernate, <emphasis>proxies</emphasis>,
depends upon the
+ persistent class being either non-final, or the implementation of an
interface
+ that declares all public methods.
+ </para>
+ <para>
+ You can persist <literal>final</literal> classes that do not
implement an interface
+ with Hibernate, but you won't be able to use proxies for lazy
association fetching -
+ which will limit your options for performance tuning.
+ </para>
+ <para>
+ You should also avoid declaring <literal>public
final</literal> methods on the
+ non-final classes. If you want to use a class with a
<literal>public final</literal>
+ method, you must explicitly disable proying by setting
<literal>lazy="false"</literal>.
+ </para>
+ </sect2>
+
+ <sect2 id="persistent-classes-pojo-accessors"
revision="2">
+ <title>Declare accessors and mutators for persistent fields
(optional)</title>
+
+ <para>
+ <literal>Cat</literal> declares accessor methods for all its
persistent fields.
+ Many other ORM tools directly persist instance variables. We believe it
is
+ better to provide an indirection between the relational schema and
internal
+ data structures of the class. By default, Hibernate persists JavaBeans
style
+ properties, and recognizes method names of the form
<literal>getFoo</literal>,
+ <literal>isFoo</literal> and
<literal>setFoo</literal>. You may switch to direct
+ field access for particular properties, if needed.
+ </para>
+
+ <para>
+ Properties need <emphasis>not</emphasis> be declared public -
Hibernate can
+ persist a property with a default,
<literal>protected</literal> or
+ <literal>private</literal> get / set pair.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="persistent-classes-inheritance">
+ <title>Implementing inheritance</title>
+
+ <para>
+ A subclass must also observe the first and second rules. It inherits its
+ identifier property from the superclass, <literal>Cat</literal>.
+ </para>
+
+ <programlisting><![CDATA[package eg;
+
+public class DomesticCat extends Cat {
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+ protected void setName(String name) {
+ this.name=name;
+ }
+}]]></programlisting>
+ </sect1>
+
+ <sect1 id="persistent-classes-equalshashcode"
revision="1">
+ <title>Implementing <literal>equals()</literal> and
<literal>hashCode()</literal></title>
+
+ <para>
+ You have to override the <literal>equals()</literal> and
<literal>hashCode()</literal>
+ methods if you
+ </para>
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ intend to put instances of persistent classes in a
<literal>Set</literal>
+ (the recommended way to represent many-valued associations)
+ <emphasis>and</emphasis>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ intend to use reattachment of detached instances
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Hibernate guarantees equivalence of persistent identity (database row) and
Java identity
+ only inside a particular session scope. So as soon as we mix instances
retrieved in
+ different sessions, we must implement <literal>equals()</literal>
and
+ <literal>hashCode()</literal> if we wish to have meaningful
semantics for
+ <literal>Set</literal>s.
+ </para>
+
+ <para>
+ The most obvious way is to implement
<literal>equals()</literal>/<literal>hashCode()</literal>
+ by comparing the identifier value of both objects. If the value is the same,
both must
+ be the same database row, they are therefore equal (if both are added to a
<literal>Set</literal>,
+ we will only have one element in the <literal>Set</literal>).
Unfortunately, we can't use that
+ approach with generated identifiers! Hibernate will only assign identifier
values to objects
+ that are persistent, a newly created instance will not have any identifier
value! Furthermore,
+ if an instance is unsaved and currently in a
<literal>Set</literal>, saving it will assign
+ an identifier value to the object. If <literal>equals()</literal>
and <literal>hashCode()</literal>
+ are based on the identifier value, the hash code would change, breaking the
contract of the
+ <literal>Set</literal>. See the Hibernate website for a full
discussion of this problem. Note
+ that this is not a Hibernate issue, but normal Java semantics of object
identity and equality.
+ </para>
+
+ <para>
+ We recommend implementing <literal>equals()</literal> and
<literal>hashCode()</literal>
+ using <emphasis>Business key equality</emphasis>. Business key
equality means that the
+ <literal>equals()</literal> method compares only the properties
that form the business
+ key, a key that would identify our instance in the real world (a
+ <emphasis>natural</emphasis> candidate key):
+ </para>
+
+ <programlisting><![CDATA[public class Cat {
+
+ ...
+ public boolean equals(Object other) {
+ if (this == other) return true;
+ if ( !(other instanceof Cat) ) return false;
+
+ final Cat cat = (Cat) other;
+
+ if ( !cat.getLitterId().equals( getLitterId() ) ) return false;
+ if ( !cat.getMother().equals( getMother() ) ) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = getMother().hashCode();
+ result = 29 * result + getLitterId();
+ return result;
+ }
+
+}]]></programlisting>
+
+ <para>
+ Note that a business key does not have to be as solid as a database
+ primary key candidate (see <xref
linkend="transactions-basics-identity"/>).
+ Immutable or unique properties are usually good
+ candidates for a business key.
+ </para>
+
+ </sect1>
+
+ <sect1 id="persistent-classes-dynamicmodels">
+ <title>Dynamic models</title>
+
+ <para>
+ <emphasis>Note that the following features are currently considered
+ experimental and may change in the near future.</emphasis>
+ </para>
+
+ <para>
+ Persistent entities don't necessarily have to be represented as POJO
classes
+ or as JavaBean objects at runtime. Hibernate also supports dynamic models
+ (using <literal>Map</literal>s of
<literal>Map</literal>s at runtime) and the
+ representation of entities as DOM4J trees. With this approach, you don't
+ write persistent classes, only mapping files.
+ </para>
+
+ <para>
+ By default, Hibernate works in normal POJO mode. You may set a default
entity
+ representation mode for a particular
<literal>SessionFactory</literal> using the
+ <literal>default_entity_mode</literal> configuration option (see
+ <xref linkend="configuration-optional-properties"/>.
+ </para>
+
+ <para>
+ The following examples demonstrates the representation using
<literal>Map</literal>s.
+ First, in the mapping file, an <literal>entity-name</literal> has
to be declared
+ instead of (or in addition to) a class name:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class entity-name="Customer">
+
+ <id name="id"
+ type="long"
+ column="ID">
+ <generator class="sequence"/>
+ </id>
+
+ <property name="name"
+ column="NAME"
+ type="string"/>
+
+ <property name="address"
+ column="ADDRESS"
+ type="string"/>
+
+ <many-to-one name="organization"
+ column="ORGANIZATION_ID"
+ class="Organization"/>
+
+ <bag name="orders"
+ inverse="true"
+ lazy="false"
+ cascade="all">
+ <key column="CUSTOMER_ID"/>
+ <one-to-many class="Order"/>
+ </bag>
+
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+
+ Note that even though associations are declared using target class names,
+ the target type of an associations may also be a dynamic entity instead
+ of a POJO.
+ </para>
+
+ <para>
+ After setting the default entity mode to
<literal>dynamic-map</literal>
+ for the <literal>SessionFactory</literal>, we can at runtime work
with
+ <literal>Map</literal>s of <literal>Map</literal>s:
+ </para>
+
+ <programlisting><![CDATA[Session s = openSession();
+Transaction tx = s.beginTransaction();
+Session s = openSession();
+
+// Create a customer
+Map david = new HashMap();
+david.put("name", "David");
+
+// Create an organization
+Map foobar = new HashMap();
+foobar.put("name", "Foobar Inc.");
+
+// Link both
+david.put("organization", foobar);
+
+// Save both
+s.save("Customer", david);
+s.save("Organization", foobar);
+
+tx.commit();
+s.close();]]></programlisting>
+
+ <para>
+ The advantages of a dynamic mapping are quick turnaround time for
prototyping
+ without the need for entity class implementation. However, you lose
compile-time
+ type checking and will very likely deal with many exceptions at runtime.
Thanks
+ to the Hibernate mapping, the database schema can easily be normalized and
sound,
+ allowing to add a proper domain model implementation on top later on.
+ </para>
+
+ <para>
+ Entity representation modes can also be set on a per
<literal>Session</literal>
+ basis:
+ </para>
+
+ <programlisting><![CDATA[Session dynamicSession =
pojoSession.getSession(EntityMode.MAP);
+
+// Create a customer
+Map david = new HashMap();
+david.put("name", "David");
+dynamicSession.save("Customer", david);
+...
+dynamicSession.flush();
+dynamicSession.close()
+...
+// Continue on pojoSession
+]]></programlisting>
+
+
+ <para>
+ Please note that the call to <literal>getSession()</literal>
using an
+ <literal>EntityMode</literal> is on the
<literal>Session</literal> API, not the
+ <literal>SessionFactory</literal>. That way, the new
<literal>Session</literal>
+ shares the underlying JDBC connection, transaction, and other context
+ information. This means you don't have tocall
<literal>flush()</literal>
+ and <literal>close()</literal> on the secondary
<literal>Session</literal>, and
+ also leave the transaction and connection handling to the primary unit of
work.
+ </para>
+
+ <para>
+ More information about the XML representation capabilities can be found
+ in <xref linkend="xml"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="persistent-classes-tuplizers" revision="0">
+ <title>Tuplizers</title>
+
+ <para>
+ <literal>org.hibernate.tuple.Tuplizer</literal>, and its
sub-interfaces, are responsible
+ for managing a particular representation of a piece of data, given that
representation's
+ <literal>org.hibernate.EntityMode</literal>. If a given piece of
data is thought of as
+ a data structure, then a tuplizer is the thing which knows how to create such
a data structure
+ and how to extract values from and inject values into such a data structure.
For example,
+ for the POJO entity mode, the correpsonding tuplizer knows how create the
POJO through its
+ constructor and how to access the POJO properties using the defined property
accessors.
+ There are two high-level types of Tuplizers, represented by the
+ <literal>org.hibernate.tuple.EntityTuplizer</literal> and
<literal>org.hibernate.tuple.ComponentTuplizer</literal>
+ interfaces. <literal>EntityTuplizer</literal>s are responsible
for managing the above mentioned
+ contracts in regards to entities, while
<literal>ComponentTuplizer</literal>s do the same for
+ components.
+ </para>
+
+ <para>
+ Users may also plug in their own tuplizers. Perhaps you require that a
<literal>java.util.Map</literal>
+ implementation other than <literal>java.util.HashMap</literal> be
used while in the
+ dynamic-map entity-mode; or perhaps you need to define a different proxy
generation strategy
+ than the one used by default. Both would be achieved by defining a custom
tuplizer
+ implementation. Tuplizers definitions are attached to the entity or
component mapping they
+ are meant to manage. Going back to the example of our customer entity:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+ <class entity-name="Customer">
+ <!--
+ Override the dynamic-map entity-mode
+ tuplizer for the customer entity
+ -->
+ <tuplizer entity-mode="dynamic-map"
+ class="CustomMapTuplizerImpl"/>
+
+ <id name="id" type="long" column="ID">
+ <generator class="sequence"/>
+ </id>
+
+ <!-- other properties -->
+ ...
+ </class>
+</hibernate-mapping>
+
+
+public class CustomMapTuplizerImpl
+ extends org.hibernate.tuple.DynamicMapEntityTuplizer {
+ // override the buildInstantiator() method to plug in our custom map...
+ protected final Instantiator buildInstantiator(
+ org.hibernate.mapping.PersistentClass mappingInfo) {
+ return new CustomMapInstantiator( mappingInfo );
+ }
+
+ private static final class CustomMapInstantiator
+ extends org.hibernate.tuple.DynamicMapInstantitor {
+ // override the generateMap() method to return our custom map...
+ protected final Map generateMap() {
+ return new CustomMap();
+ }
+ }
+}]]></programlisting>
+
+
+ </sect1>
+
+ <para>
+ TODO: Document user-extension framework in the property and proxy packages
+ </para>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/persistent_classes.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/query_criteria.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/query_criteria.xml 2006-08-14 14:43:45
UTC (rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/query_criteria.xml 2006-08-14 14:55:10
UTC (rev 10262)
@@ -0,0 +1,436 @@
+<chapter id="querycriteria">
+ <title>Consultas por critérios</title>
+
+ <para>
+ O Hibernate provê uma intuitiva e extensível API de critério de query.
+ </para>
+
+ <sect1 id="querycriteria-creating">
+ <title>Criando uma instancia
<literal>Criteria</literal></title>
+
+ <para>
+ A interface <literal>org.hibernate.Criteria</literal> representa
a query
+ ao invés de uma classe persistente particular. A sessão é uma fábrica para
+ intancias de <literal>Criteria</literal> .
+ </para>
+
+ <programlisting><![CDATA[Criteria crit =
sess.createCriteria(Cat.class);
+crit.setMaxResults(50);
+List cats = crit.list();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-narrowing">
+ <title>Limitando o result set</title>
+
+ <para>
+ Um critério individual de query é uma instancia da interface
+ <literal>org.hibernate.criterion.Criterion</literal>. A classe
+ <literal>org.hibernate.criterion.Restrictions</literal> define
+ os métodos da fábrica para obter certos tipos pré fabricados
+ de <literal>Criterion</literal>.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.like("name", "Fritz%") )
+ .add( Restrictions.between("weight", minWeight, maxWeight) )
+ .list();]]></programlisting>
+
+ <para>
+ Restrições podem ser logicamente agrupadas.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.like("name", "Fritz%") )
+ .add( Restrictions.or(
+ Restrictions.eq( "age", new Integer(0) ),
+ Restrictions.isNull("age")
+ ) )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.in( "name", new String[] { "Fritz",
"Izi", "Pk" } ) )
+ .add( Restrictions.disjunction()
+ .add( Restrictions.isNull("age") )
+ .add( Restrictions.eq("age", new Integer(0) ) )
+ .add( Restrictions.eq("age", new Integer(1) ) )
+ .add( Restrictions.eq("age", new Integer(2) ) )
+ ) )
+ .list();]]></programlisting>
+
+ <para>
+ Existe um grande número de critérios pré fabricados (subclasses de
+ <literal>Restrictions</literal>), mas um é especialmente útil
pois
+ permite especificar o SQL diretamente.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.sqlRestriction("lower({alias}.name) like lower(?)",
"Fritz%", Hibernate.STRING) )
+ .list();]]></programlisting>
+
+ <para>
+ O parametro <literal>{alias}</literal> será substituido pelo
alias da entidade procurada.
+ </para>
+
+ <para>
+ Uma maneira alternativa de obter um critério é pegá-lo de uma instancia de
+ <literal>Property</literal>. Você pode criar uma
<literal>Property</literal>
+ chamando <literal>Property.forName()</literal>.
+ </para>
+
+ <programlisting><![CDATA[
+Property age = Property.forName("age");
+List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.disjunction()
+ .add( age.isNull() )
+ .add( age.eq( new Integer(0) ) )
+ .add( age.eq( new Integer(1) ) )
+ .add( age.eq( new Integer(2) ) )
+ ) )
+ .add( Property.forName("name").in( new String[] { "Fritz",
"Izi", "Pk" } ) )
+ .list();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-ordering">
+ <title>Ordering the results</title>
+
+ <para>
+ You may order the results using
<literal>org.hibernate.criterion.Order</literal>.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.like("name", "F%")
+ .addOrder( Order.asc("name") )
+ .addOrder( Order.desc("age") )
+ .setMaxResults(50)
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Property.forName("name").like("F%") )
+ .addOrder( Property.forName("name").asc() )
+ .addOrder( Property.forName("age").desc() )
+ .setMaxResults(50)
+ .list();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-associations" revision="2">
+ <title>Associations</title>
+
+ <para>
+ You may easily specify constraints upon related entities by navigating
+ associations using <literal>createCriteria()</literal>.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.like("name", "F%") )
+ .createCriteria("kittens")
+ .add( Restrictions.like("name", "F%") )
+ .list();]]></programlisting>
+
+ <para>
+ note that the second <literal>createCriteria()</literal> returns
a new
+ instance of <literal>Criteria</literal>, which refers to the
elements of
+ the <literal>kittens</literal> collection.
+ </para>
+
+ <para>
+ The following, alternate form is useful in certain circumstances.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .createAlias("kittens", "kt")
+ .createAlias("mate", "mt")
+ .add( Restrictions.eqProperty("kt.name", "mt.name") )
+ .list();]]></programlisting>
+
+ <para>
+ (<literal>createAlias()</literal> does not create a new instance
of
+ <literal>Criteria</literal>.)
+ </para>
+
+ <para>
+ Note that the kittens collections held by the
<literal>Cat</literal> instances
+ returned by the previous two queries are <emphasis>not</emphasis>
pre-filtered
+ by the criteria! If you wish to retrieve just the kittens that match the
+ criteria, you must use a <literal>ResultTransformer</literal>.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .createCriteria("kittens", "kt")
+ .add( Restrictions.eq("name", "F%") )
+ .setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)
+ .list();
+Iterator iter = cats.iterator();
+while ( iter.hasNext() ) {
+ Map map = (Map) iter.next();
+ Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
+ Cat kitten = (Cat) map.get("kt");
+}]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-dynamicfetching" revision="1">
+ <title>Dynamic association fetching</title>
+
+ <para>
+ You may specify association fetching semantics at runtime using
+ <literal>setFetchMode()</literal>.
+ </para>
+
+ <programlisting><![CDATA[List cats = sess.createCriteria(Cat.class)
+ .add( Restrictions.like("name", "Fritz%") )
+ .setFetchMode("mate", FetchMode.EAGER)
+ .setFetchMode("kittens", FetchMode.EAGER)
+ .list();]]></programlisting>
+
+ <para>
+ This query will fetch both <literal>mate</literal> and
<literal>kittens</literal>
+ by outer join. See <xref linkend="performance-fetching"/> for
more information.
+ </para>
+
+ </sect1>
+
+ <sect1 id="querycriteria-examples">
+ <title>Example queries</title>
+
+ <para>
+ The class <literal>org.hibernate.criterion.Example</literal>
allows
+ you to construct a query criterion from a given instance.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = new Cat();
+cat.setSex('F');
+cat.setColor(Color.BLACK);
+List results = session.createCriteria(Cat.class)
+ .add( Example.create(cat) )
+ .list();]]></programlisting>
+
+ <para>
+ Version properties, identifiers and associations are ignored. By default,
+ null valued properties are excluded.
+ </para>
+
+ <para>
+ You can adjust how the <literal>Example</literal> is applied.
+ </para>
+
+ <programlisting><![CDATA[Example example = Example.create(cat)
+ .excludeZeroes() //exclude zero valued properties
+ .excludeProperty("color") //exclude the property named "color"
+ .ignoreCase() //perform case insensitive string comparisons
+ .enableLike(); //use like for string comparisons
+List results = session.createCriteria(Cat.class)
+ .add(example)
+ .list();]]></programlisting>
+
+ <para>
+ You can even use examples to place criteria upon associated objects.
+ </para>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .add( Example.create(cat) )
+ .createCriteria("mate")
+ .add( Example.create( cat.getMate() ) )
+ .list();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-projection">
+ <title>Projections, aggregation and grouping</title>
+ <para>
+ The class <literal>org.hibernate.criterion.Projections</literal>
is a
+ factory for <literal>Projection</literal> instances. We apply a
+ projection to a query by calling
<literal>setProjection()</literal>.
+ </para>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.rowCount() )
+ .add( Restrictions.eq("color", Color.BLACK) )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.projectionList()
+ .add( Projections.rowCount() )
+ .add( Projections.avg("weight") )
+ .add( Projections.max("weight") )
+ .add( Projections.groupProperty("color") )
+ )
+ .list();]]></programlisting>
+
+ <para>
+ There is no explicit "group by" necessary in a criteria query.
Certain
+ projection types are defined to be <emphasis>grouping
projections</emphasis>,
+ which also appear in the SQL <literal>group by</literal> clause.
+ </para>
+
+ <para>
+ An alias may optionally be assigned to a projection, so that the projected
value
+ may be referred to in restrictions or orderings. Here are two different ways
to
+ do this:
+ </para>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.alias( Projections.groupProperty("color"),
"colr" ) )
+ .addOrder( Order.asc("colr") )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.groupProperty("color").as("colr") )
+ .addOrder( Order.asc("colr") )
+ .list();]]></programlisting>
+
+ <para>
+ The <literal>alias()</literal> and
<literal>as()</literal> methods simply wrap a
+ projection instance in another, aliased, instance of
<literal>Projection</literal>.
+ As a shortcut, you can assign an alias when you add the projection to a
+ projection list:
+ </para>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.projectionList()
+ .add( Projections.rowCount(), "catCountByColor" )
+ .add( Projections.avg("weight"), "avgWeight" )
+ .add( Projections.max("weight"), "maxWeight" )
+ .add( Projections.groupProperty("color"), "color" )
+ )
+ .addOrder( Order.desc("catCountByColor") )
+ .addOrder( Order.desc("avgWeight") )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Domestic.class, "cat")
+ .createAlias("kittens", "kit")
+ .setProjection( Projections.projectionList()
+ .add( Projections.property("cat.name"), "catName" )
+ .add( Projections.property("kit.name"), "kitName" )
+ )
+ .addOrder( Order.asc("catName") )
+ .addOrder( Order.asc("kitName") )
+ .list();]]></programlisting>
+
+ <para>
+ You can also use <literal>Property.forName()</literal> to express
projections:
+ </para>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Property.forName("name") )
+ .add( Property.forName("color").eq(Color.BLACK) )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[List results =
session.createCriteria(Cat.class)
+ .setProjection( Projections.projectionList()
+ .add( Projections.rowCount().as("catCountByColor") )
+ .add( Property.forName("weight").avg().as("avgWeight") )
+ .add( Property.forName("weight").max().as("maxWeight") )
+ .add( Property.forName("color").group().as("color" )
+ )
+ .addOrder( Order.desc("catCountByColor") )
+ .addOrder( Order.desc("avgWeight") )
+ .list();]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="querycriteria-detachedqueries">
+ <title>Detached queries and subqueries</title>
+ <para>
+ The <literal>DetachedCriteria</literal> class lets you create a
query outside the scope
+ of a session, and then later execute it using some arbitrary
<literal>Session</literal>.
+ </para>
+
+ <programlisting><![CDATA[DetachedCriteria query =
DetachedCriteria.forClass(Cat.class)
+ .add( Property.forName("sex").eq('F') );
+
+Session session = ....;
+Transaction txn = session.beginTransaction();
+List results = query.getExecutableCriteria(session).setMaxResults(100).list();
+txn.commit();
+session.close();]]></programlisting>
+
+ <para>
+ A <literal>DetachedCriteria</literal> may also be used to express
a subquery. Criterion
+ instances involving subqueries may be obtained via
<literal>Subqueries</literal> or
+ <literal>Property</literal>.
+ </para>
+
+ <programlisting><![CDATA[DetachedCriteria avgWeight =
DetachedCriteria.forClass(Cat.class)
+ .setProjection( Property.forName("weight").avg() );
+session.createCriteria(Cat.class)
+ .add( Property.forName("weight).gt(avgWeight) )
+ .list();]]></programlisting>
+
+ <programlisting><![CDATA[DetachedCriteria weights =
DetachedCriteria.forClass(Cat.class)
+ .setProjection( Property.forName("weight") );
+session.createCriteria(Cat.class)
+ .add( Subqueries.geAll("weight", weights) )
+ .list();]]></programlisting>
+
+ <para>
+ Even correlated subqueries are possible:
+ </para>
+
+ <programlisting><![CDATA[DetachedCriteria avgWeightForSex =
DetachedCriteria.forClass(Cat.class, "cat2")
+ .setProjection( Property.forName("weight").avg() )
+ .add( Property.forName("cat2.sex").eqProperty("cat.sex") );
+session.createCriteria(Cat.class, "cat")
+ .add( Property.forName("weight).gt(avgWeightForSex) )
+ .list();]]></programlisting>
+
+ </sect1>
+
+ <!--TODO: ResultSetTransformer + aliasing. AliasToBeanTransformer allow
returning arbitrary
+ user objects - similar to setResultClass in JDO2. General use of
ResultTransformer
+ could also be explained. -->
+
+ <sect1 id="query-criteria-naturalid">
+ <title>Queries by natural identifier</title>
+
+ <para>
+ For most queries, including criteria queries, the query cache is not very
efficient,
+ because query cache invalidation occurs too frequently. However, there is one
special
+ kind of query where we can optimize the cache invalidation algorithm: lookups
by a
+ constant natural key. In some applications, this kind of query occurs
frequently.
+ The criteria API provides special provision for this use case.
+ </para>
+
+ <para>
+ First, you should map the natural key of your entity using
+ <literal><natural-id></literal>, and enable use of
the second-level cache.
+ </para>
+
+ <programlisting><![CDATA[<class name="User">
+ <cache usage="read-write"/>
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <natural-id>
+ <property name="name"/>
+ <property name="org"/>
+ </natural-id>
+ <property name="password"/>
+</class>]]></programlisting>
+
+ <para>
+ Note that this functionality is not intended for use with entities with
+ <emphasis>mutable</emphasis> natural keys.
+ </para>
+
+ <para>
+ Next, enable the Hibernate query cache.
+ </para>
+
+ <para>
+ Now, <literal>Restrictions.naturalId()</literal> allows us to
make use of
+ the more efficient cache algorithm.
+ </para>
+
+ <programlisting><![CDATA[session.createCriteria(User.class)
+ .add( Restrictions.naturalId()
+ .set("name", "gavin")
+ .set("org", "hb")
+ ).setCacheable(true)
+ .uniqueResult();]]></programlisting>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/query_criteria.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/query_hql.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/query_hql.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/query_hql.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1162 @@
+858
+
+<chapter id="queryhql">
+ <title>HQL: A linguagem de Queries do Hibernate</title>
+
+ <para>
+ O Hibernate vem com uma poderosa linguagem que é (intencionalmente) muito
parecida
+ com o SQL. Mas não seja enganado pela sintaxe; a HQL é totalmente orientada à
objetos,
+ requer conhecimentos de herança, polimorfismo e associações.
+ </para>
+
+ <sect1 id="queryhql-casesensitivity">
+ <title>Case Sensitíve</title>
+
+ <para>
+ As Queries não são case-sensitive, exceto pelo nomes das classes e
propriedades Java.
+ <literal>sELEct</literal> e o mesmo que
+ <literal>SELECT</literal> mas
+ <literal>org.hibernate.eg.FOO</literal> não é
+ <literal>org.hibernate.eg.Foo</literal> e
+ <literal>foo.barSet</literal> não é
+ <literal>foo.BARSET</literal>.
+
+ </para>
+
+ <para>
+ Esse manual usa as palavras chave HQL em letras minúsculas. Alguns usuários
acham que
+ com letras maiúsculas as queries ficam mais legíveis, mas nós achamos essa
convenção feia
+ dentro do código Java.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-from">
+ <title>A clausula from</title>
+
+ <para>
+ A mais simples query possível do Hibernate é a assim:
+ </para>
+
+ <programlisting><![CDATA[from eg.Cat]]></programlisting>
+
+ <para>
+ Ela irá retornar todas as instancias da classe
<literal>eg.Cat</literal>.
+ Necessariamente não precisamos qualificar o nome da classe, pois é realizado
+ <literal>auto-import</literal> por padrão. Por isso na maior
parte do tempos
+ nós simplesmente escrevemos:
+ </para>
+
+ <programlisting><![CDATA[from Cat]]></programlisting>
+
+ <para>
+ Na maior parte do tempo, você precisará atribuir um
<emphasis>alias</emphasis>,
+ desde que você queira se referia ao <literal>Cat</literal> em
outras partes da
+ query.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat]]></programlisting>
+
+ <para>
+ Essa query atribui um alias a <literal>cat</literal> para as
instancias de
+ <literal>Cat</literal>, então nós podemos usar esse alias depois
na query.
+ A palavra chave as é opcional; poderíamos escrever assim:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat]]></programlisting>
+
+ <para>
+ Múltiplas classes pode ser envolvidas, resultando em um produto cartesiano ou
"cross" join.
+ </para>
+
+ <programlisting><![CDATA[from Formula,
Parameter]]></programlisting>
+ <programlisting><![CDATA[from Formula as form, Parameter as
param]]></programlisting>
+
+ <para>
+ É considerada uma boa prática os nomes dos aliases começarem com letra
minúscula,
+ aderente com os padrões Java para variáveis locais (ex:
<literal>domesticCat</literal>).
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-joins" revision="2">
+ <title>Associações e joins</title>
+
+ <para>
+ Nós também podemos querer atribuir aliases em uma entidade associada, ou
mesmo
+ em elementos de uma coleção de valores, usando um
<literal>join</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join cat.mate as mate
+ left outer join cat.kittens as kitten]]></programlisting>
+
+ <programlisting><![CDATA[from Cat as cat left join cat.mate.kittens as
kittens]]></programlisting>
+
+ <programlisting><![CDATA[from Formula form full join form.parameter
param]]></programlisting>
+
+ <para>
+ Os tipos de joins suportados foram inspirados no SQL ANSI:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>inner join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>left outer join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>right outer join</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>full join</literal> (geralmente não é útil)
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The <literal>inner join</literal>, <literal>left outer
join</literal> and
+ <literal>right outer join</literal> constructs may be
abbreviated.
+ As construções <literal>inner join</literal>, <literal>left
outer join</literal> e
+ <literal>right outer join</literal> podem ser abreviadas.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ join cat.mate as mate
+ left join cat.kittens as kitten]]></programlisting>
+
+ <para>
+ Você pode fornecer condições extras de join usando a palavra
+ chave do HQL <literal>with</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ left join cat.kittens as kitten
+ <literal>with</literal> kitten.bodyWeight >
10.0]]></programlisting>
+
+ <para>
+ Adicionalmente, um "fetch" join permite que associações ou coleções
de valores
+ sejam inicializadas junto com o objeto pai, usando apenas um select. Isso é
+ muito útil no caso das coleções. Isso efetivamente sobre escreve as
declarações
+ outer join e lazy do arquivo mapeamento para associações e coleções.
+ Veja a seção <xref linkend="performance-fetching"/> para
mais informações.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join <literal>fetch</literal>cat.mate
+ left join
<literal>fetch</literal>cat.kittens]]></programlisting>
+
+ <para>
+ Usualmente, um <literal>fetch</literal>join não precisa atribuir
um alias, pois o objeto associado não
+ deve ser usado na clausula <literal>where</literal> (ou em
qualquer outra clausula).
+ Também, os objetos associados não são retornados diretamente nos resultados
da query.
+ Ao invés disso, eles devem ser acessados usando o objeto pai. A única razão
que nós
+ podemos necessitar de um alias é quando fazemos um fech join recursivamente
em uma
+ coleção adicional:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+ inner join <literal>fetch</literal>cat.mate
+ left join <literal>fetch</literal>cat.kittens child
+ left join
<literal>fetch</literal>child.kittens]]></programlisting>
+
+ <para>
+ Observe que a construção <literal>fetch</literal> não deve ser
usada em queries invocadas usando
+ <literal>iterate()</literal> (embora possa ser usado com
<literal>scroll()</literal>). O
+ <literal>fetch</literal> também não deve ser usado junto com o
<literal>setMaxResults()</literal> ou
+ <literal>setFirstResult()</literal> pois essas operações são
baseadas nas linhas retornadas, que
+ normalmente contem duplicidade devido ao fetching das coleções, então o
número de linhas pode não
+ ser o que você espera.
+
+ O <literal>fetch</literal> não deve ser usado junto com uma
condição <literal>with</literal> em
+ uma condição <literal>with</literal> ad hoc. É possível que seja
criado um produto cartesiano pelo
+ join fetching em mais do que uma coleção em uma query, então tome cuidado
nesses casos. Um join
+ fetching em varias coleções pode trazer resultados inesperados para
mapeamentos do tipo bag, tome
+ cuidado na hora de formular queries como essas. Finalmente, observe o
seguinte, o
+ <literal>full join fetch</literal> e <literal>right join
fetch</literal> não são significativos.
+ </para>
+
+ <para>
+
+ Se está usando o nível de propriedade lazy
(<literal>com</literal> instrumentação de bytecode), é possível
+ forçar o Hibernate a <literal>buscar</literal> as propriedades
lazy imediatamente (na primeira query),
+ usando <literal>fetch all properties </literal>.
+ </para>
+
+ <programlisting><![CDATA[from Document
<literal>fetch</literal>all properties order by
name]]></programlisting>
+ <programlisting><![CDATA[from Document doc
<literal>fetch</literal>all properties where lower(doc.name) like
'%cats%']]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-joins-forms">
+ <title>Formas e sintaxe de joins</title>
+
+ <para>
+ O HQL suporta duas formas de associação para união:
<literal>implícita</literal> e <literal>explicita</literal>.
+ </para>
+
+ <para>
+ As queries apresentadas na seção anterior usam a forma
<literal>explicita</literal>, onde a
+ palavra chave "join" é explicitamente usada na clausula "from".
Essa é a forma recomendada.
+ </para>
+
+ <para>
+ A forma <literal>implícita</literal> não usa a palavra chave
"join". Entretanto, as associações
+ são diferenciadas usando pontuação ("." - dotnation). Uniões implícitas
podem aparecer em
+ qualquer das clausulas HQL. A união <literal>implícita</literal>
resulta em declarações
+ SQL que contem inner joins.
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where cat.mate.name like
'%s%']]></programlisting>
+ </sect1>
+
+ <sect1 id="queryhql-select">
+ <title>Clausula select</title>
+
+ <para>
+ A clausula <literal>select</literal> seleciona quais obetos e
propriedades retornam
+ no resultado da query. Considere:
+ </para>
+
+ <programlisting><![CDATA[select mate
+from Cat as cat
+ inner join cat.mate as mate]]></programlisting>
+
+ <para>
+ A query selecionará <literal>mate</literal>s (companheiros), de
outros <literal>Cat</literal>s.
+ Atualmente, podemos expressar a query de forma mais compacta como:
+ </para>
+
+ <programlisting><![CDATA[select cat.mate from Cat
cat]]></programlisting>
+
+ <para>
+ Queries podem retornar propriedades de qualquer tipo de valor, incluindo
propriedades de tipo de componente:
+
+ </para>
+
+ <programlisting><![CDATA[select cat.name from DomesticCat cat
+where cat.name like 'fri%']]></programlisting>
+
+ <programlisting><![CDATA[select cust.name.firstName from Customer as
cust]]></programlisting>
+
+ <para>
+ Queries podem retornar múltiplos objetos e/ou propriedades como um array do
+ tipo Object[],
+ </para>
+
+ <programlisting><![CDATA[select mother, offspr, mate.name
+from DomesticCat as mother
+ inner join mother.mate as mate
+ left outer join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ ou como um <literal>List</literal>,
+ </para>
+
+ <programlisting><![CDATA[select new list(mother, offspr, mate.name)
+from DomesticCat as mother
+ inner join mother.mate as mate
+ left outer join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ ou como um objeto Java typesafe,
+ </para>
+
+ <programlisting><![CDATA[select new Family(mother, mate, offspr)
+from DomesticCat as mother
+ join mother.mate as mate
+ left join mother.kittens as offspr]]></programlisting>
+
+ <para>
+ assumindo que a classe <literal>Family</literal> tenha um
construtor apropriado.
+ </para>
+
+ <para>
+ Pode-se designar referencias a expressões selecionadas,
<literal>as</literal>:
+ </para>
+
+ <programlisting><![CDATA[select max(bodyWeight) as max, min(bodyWeight)
as min, count(*) as n
+from Cat cat]]></programlisting>
+
+ <para>
+ Isto é bem mais útil quando usado junto <literal>com</literal>
<literal>select new map</literal>:
+ </para>
+
+ <programlisting><![CDATA[select new map( max(bodyWeight) as max,
min(bodyWeight) as min, count(*) as n )
+from Cat cat]]></programlisting>
+
+ <para>
+ Esta query retorna um <literal>Map</literal> de referencias para
valores selecionados.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-aggregation">
+ <title>Funções de agregação</title>
+
+ <para>
+ As queries HQL podem retornar o resultado de funções agregadas nas
propriedades.
+ </para>
+
+ <programlisting><![CDATA[select avg(cat.weight), sum(cat.weight),
max(cat.weight), count(cat)
+from Cat cat]]></programlisting>
+
+<!-- NO LONGER SUPPORTED
+ <para>
+ Collections may also appear inside aggregate functions in the
<literal>select</literal>
+ clause.
+ </para>
+
+ <programlisting><![CDATA[select cat, count( elements(cat.kittens) )
+from Cat cat group by cat]]></programlisting>
+-->
+
+ <para>
+ As funções agregadas suportadas são:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>avg(...), sum(...), min(...),
max(...)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>count(*)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>count(...), count(distinct ...),
count(all...)</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Pode-se usar operadores aritiméticos, concatenação e funções SQL
+ reconhecidas na clausula select:
+ </para>
+
+ <programlisting><![CDATA[select cat.weight + sum(kitten.weight)
+from Cat cat
+ join cat.kittens kitten
+group by cat.id, cat.weight]]></programlisting>
+
+ <programlisting><![CDATA[select firstName||' '||initial||'
'||upper(lastName) from Person]]></programlisting>
+
+ <para>
+ As palavras <literal>distinct</literal> e
<literal>all</literal> podem ser usadas e têm
+ a mesma semântica como no SQL.
+ </para>
+
+ <programlisting><![CDATA[select distinct cat.name from Cat cat
+
+select count(distinct cat.name), count(cat) from Cat cat]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-polymorphism">
+ <title>Queries polimórficas</title>
+
+ <para>
+ A query:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat]]></programlisting>
+
+ <para>
+ retorna instancias não só de <literal>Cat</literal>, mas também
de subclasses como
+ <literal>DomesticCat</literal>. As queries do Hibernate podem
nomear qualquer classe Java
+ ou interface na clausula <literal>from</literal>. A query
retornará instancias de toda classe
+ persistente que extenda a determinada classe ou implemente a determinada
interface. A query
+ , a seguir, pode retornar todo objeto persistente:
+ </para>
+
+ <programlisting><![CDATA[from java.lang.Object
o]]></programlisting>
+
+ <para>
+ A interface <literal>Named</literal> pode ser implementada por
várias classes persistentes:
+ </para>
+
+ <programlisting><![CDATA[from Named n, Named m where n.name =
m.name]]></programlisting>
+
+ <para>
+ Note que as duas últimas queries requerem mais de um SQL SELECT . Isto
significa que a clausula
+ <literal>order by</literal> não ordena corretamente todo o
resultado. (Isso também significa que
+ você não pode chamar essas queries usando
<literal>Query.scroll()</literal>.)
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-where">
+ <title>A clausula where</title>
+
+ <para>
+ A clausula <literal>where</literal> permite estreitar a lista de
instancias retornada.
+ Se não houver referencia alguma, pode-se referir a propriedades pelo nome:
+ </para>
+
+ <programlisting><![CDATA[from Cat where
name='Fritz']]></programlisting>
+
+ <para>
+ Se houver uma referência, use o nome da propriedade qualificada:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where
cat.name='Fritz']]></programlisting>
+
+ <para>
+ retorna instancias de <literal>Cat</literal> com nome ‘Fritz’.
+ </para>
+
+ <programlisting><![CDATA[select foo
+from Foo foo, Bar bar
+where foo.startDate = bar.date]]></programlisting>
+
+ <para>
+ retornará todas as instancias de <literal>Foo</literal>, para
cada
+ um que tiver uma instancia de <literal>bar</literal> com a
propriedade
+ <literal>date</literal> igual a propriedade
+ <literal>startDate</literal> de
+ <literal>Foo</literal>. Expressões de filtro compostas fazem da
+ clausula <literal>where</literal>, extremamente poderosa.
Consideremos:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.mate.name is not
null]]></programlisting>
+
+ <para>
+ Esta query traduzida para uma query SQL <literal>com</literal>
uma tabela (inner) join. Se fosse
+ escrever algo como:
+ </para>
+
+ <programlisting><![CDATA[from Foo foo
+where foo.bar.baz.customer.address.city is not null]]></programlisting>
+
+ <para>
+ Poderia-se terminar <literal>com</literal> uma query que
necessitasse de join de quatro tabelas,
+ no SQL.
+ </para>
+
+ <para>
+ O operador <literal>=</literal> pode ser uasdo para comparar não
apenas propriedades,
+ mas também instancias:
+ </para>
+
+ <programlisting><![CDATA[from Cat cat, Cat rival where cat.mate =
rival.mate]]></programlisting>
+
+ <programlisting><![CDATA[select cat, mate
+from Cat cat, Cat mate
+where cat.mate = mate]]></programlisting>
+
+ <para>
+ A propriedade especial (lowercase) <literal>id</literal> pode
ser usada para referenciar
+ o identificador único de um objeto. (Pode-se usar também o nome de sua
propriedade)
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat where cat.id = 123
+
+from Cat as cat where cat.mate.id = 69]]></programlisting>
+
+ <para>
+ A Segunda query é eficiente. Nenhuma união de tabelas é necessária!
+ </para>
+
+ <para>
+ As propriedades de identificadores compostas também podem ser usadas. Suponha
que
+ <literal>Person</literal> tenha um identificador composto que
consiste de
+ <literal>country</literal> e
<literal>medicareNumber</literal>.
+ </para>
+
+ <programlisting><![CDATA[from bank.Person person
+where person.id.country = 'AU'
+ and person.id.medicareNumber = 123456]]></programlisting>
+
+ <programlisting><![CDATA[from bank.Account account
+where account.owner.id.country = 'AU'
+ and account.owner.id.medicareNumber = 123456]]></programlisting>
+
+ <para>
+ Mais uma vez, a Segunda query não precisa de nenhum join de tabela.
+ </para>
+
+ <para>
+ Assim mesmo, a propriedade especial <literal>class</literal>
acessa o valor discriminador da
+ instancia, no caso de persistência polimórfica. O nome de uma classe Java
inclusa em uma
+ clausula "where", será traduzida para seu valor descriminante.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.class =
DomesticCat]]></programlisting>
+
+ <para>
+ Pode-se também especificar as propriedades dos components ou tipos de usuário
composto
+ (e de componentes de componentes). Nunca tente usar uma expressão de filtro
que termine na propriedade
+ de um tipo de componente (ao contrário de uma propriedade de um componente).
Por exemplo,
+ se store.owner é uma entidade <literal>com</literal> um
componente <literal>address</literal>.
+ </para>
+
+ <programlisting><![CDATA[store.owner.address.city // okay
+store.owner.address // error!]]></programlisting>
+
+ <para>
+ Um tipo "any" tem as propriedades <literal>id</literal>
e <literal>class</literal> especiais,
+ nôs permitindo expressar um join da seguinte forma (onde
<literal>AuditLog.item</literal> é
+ uma propriedade mapeada <literal>com</literal>
<literal><any></literal>)
+ </para>
+
+ <programlisting><![CDATA[from AuditLog log, Payment payment
+where log.item.class = 'Payment' and log.item.id =
payment.id]]></programlisting>
+
+ <para>
+ Veja que <literal>log.item.class</literal> e
<literal>payment.class</literal> podem
+ referir-se a valores de colunas de banco de dados completamente diferentes,
na query acima.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-expressions">
+ <title>Expressões</title>
+
+ <para>
+ As expressões permitidas na cláusula <literal>where</literal>
inclui a maioria
+ das coisas que você poderia escrever no SQL:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ operadores matemáticos <literal>+, -, *, /</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ operadores de comparação binários <literal>=, >=,
<=, <>, !=, like</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ operadores lógicos <literal>and, or, not</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ parenteses <literal>( )</literal>, indicating grouping
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>in</literal>,
+ <literal>not in</literal>,
+ <literal>between</literal>,
+ <literal>is null</literal>,
+ <literal>is not null</literal>,
+ <literal>is empty</literal>,
+ <literal>is not empty</literal>,
+ <literal>member of</literal> and
+ <literal>not member of</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ case "simples" , <literal>case ... when ... then ...
else ... end</literal>, and
+ "searched" case, <literal>case when ... then ... else
... end</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ concatenação de string <literal>...||...</literal> ou
<literal>concat(...,...)</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>current_date()</literal>,
<literal>current_time()</literal>,
+ <literal>current_timestamp()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>second(...)</literal>,
<literal>minute(...)</literal>,
+ <literal>hour(...)</literal>, <literal>day(...)</literal>,
+ <literal>month(...)</literal>,
<literal>year(...)</literal>,
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ qualquer funcao ou operador definida pela EJB-QL 3.0:
<literal>substring(), trim(),
+ lower(), upper(), length(), locate(), abs(), sqrt(), bit_length(),
mod()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>coalesce()</literal> and
<literal>nullif()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>str()</literal> para converter valores numericos
ou temporais para string
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>cast(... as ...)</literal>, onde o segundo
argumento é o nome do tipo
+ hibernate, e<literal>extract(... from ...)</literal> se
ANSI
+ <literal>cast()</literal> e
<literal>extract()</literal> é suportado pele
+ banco de dados usado
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ A função HQL <literal>index()</literal> , que se aplicam
a referencias de
+ coleçôes associadas e indexadas
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ As funções hql que retornam expressões de coleções de valores:
+ <literal>size(), minelement(), maxelement(), minindex(),
maxindex()</literal>,
+ <literal>junto</literal> com o elemento especial,
<literal>elements()</literal>,
+ e funções de <literal>índice</literal> que podem ser
quantificadas usando
+ <literal>some, all, exists, any, in</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Qualquer funçâo escalar pelo bando de dados como
<literal>sign()</literal>,
+ <literal>trunc()</literal>,
<literal>rtrim()</literal>, <literal>sin()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Parametros posicionais ao estilo JDBC
<literal>?</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Parametros nomeados <literal>:name</literal>,
<literal>:start_date</literal>, <literal>:x1</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Literais SQL <literal>'foo'</literal>,
<literal>69</literal>, <literal>6.66E+2</literal>,
+ <literal>'1970-01-01 10:00:01.0'</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Constantes Java <literal>public static final</literal>
<literal>ex: Color.TABBY</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ <literal>in</literal> e <literal>between</literal>
podem ser usadas da seguinte maneira:
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name between
'A' and 'B']]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
+
+ <para>
+ e as formas negativas podem ser escritas
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name not between
'A' and 'B']]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat cat where cat.name not in (
'Foo', 'Bar', 'Baz' )]]></programlisting>
+
+ <para>
+ Likewise, <literal>is null</literal> and <literal>is not
null</literal> may be used to test
+ for null values.
+ Assim mesmo, , <literal>is null</literal> e <literal>is not
null</literal> podem ser usados
+ para testar valores nulos.
+ </para>
+
+ <para>
+ Booleanos podem ser facilmente usados em expressões, declarando as
substituições da HQL query,
+ na configuração do Hibernate
+ </para>
+
+ <programlisting><![CDATA[<property
name="hibernate.query.substitutions">true 1, false
0</property>]]></programlisting>
+
+ <para>
+ Isso irá substituir as palavras chave <literal>true</literal> e
<literal>false</literal>
+ <literal>pelos</literal> literais
<literal>1</literal> e <literal>0</literal> na tradução do HQL
para SQL.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.alive =
true]]></programlisting>
+
+ <para>
+ Pode-se testar o tamanho de uma coleção <literal>com</literal> a
propriedade especial <literal>size</literal>,
+ ou a função especial <literal>size()</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Cat cat where cat.kittens.size >
0]]></programlisting>
+
+ <programlisting><![CDATA[from Cat cat where size(cat.kittens) >
0]]></programlisting>
+
+ <para>
+ Para coleções indexadas, você pode se referir aos índices máximo e mínimo,
usando
+ as funções <literal>minindex</literal> e
<literal>maxindex</literal>. Similarmente,
+ pode-se referir aos elementos máximo e mínimo de uma coleção de tipos básicos
usando
+ as funções <literal>minelement</literal> e
<literal>maxelement</literal>.
+ </para>
+
+ <programlisting><![CDATA[from Calendar cal where
maxelement(cal.holidays) > current_date]]></programlisting>
+
+ <programlisting><![CDATA[from Order order where maxindex(order.items)
> 100]]></programlisting>
+
+ <programlisting><![CDATA[from Order order where minelement(order.items)
> 10000]]></programlisting>
+
+ <para>
+ As funções SQL <literal>any, some, all, exists, in</literal> são
suportadas quando passado o
+ elemento ou o conjunto de índices de uma coleção
(<literal>elements</literal> e
+ <literal>indices</literal> de funções), ou o resultado de uma
subquery (veja abaixo).
+ </para>
+
+ <programlisting><![CDATA[select mother from Cat as mother, Cat as kit
+where kit in elements(foo.kittens)]]></programlisting>
+
+ <programlisting><![CDATA[select p from NameList list, Person p
+where p.name = some elements(list.names)]]></programlisting>
+
+ <programlisting><![CDATA[from Cat cat where exists
elements(cat.kittens)]]></programlisting>
+
+ <programlisting><![CDATA[from Player p where 3 > all
elements(p.scores)]]></programlisting>
+
+ <programlisting><![CDATA[from Show show where 'fizard' in
indices(show.acts)]]></programlisting>
+
+ <para>
+ Note que essas construções - <literal>size</literal>,
<literal>elements</literal>,
+ <literal>indices</literal>,
<literal>minindex</literal>, <literal>maxindex</literal>,
+ <literal>minelement</literal>,
<literal>maxelement</literal>–
+ só podem ser usados na clausula where do Hibernate3.
+ </para>
+
+ <para>
+ Elementos de coleções com índice (arrays, lists, maps), podem ser
referenciadas
+ pelo índice (apenas na clausula where):
+ </para>
+
+ <programlisting><![CDATA[from Order order where order.items[0].id =
1234]]></programlisting>
+
+ <programlisting><![CDATA[select person from Person person, Calendar
calendar
+where calendar.holidays['national day'] = person.birthDay
+ and person.nationality.calendar = calendar]]></programlisting>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ order.deliveredItemIndices[0] ] = item and order.id =
11]]></programlisting>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ maxindex(order.items) ] = item and order.id =
11]]></programlisting>
+
+ <para>
+ A expressão entre colchetes <literal>[]</literal>, pode ser até
uma expressão aritimética.
+ </para>
+
+ <programlisting><![CDATA[select item from Item item, Order order
+where order.items[ size(order.items) - 1 ] = item]]></programlisting>
+
+ <para>
+ O HQL também provê a função interna <literal>index()</literal>,
para elementos de
+ associação um-pra-muitos ou coleção de valores.
+ </para>
+
+ <programlisting><![CDATA[select item, index(item) from Order order
+ join order.items item
+where index(item) < 5]]></programlisting>
+
+ <para>
+ Funções escalares SQL, suportadas pelo banco de dados subjacente.
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat where upper(cat.name) like
'FRI%']]></programlisting>
+
+ <para>
+ Se ainda ainda não está totalmente convencido, pense o quão maior e menos
legível poderia
+ ser a query a seguir, em SQL:
+ </para>
+
+ <programlisting><![CDATA[select cust
+from Product prod,
+ Store store
+ inner join store.customers cust
+where prod.name = 'widget'
+ and store.location.name in ( 'Melbourne', 'Sydney' )
+ and prod = all elements(cust.currentOrder.lineItems)]]></programlisting>
+
+ <para>
+ <emphasis>Hint:</emphasis> something like
+ </para>
+
+ <programlisting><![CDATA[SELECT cust.name, cust.address, cust.phone,
cust.id, cust.current_order
+FROM customers cust,
+ stores store,
+ locations loc,
+ store_customers sc,
+ product prod
+WHERE prod.name = 'widget'
+ AND store.loc_id = loc.id
+ AND loc.name IN ( 'Melbourne', 'Sydney' )
+ AND sc.store_id = store.id
+ AND sc.cust_id = cust.id
+ AND prod.id = ALL(
+ SELECT item.prod_id
+ FROM line_items item, orders o
+ WHERE item.order_id = o.id
+ AND cust.current_order = o.id
+ )]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-ordering">
+ <title>A clausula order by</title>
+
+ <para>
+ A lista retornada pela query pode ser ordenada por qualquer propriedade da
classe ou componente retornado:
+ </para>
+
+ <programlisting><![CDATA[from DomesticCat cat
+order by cat.name asc, cat.weight desc, cat.birthdate]]></programlisting>
+
+ <para>
+ As opções <literal>asc</literal> ou
<literal>desc</literal> indicam ordem crescente ou decrescente,
+ respectivamente.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-grouping">
+ <title>A clausula group by</title>
+
+ <para>
+ Uma query que retorne valores agregados, podem ser agrupados por qualquer
propriedade de uma classe
+ ou componente retornado:
+ </para>
+
+ <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
+from Cat cat
+group by cat.color]]></programlisting>
+
+ <programlisting><![CDATA[select foo.id, avg(name), max(name)
+from Foo foo join foo.names name
+group by foo.id]]></programlisting>
+
+ <para>
+ Uma clausula <literal>having</literal> também é permitida.
+ </para>
+
+ <programlisting><![CDATA[select cat.color, sum(cat.weight), count(cat)
+from Cat cat
+group by cat.color
+having cat.color in (eg.Color.TABBY, eg.Color.BLACK)]]></programlisting>
+
+ <para>
+ Funções SQL e funções agregadas são permitidas nas clausulas
+ <literal>having</literal> e <literal>order
by</literal>, se suportadas pelo banco
+ de dados subjacente (ex: não no MySQL).
+ </para>
+
+ <programlisting><![CDATA[select cat
+from Cat cat
+ join cat.kittens kitten
+group by cat
+having avg(kitten.weight) > 100
+order by count(kitten) asc, sum(kitten.weight) desc]]></programlisting>
+
+ <para>
+ Note que, nem a clausula <literal>group by</literal> ou
+ <literal>order by</literal>, podem conter expressões
aritiméticas.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-subqueries" revision="2">
+ <title>Subqueries</title>
+
+ <para>
+ Para bancos de dados que suportem subselects, o Hibernate suporta subqueries
dentro de queries.
+ Uma subquery precisa estar entre parênteses (normalmente uma chamada de
função agregada SQL).
+ Mesmo subqueries co-relacionadas (subqueries que fazem referência à alias de
outras queries),
+ são aceitas.
+ </para>
+
+ <programlisting><![CDATA[from Cat as fatcat
+where fatcat.weight > (
+ select avg(cat.weight) from DomesticCat cat
+)]]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat as cat
+where cat.name = some (
+ select name.nickName from Name as name
+)]]></programlisting>
+
+ <programlisting><![CDATA[from Cat as cat
+where not exists (
+ from Cat as mate where mate.mate = cat
+)]]></programlisting>
+
+ <programlisting><![CDATA[from DomesticCat as cat
+where cat.name not in (
+ select name.nickName from Name as name
+)]]></programlisting>
+
+ <programlisting><![CDATA[select cat.id, (select max(kit.weight) from
cat.kitten kit)
+from Cat as cat]]></programlisting>
+
+ <para>
+ Note que HQL subqueries podem aparecer apenas dentro de clausulas select ou
where.
+ </para>
+
+ <para>
+ Para subqueries <literal>com</literal> mais de uma expressão na
lista do select, pode-se usar um construtor
+ de tuplas:
+ </para>
+
+ <programlisting><![CDATA[from Cat as cat
+where not ( cat.name, cat.color ) in (
+ select cat.name, cat.color from DomesticCat cat
+)]]></programlisting>
+
+ <para>
+ Veja que em alguns bancos de dados (mas não o Oracle ou HSQL), pode-se usar
construtores
+ de tuplas em outros contextos. Por exemplo quando buscando componentes ou
tipos de usuário composto.
+ </para>
+
+ <programlisting><![CDATA[from Person where name = ('Gavin',
'A', 'King')]]></programlisting>
+
+ <para>
+ Qual é equivalente ao mais verbalizado:
+ </para>
+
+ <programlisting><![CDATA[from Person where name.first = 'Gavin'
and name.initial = 'A' and name.last =
'King')]]></programlisting>
+
+ <para>
+ Há duas razões boas que você pode não querer fazer este tipo de coisa:
primeira, não
+ é completamente portável entre plataformas de banco de dados; segunda, a
query agora é
+ dependente da ordem de propriedades no documento de mapeamento.
+ </para>
+
+ </sect1>
+
+ <sect1 id="queryhql-examples">
+ <title>Exemplos de HQL</title>
+
+ <para>
+ As queries do Hibernate, podem ser muito poderosas e complexas. De fato, o
poder da linguagem de
+ querie é um dos pontos principais na distribuição do Hibernate. Aqui temos
algumas queries de exemplo,
+ muito similares a queries que usei em um projeto recente. Note que a maioria
das queries que você
+ irá escrever, são mais simples que estas.
+ </para>
+
+ <para>
+ A query a seguir retorna o id de order, numero de itens e o valor total do
order para todos os
+ orders não pagos para um freguês particular e valor total mínimo dado,
ordenando os resultados por
+ valor total. Ao determinar os preços, é usado o catalogo corrente. A query
SQL resultante,
+ usando tabelas <literal>ORDER</literal>,
<literal>ORDER_LINE</literal>, <literal>PRODUCT</literal>,
+ <literal>CATALOG</literal> e
<literal>PRICE</literal>, tem quatro inner joins e um
+ (não correlacionado) subselect.
+ </para>
+
+ <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
+from Order as order
+ join order.lineItems as item
+ join item.product as product,
+ Catalog as catalog
+ join catalog.prices as price
+where order.paid = false
+ and order.customer = :customer
+ and price.product = product
+ and catalog.effectiveDate < sysdate
+ and catalog.effectiveDate >= all (
+ select cat.effectiveDate
+ from Catalog as cat
+ where cat.effectiveDate < sysdate
+ )
+group by order
+having sum(price.amount) > :minAmount
+order by sum(price.amount) desc]]></programlisting>
+
+ <para>
+ Que monstro! Atualmente, na vida real, eu não sou muito afeiçoado a
subqueries, então
+ minha query seria mais parecida com isto:
+ </para>
+
+ <programlisting><![CDATA[select order.id, sum(price.amount),
count(item)
+from Order as order
+ join order.lineItems as item
+ join item.product as product,
+ Catalog as catalog
+ join catalog.prices as price
+where order.paid = false
+ and order.customer = :customer
+ and price.product = product
+ and catalog = :currentCatalog
+group by order
+having sum(price.amount) > :minAmount
+order by sum(price.amount) desc]]></programlisting>
+
+ <para>
+ A próxima query conta o número de pagamentos em cada status, tirando todos os
pagamentos com
+ status <literal>AWAITING_APPROVAL</literal>, onde a mais recente
mudança de status foi feita
+ pelo usuário corrente. Traduz-se para uma query SQL
<literal>com</literal> dois inner joins e
+ um subselect correlacionado, nas tabelas
<literal>PAYMENT</literal>,
+ <literal>PAYMENT_STATUS</literal> e
<literal>PAYMENT_STATUS_CHANGE</literal> .
+ </para>
+
+ <programlisting><![CDATA[select count(payment), status.name
+from Payment as payment
+ join payment.currentStatus as status
+ join payment.statusChanges as statusChange
+where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
+ or (
+ statusChange.timeStamp = (
+ select max(change.timeStamp)
+ from PaymentStatusChange change
+ where change.payment = payment
+ )
+ and statusChange.user <> :currentUser
+ )
+group by status.name, status.sortOrder
+order by status.sortOrder]]></programlisting>
+
+ <para>
+ Se eu tivesse mapeado a Collection
<literal>statusChanges</literal> como um List, ao invés de um
+ Set, a query teria sido muito mais simples de escrever.
+ </para>
+
+ <programlisting><![CDATA[select count(payment), status.name
+from Payment as payment
+ join payment.currentStatus as status
+where payment.status.name <> PaymentStatus.AWAITING_APPROVAL
+ or payment.statusChanges[ maxIndex(payment.statusChanges) ].user <>
:currentUser
+group by status.name, status.sortOrder
+order by status.sortOrder]]></programlisting>
+
+ <para>
+ A próxima query usa a função <literal>isNull()</literal> do MS
SQL Server, para retornar
+ todas as contas e pagamentos não pagos para a organização, para cada usuário
corrente
+ pertencente. Traduz-se para uma query SQL <literal>com</literal>
três inner joins,
+ um outer join e um subselect nas tabelas
<literal>ACCOUNT</literal>, <literal>PAYMENT</literal>,
+
<literal>PAYMENT_STATUS</literal>,<literal>ACCOUNT_TYPE</literal>,
+ <literal>ORGANIZATION</literal> e
<literal>ORG_USER</literal> .
+ </para>
+
+ <programlisting><![CDATA[select account, payment
+from Account as account
+ left outer join account.payments as payment
+where :currentUser in elements(account.holder.users)
+ and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
+order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
+
+ <para>
+ Para alguns bancos de dados, precisaremos eleminar o subselect
(correlacionado).
+ </para>
+
+ <programlisting><![CDATA[select account, payment
+from Account as account
+ join account.holder.users as user
+ left outer join account.payments as payment
+where :currentUser = user
+ and PaymentStatus.UNPAID = isNull(payment.currentStatus.name, PaymentStatus.UNPAID)
+order by account.type.sortOrder, account.accountNumber,
payment.dueDate]]></programlisting>
+
+ </sect1>
+
+ <sect1 id="queryhql-bulk" revision="2">
+ <title>update e delete em lote</title>
+
+ <para>
+ Agora o HQL suporta declarações, <literal>update</literal>,
+ <literal>delete</literal> e <literal>insert ... select
...</literal>
+ Veja <xref linkend="batch-direct"/>, para mais detalhes.
+ </para>
+ </sect1>
+
+ <sect1 id="queryhql-tipstricks">
+ <title>Dicas e Truques</title>
+
+ <para>
+ Pode-se contar o número de resultados da query, sem realmente retorna-los.
+ </para>
+
+ <programlisting><![CDATA[( (Integer) session.iterate("select
count(*) from ....").next() ).intValue()]]></programlisting>
+
+ <para>
+ Para ordenar um resultado pelo tamanho de uma Collection, use a query a
seguir.
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User as usr
+ left join usr.messages as msg
+group by usr.id, usr.name
+order by count(msg)]]></programlisting>
+
+ <para>
+ Se seu banco de dados suporta subselects, pode-se colocar uma condição sobre
+ tamanho de seleção na cláusula where da sua query:
+ </para>
+
+ <programlisting><![CDATA[from User usr where size(usr.messages) >=
1]]></programlisting>
+
+ <para>
+ Se seu banco de dados não suporta subselects, use a query a seguir:
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User usr.name
+ join usr.messages msg
+group by usr.id, usr.name
+having count(msg) >= 1]]></programlisting>
+
+ <para>
+ Com essa solução não se pode retornar um <literal>User</literal>
<literal>com</literal> sem
+ nenhuma menssagem, por causa do "inner join", a forma a seguir
também é útil.
+ </para>
+
+ <programlisting><![CDATA[select usr.id, usr.name
+from User as usr
+ left join usr.messages as msg
+group by usr.id, usr.name
+having count(msg) = 0]]></programlisting>
+
+ <para>
+ As propriedades de um JavaBean podem ser limitadas à parâmetros nomeados da
query:
+ </para>
+
+ <programlisting><![CDATA[Query q = s.createQuery("from foo Foo as
foo where foo.name=:name and foo.size=:size");
+q.setProperties(fooBean); // fooBean has getName() and getSize()
+List foos = q.list();]]></programlisting>
+
+ <para>
+ As Collections são paginaveis, usando a interface
<literal>Query</literal> <literal>com</literal> um filtro:
+ </para>
+
+ <programlisting><![CDATA[Query q = s.createFilter( collection,
"" ); // the trivial filter
+q.setMaxResults(PAGE_SIZE);
+q.setFirstResult(PAGE_SIZE * pageNumber);
+List page = q.list();]]></programlisting>
+
+ <para>
+ Os elementos da Collection podem ser ordenados ou agrupados
+ usando um filtro de query:
+ </para>
+
+ <programlisting><![CDATA[Collection orderedCollection = s.filter(
collection, "order by this.amount" );
+Collection counts = s.filter( collection, "select this.type, count(this) group by
this.type" );]]></programlisting>
+
+ <para>
+ Pode-se achar o tamanho de uma Collection sem inicializa-la:
+ </para>
+
+ <programlisting><![CDATA[( (Integer) session.iterate("select
count(*) from ....").next() ).intValue();]]></programlisting>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/query_hql.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/query_sql.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/query_sql.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/query_sql.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,783 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<chapter id="querysql" revision="2">
+ <title>Native SQL</title>
+
+ <para>You may also express queries in the native SQL dialect of your
+ database. This is useful if you want to utilize database specific features
+ such as query hints or the <literal>CONNECT</literal> keyword in Oracle.
It
+ also provides a clean migration path from a direct SQL/JDBC based
+ application to Hibernate.</para>
+
+ <para>Hibernate3 allows you to specify handwritten SQL (including stored
+ procedures) for all create, update, delete, and load operations.</para>
+
+ <sect1 id="querysql-creating" revision="4">
+ <title>Using a <literal>SQLQuery</literal></title>
+
+ <para>Execution of native SQL queries is controlled via the
+ <literal>SQLQuery</literal> interface, which is obtained by calling
+ <literal>Session.createSQLQuery()</literal>. The following describes how
+ to use this API for querying.</para>
+
+ <sect2>
+ <title>Scalar queries</title>
+
+ <para>The most basic SQL query is to get a list of scalars
+ (values).</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM
CATS").list();
+sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM CATS").list();
+]]></programlisting>
+
+ <para>These will both return a List of Object arrays (Object[]) with
+ scalar values for each column in the CATS table. Hibernate will use
+ ResultSetMetadata to deduce the actual order and types of the returned
+ scalar values.</para>
+
+ <para>To avoid the overhead of using
+ <literal>ResultSetMetadata</literal> or simply to be more explicit in
+ what is returned one can use
<literal>addScalar()</literal>.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM
CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME", Hibernate.STRING)
+ .addScalar("BIRTHDATE", Hibernate.DATE)
+]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>the columns and types to return</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This will still return Object arrays, but now it will not use
+ <literal>ResultSetMetdata</literal> but will instead explicitly get
the
+ ID, NAME and BIRTHDATE column as respectively a Long, String and a Short
+ from the underlying resultset. This also means that only these three
+ columns will be returned, even though the query is using
+ <literal>*</literal> and could return more than the three listed
+ columns.</para>
+
+ <para>It is possible to leave out the type information for all or some
+ of the scalars.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM
CATS")
+ .addScalar("ID", Hibernate.LONG)
+ .addScalar("NAME")
+ .addScalar("BIRTHDATE")
+]]></programlisting>
+
+ <para>This is essentially the same query as before, but now
+ <literal>ResultSetMetaData</literal> is used to decide the type of
NAME
+ and BIRTHDATE where as the type of ID is explicitly specified.</para>
+
+ <para>How the java.sql.Types returned from ResultSetMetaData is mapped
+ to Hibernate types is controlled by the Dialect. If a specific type is
+ not mapped or does not result in the expected type it is possible to
+ customize it via calls to <literal>registerHibernateType</literal> in
+ the Dialect.</para>
+ </sect2>
+
+ <sect2>
+ <title>Entity queries</title>
+
+ <para>The above queries were all about returning scalar values,
+ basically returning the "raw" values from the resultset. The following
+ shows how to get entity objects from a native sql query via
+ <literal>addEntity()</literal>.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT * FROM
CATS").addEntity(Cat.class);
+sess.createSQLQuery("SELECT ID, NAME, BIRTHDATE FROM
CATS").addEntity(Cat.class);
+]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>the entity returned by the query</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Assuming that Cat is mapped as a class with the columns ID, NAME
+ and BIRTHDATE the above queries will both return a List where each
+ element is a Cat entity.</para>
+
+ <para>If the entity is mapped with a
<literal>many-to-one</literal> to
+ another entity it is required to also return this when performing the
+ native query, otherwise a database specific "column not found" error
+ will occur. The additional columns will automatically be returned when
+ using the * notation, but we prefer to be explicit as in the following
+ example for a <literal>many-to-one</literal> to a
+ <literal>Dog</literal>:</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME,
BIRTHDATE, DOG_ID FROM CATS").addEntity(Cat.class);
+]]></programlisting>
+
+ <para>This will allow cat.getDog() to function properly.</para>
+ </sect2>
+
+ <sect2>
+ <title>Handling associations and collections</title>
+
+ <para>It is possible to eagerly join in the
<literal>Dog</literal> to
+ avoid the possible extra roundtrip for initializing the proxy. This is
+ done via the <literal>addJoin()</literal> method, which allows you to
+ join in an association or collection.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT c.ID, NAME,
BIRTHDATE, DOG_ID, D_ID, D_NAME FROM CATS c, DOGS d WHERE c.DOG_ID = d.D_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dog");
+]]></programlisting>
+
+ <para>In this example the returned <literal>Cat</literal>'s
will have
+ their <literal>dog</literal> property fully initialized without any
+ extra roundtrip to the database. Notice that we added a alias name
+ ("cat") to be able to specify the target property path of the join. It
+ is possible to do the same eager joining for collections, e.g. if the
+ <literal>Cat</literal> had a one-to-many to
<literal>Dog</literal>
+ instead.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT ID, NAME,
BIRTHDATE, D_ID, D_NAME, CAT_ID FROM CATS c, DOGS d WHERE c.ID = d.CAT_ID")
+ .addEntity("cat", Cat.class)
+ .addJoin("cat.dogs");
+]]></programlisting>
+
+ <p>At this stage we are reaching the limits of what is possible with
+ native queries without starting to enhance the sql queries to make them
+ usable in Hibernate; the problems starts to arise when returning
+ multiple entities of the same type or when the default alias/column
+ names are not enough.</p>
+ </sect2>
+
+ <sect2>
+ <title>Returning multiple entities</title>
+
+ <para>Until now the result set column names are assumed to be the same
+ as the column names specified in the mapping document. This can be
+ problematic for SQL queries which join multiple tables, since the same
+ column names may appear in more than one table.</para>
+
+ <para>Column alias injection is needed in the following query (which
+ most likely will fail):</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT c.*, m.* FROM
CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+]]></programlisting>
+
+ <para>The intention for this query is to return two Cat instances per
+ row, a cat and its mother. This will fail since there is a conflict of
+ names since they are mapped to the same column names and on some
+ databases the returned column aliases will most likely be on the form
+ "c.ID", "c.NAME", etc. which are not equal to the columns
specificed in
+ the mappings ("ID" and "NAME").</para>
+
+ <para>The following form is not vulnerable to column name
+ duplication:</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT {cat.*},
{mother.*} FROM CATS c, CATS m WHERE c.MOTHER_ID = c.ID")
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class)
+]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string, with placeholders for Hibernate to
+ inject column aliases</para>
+ </listitem>
+
+ <listitem>
+ <para>the entities returned by the query</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The {cat.*} and {mother.*} notation used above is a shorthand for
+ "all properties". Alternatively, you may list the columns explicity, but
+ even in this case we let Hibernate inject the SQL column aliases for
+ each property. The placeholder for a column alias is just the property
+ name qualified by the table alias. In the following example, we retrieve
+ Cats and their mothers from a different table (cat_log) to the one
+ declared in the mapping metadata. Notice that we may even use the
+ property aliases in the where clause if we like.</para>
+
+ <programlisting><![CDATA[String sql = "SELECT ID as {c.id}, NAME as
{c.name}, " +
+ "BIRTHDATE as {c.birthDate}, MOTHER_ID as {c.mother}, {mother.*} " +
+ "FROM CAT_LOG c, CAT_LOG m WHERE {c.mother} = c.ID";
+
+List loggedCats = sess.createSQLQuery(sql)
+ .addEntity("cat", Cat.class)
+ .addEntity("mother", Cat.class).list()
+]]></programlisting>
+
+ <sect3 id="querysql-aliasreferences" revision="2">
+ <title>Alias and property references</title>
+
+ <para>For most cases the above alias injection is needed, but for
+ queries relating to more complex mappings like composite properties,
+ inheritance discriminators, collections etc. there are some specific
+ aliases to use to allow Hibernate to inject the proper aliases.</para>
+
+ <para>The following table shows the different possibilities of using
+ the alias injection. Note: the alias names in the result are examples,
+ each alias will have a unique and probably different name when
+ used.</para>
+
+ <table frame="topbot" id="aliasinjection-summary">
+ <title>Alias injection names</title>
+
+ <tgroup cols="3">
+ <colspec colwidth="1*" />
+
+ <colspec colwidth="1*" />
+
+ <colspec colwidth="2.5*" />
+
+ <thead>
+ <row>
+ <entry>Description</entry>
+
+ <entry>Syntax</entry>
+
+ <entry>Example</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>A simple property</entry>
+
+
<entry><literal>{[aliasname].[propertyname]</literal></entry>
+
+ <entry><literal>A_NAME as
{item.name}</literal></entry>
+ </row>
+
+ <row>
+ <entry>A composite property</entry>
+
+
<entry><literal>{[aliasname].[componentname].[propertyname]}</literal></entry>
+
+ <entry><literal>CURRENCY as {item.amount.currency}, VALUE as
+ {item.amount.value}</literal></entry>
+ </row>
+
+ <row>
+ <entry>Discriminator of an entity</entry>
+
+
<entry><literal>{[aliasname].class}</literal></entry>
+
+ <entry><literal>DISC as
{item.class}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of an entity</entry>
+
+
<entry><literal>{[aliasname].*}</literal></entry>
+
+ <entry><literal>{item.*}</literal></entry>
+ </row>
+
+ <row>
+ <entry>A collection key</entry>
+
+
<entry><literal>{[aliasname].key}</literal></entry>
+
+ <entry><literal>ORGID as
{coll.key}</literal></entry>
+ </row>
+
+ <row>
+ <entry>The id of an collection</entry>
+
+
<entry><literal>{[aliasname].id}</literal></entry>
+
+ <entry><literal>EMPID as
{coll.id}</literal></entry>
+ </row>
+
+ <row>
+ <entry>The element of an collection</entry>
+
+
<entry><literal>{[aliasname].element}</literal></entry>
+
+ <entry><literal>XID as
{coll.element}</literal></entry>
+ </row>
+
+ <row>
+ <entry>roperty of the element in the collection</entry>
+
+
<entry><literal>{[aliasname].element.[propertyname]}</literal></entry>
+
+ <entry><literal>NAME as
{coll.element.name}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of the element in the
collection</entry>
+
+
<entry><literal>{[aliasname].element.*}</literal></entry>
+
+
<entry><literal>{coll.element.*}</literal></entry>
+ </row>
+
+ <row>
+ <entry>All properties of the the collection</entry>
+
+
<entry><literal>{[aliasname].*}</literal></entry>
+
+ <entry><literal>{coll.*}</literal></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </sect3>
+ </sect2>
+
+ <sect2>
+ <title>Returning non-managed entities</title>
+
+ <para>It is possible to apply a ResultTransformer to native sql queries.
Allowing it to e.g. return non-managed entities.</para>
+
+ <programlisting><![CDATA[sess.createSQLQuery("SELECT NAME, BIRTHDATE
FROM CATS")
+
.setResultTransformer(Transformers.aliasToBean(CatDTO.class))]]></programlisting>
+
+ <para>This query specified:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the SQL query string</para>
+ </listitem>
+
+ <listitem>
+ <para>a result transformer</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The above query will return a list of <literal>CatDTO</literal> which
has been instantiated and injected the values of NAME and BIRTHNAME into its
corresponding
+ properties or fields.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Handling inheritance</title>
+
+ <para>Native sql queries which query for entities that is mapped as part
+ of an inheritance must include all properties for the baseclass and all
+ it subclasses.</para>
+ </sect2>
+
+ <sect2>
+ <title>Parameters</title>
+
+ <para>Native sql queries support positional as well as named
+ parameters:</para>
+
+ <programlisting><![CDATA[Query query = sess.createSQLQuery("SELECT *
FROM CATS WHERE NAME like ?").addEntity(Cat.class);
+List pusList = query.setString(0, "Pus%").list();
+
+query = sess.createSQLQuery("SELECT * FROM CATS WHERE NAME like
:name").addEntity(Cat.class);
+List pusList = query.setString("name", "Pus%").list();
]]></programlisting>
+ </sect2>
+
+
+
+ </sect1>
+
+ <sect1 id="querysql-namedqueries" revision="3">
+ <title>Named SQL queries</title>
+
+ <para>Named SQL queries may be defined in the mapping document and called
+ in exactly the same way as a named HQL query. In this case, we do
+ <emphasis>not</emphasis> need to call
+ <literal>addEntity()</literal>.</para>
+
+ <programlisting><![CDATA[<sql-query name="persons">
+ <return alias="person" class="eg.Person"/>
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex}
+ FROM PERSON person
+ WHERE person.NAME LIKE :namePattern
+</sql-query>]]></programlisting>
+
+ <programlisting><![CDATA[List people =
sess.getNamedQuery("persons")
+ .setString("namePattern", namePattern)
+ .setMaxResults(50)
+ .list();]]></programlisting>
+
+ <para>The <literal><return-join></literal> and
+ <literal><load-collection></literal> elements are used to
join
+ associations and define queries which initialize collections,
+ respectively.</para>
+
+ <programlisting><![CDATA[<sql-query name="personsWith">
+ <return alias="person" class="eg.Person"/>
+ <return-join alias="address"
property="person.mailingAddress"/>
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex},
+ adddress.STREET AS {address.street},
+ adddress.CITY AS {address.city},
+ adddress.STATE AS {address.state},
+ adddress.ZIP AS {address.zip}
+ FROM PERSON person
+ JOIN ADDRESS adddress
+ ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
+ WHERE person.NAME LIKE :namePattern
+</sql-query>]]></programlisting>
+
+ <para>A named SQL query may return a scalar value. You must declare the
+ column alias and Hibernate type using the
+ <literal><return-scalar></literal> element:</para>
+
+ <programlisting><![CDATA[<sql-query name="mySqlQuery">
+ <return-scalar column="name" type="string"/>
+ <return-scalar column="age" type="long"/>
+ SELECT p.NAME AS name,
+ p.AGE AS age,
+ FROM PERSON p WHERE p.NAME LIKE 'Hiber%'
+</sql-query>]]></programlisting>
+
+ <para>You can externalize the resultset mapping informations in a
+ <literal><resultset></literal> element to either reuse them
accross
+ several named queries or through the
+ <literal>setResultSetMapping()</literal> API.</para>
+
+ <programlisting><![CDATA[<resultset name="personAddress">
+ <return alias="person" class="eg.Person"/>
+ <return-join alias="address"
property="person.mailingAddress"/>
+</resultset>
+
+<sql-query name="personsWith" resultset-ref="personAddress">
+ SELECT person.NAME AS {person.name},
+ person.AGE AS {person.age},
+ person.SEX AS {person.sex},
+ adddress.STREET AS {address.street},
+ adddress.CITY AS {address.city},
+ adddress.STATE AS {address.state},
+ adddress.ZIP AS {address.zip}
+ FROM PERSON person
+ JOIN ADDRESS adddress
+ ON person.ID = address.PERSON_ID AND address.TYPE='MAILING'
+ WHERE person.NAME LIKE :namePattern
+</sql-query>]]></programlisting>
+
+ <para>You can alternatively use the resultset mapping information in your
+ hbm files directly in java code.</para>
+
+ <programlisting><![CDATA[List cats = sess.createSQLQuery(
+ "select {cat.*}, {kitten.*} from cats cat, cats kitten where kitten.mother =
cat.id"
+ )
+ .setResultSetMapping("catAndKitten")
+ .list();]]></programlisting>
+
+ <sect2 id="propertyresults">
+ <title>Using return-property to explicitly specify column/alias
+ names</title>
+
+ <para>With <literal><return-property></literal> you
can explicitly
+ tell Hibernate what column aliases to use, instead of using the
+ <literal>{}</literal>-syntax to let Hibernate inject its own
+ aliases.</para>
+
+ <programlisting><![CDATA[<sql-query name="mySqlQuery">
+ <return alias="person" class="eg.Person">
+ <return-property name="name" column="myName"/>
+ <return-property name="age" column="myAge"/>
+ <return-property name="sex" column="mySex"/>
+ </return>
+ SELECT person.NAME AS myName,
+ person.AGE AS myAge,
+ person.SEX AS mySex,
+ FROM PERSON person WHERE person.NAME LIKE :name
+</sql-query>
+]]></programlisting>
+
+ <para><literal><return-property></literal> also
works with
+ multiple columns. This solves a limitation with the
+ <literal>{}</literal>-syntax which can not allow fine grained control
of
+ multi-column properties.</para>
+
+ <programlisting><![CDATA[<sql-query
name="organizationCurrentEmployments">
+ <return alias="emp" class="Employment">
+ <return-property name="salary">
+ <return-column name="VALUE"/>
+ <return-column name="CURRENCY"/>
+ </return-property>
+ <return-property name="endDate" column="myEndDate"/>
+ </return>
+ SELECT EMPLOYEE AS {emp.employee}, EMPLOYER AS {emp.employer},
+ STARTDATE AS {emp.startDate}, ENDDATE AS {emp.endDate},
+ REGIONCODE as {emp.regionCode}, EID AS {emp.id}, VALUE, CURRENCY
+ FROM EMPLOYMENT
+ WHERE EMPLOYER = :id AND ENDDATE IS NULL
+ ORDER BY STARTDATE ASC
+</sql-query>]]></programlisting>
+
+ <para>Notice that in this example we used
+ <literal><return-property></literal> in combination with
the
+ <literal>{}</literal>-syntax for injection. Allowing users to choose
how
+ they want to refer column and properties.</para>
+
+ <para>If your mapping has a discriminator you must use
+ <literal><return-discriminator></literal> to specify the
+ discriminator column.</para>
+ </sect2>
+
+ <sect2 id="sp_query" revision="1">
+ <title>Using stored procedures for querying</title>
+
+ <para>Hibernate 3 introduces support for queries via stored procedures
+ and functions. Most of the following documentation is equivalent for
+ both. The stored procedure/function must return a resultset as the first
+ out-parameter to be able to work with Hibernate. An example of such a
+ stored function in Oracle 9 and higher is as follows:</para>
+
+ <programlisting><![CDATA[CREATE OR REPLACE FUNCTION selectAllEmployments
+ RETURN SYS_REFCURSOR
+AS
+ st_cursor SYS_REFCURSOR;
+BEGIN
+ OPEN st_cursor FOR
+ SELECT EMPLOYEE, EMPLOYER,
+ STARTDATE, ENDDATE,
+ REGIONCODE, EID, VALUE, CURRENCY
+ FROM EMPLOYMENT;
+ RETURN st_cursor;
+ END;]]></programlisting>
+
+ <para>To use this query in Hibernate you need to map it via a named
+ query.</para>
+
+ <programlisting><![CDATA[<sql-query
name="selectAllEmployees_SP" callable="true">
+ <return alias="emp" class="Employment">
+ <return-property name="employee" column="EMPLOYEE"/>
+ <return-property name="employer" column="EMPLOYER"/>
+ <return-property name="startDate" column="STARTDATE"/>
+ <return-property name="endDate" column="ENDDATE"/>
+ <return-property name="regionCode"
column="REGIONCODE"/>
+ <return-property name="id" column="EID"/>
+ <return-property name="salary">
+ <return-column name="VALUE"/>
+ <return-column name="CURRENCY"/>
+ </return-property>
+ </return>
+ { ? = call selectAllEmployments() }
+</sql-query>]]></programlisting>
+
+ <para>Notice stored procedures currently only return scalars and
+ entities. <literal><return-join></literal> and
+ <literal><load-collection></literal> are not
supported.</para>
+
+ <sect3 id="querysql-limits-storedprocedures"
revision="1">
+ <title>Rules/limitations for using stored procedures</title>
+
+ <para>To use stored procedures with Hibernate the procedures/functions
+ have to follow some rules. If they do not follow those rules they are
+ not usable with Hibernate. If you still want to use these procedures
+ you have to execute them via
<literal>session.connection()</literal>.
+ The rules are different for each database, since database vendors have
+ different stored procedure semantics/syntax.</para>
+
+ <para>Stored procedure queries can't be paged with
+ <literal>setFirstResult()/setMaxResults()</literal>.</para>
+
+ <para>Recommended call form is standard SQL92: <literal>{ ? = call
+ functionName(<parameters>) }</literal> or <literal>{ ?
= call
+ procedureName(<parameters>}</literal>. Native call syntax is
not
+ supported.</para>
+
+ <para>For Oracle the following rules apply:</para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ A funçãp deve retornar um result set. O primeiro parâmetro da procedure
+ dever ser uma <literal>SAÍDA</literal> que retorne um result set.
Isto é feito
+ usando o tipo a <literal>SYS_REFCURSOR</literal> no Oracle 9 ou
10. No Oracle é
+ necessário definir o tipo <literal>REF CURSOR</literal>, veja a
documentação do Oracle.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>For Sybase or MS SQL server the following rules apply:</para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ A procedure deve retornar um result set. Veja que este servidor pode
retornar
+ múltiplos result sets e update counts. O Hibernate ira iterar os resultados
e
+ pegar o primeiro resultado que é o valor de retorno do result set.
+ O resto será descartado.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
+ Se você habilitar <literal>SET NOCOUNT ON</literal> na sua
procedure, ela
+ provavelmente será mais eficiente. Mas, isto não é obrigatório</para>
+ </listitem>
+ </itemizedlist>
+ </sect3>
+ </sect2>
+ </sect1>
+
+ <sect1 id="querysql-cud">
+ <title>SQL customizado para create, update e delete</title>
+
+ <para>Hibernate3 can use custom SQL statements for create, update, and
+ delete operations. The class and collection persisters in Hibernate
+ already contain a set of configuration time generated strings (insertsql,
+ deletesql, updatesql etc.). The mapping tags
+ <literal><sql-insert></literal>,
+ <literal><sql-delete></literal>, and
+ <literal><sql-update></literal> override these strings:
+
+ Hibernate3 pode usar SQL customizado para operações de create, update e delete.
+ A persistência de classe e collection no hibernate já contem alguma strings
+ de configurações (insertsql, deletesql, updatesql etc.).
+ O mapaemento das tags
+ <literal><sql-insert></literal>,
+ <literal><sql-delete></literal>, e
+ <literal><sql-update></literal>
+ sobreecreve essas strings:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <sql-insert>INSERT INTO PERSON (NAME, ID) VALUES ( UPPER(?), ?
)</sql-insert>
+ <sql-update>UPDATE PERSON SET NAME=UPPER(?) WHERE ID=?</sql-update>
+ <sql-delete>DELETE FROM PERSON WHERE ID=?</sql-delete>
+</class>]]></programlisting>
+
+ <para>
+ O SQL é executado diretamente no seu banco de dados, então você pode usar qualquer
+ linguagem que quiser. Isto com certeza reduzira a portabilidade do seu mapeamento se
+ você utilizar um SQL para um banco de dados especifico.
+ </para>
+
+ <para>
+ Stored Procedures são suportadas se o atributo the
+ <literal>callable</literal> estiver ativado:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <sql-insert callable="true">{call createPerson (?,
?)}</sql-insert>
+ <sql-delete callable="true">{? = call deletePerson
(?)}</sql-delete>
+ <sql-update callable="true">{? = call updatePerson (?,
?)}</sql-update>
+</class>]]></programlisting>
+
+ <para>
+ A ordem de posições dos parâmetros são vitais, pois eles devem estar na mesma
seqüência
+ esperada pelo Hibernate.
+ </para>
+
+ <para>Você pode ver a ordem esperada ativando o debug logging no nível
+ <literal>org.hibernate.persister.entity</literal>. Com este nível
ativado, o Hibernate
+ irá imprimir o SQL estático que foi usado para create, update, delete, etc.
+ Entidades. (Para ver a seqüência esperada, lembre-se de não incluir seu SQL
+ customizado no arquivo de mapeamento, pois ele irá sobreecreve o SQL
+ estático gerado pelo Hibernate).
+ </para>
+
+ <para>As stored procedures são na maioria dos casos (leia: melhor não fazer)
requeridas para
+ retornar o numero de linhas inseridas/atualizadas/deletadas. O hibernate tem algumas
+ verificações em tempo de execução para o sucesso da declaração. Hibernate sempre
registra
+ o primeiro parâmetro da declaração como uma saída numérica para operações CRUD.
+ </para>
+
+ <programlisting><![CDATA[CREATE OR REPLACE FUNCTION updatePerson (uid IN
NUMBER, uname IN VARCHAR2)
+ RETURN NUMBER IS
+BEGIN
+
+ update PERSON
+ set
+ NAME = uname,
+ where
+ ID = uid;
+
+ return SQL%ROWCOUNT;
+
+END updatePerson;]]>
+</programlisting>
+
+ </sect1>
+
+ <sect1 id="querysql-load">
+ <title>SQL customizado para carga</title>
+
+ <para>
+ Você pode declarar sua própria query SQL (ou HQL) para iniciar entidades:
+ </para>
+
+ <programlisting><![CDATA[<sql-query name="person">
+ <return alias="pers" class="Person"
lock-mode="upgrade"/>
+ SELECT NAME AS {pers.name}, ID AS {pers.id}
+ FROM PERSON
+ WHERE ID=?
+ FOR UPDATE
+</sql-query>]]></programlisting>
+
+ <para>
+ Este é apenas uma declaração de query com nome, como discutido anteriormente.
+ Você pode referenciar esta query com nome em um mapeamento de classe:
+ </para>
+
+ <programlisting><![CDATA[<class name="Person">
+ <id name="id">
+ <generator class="increment"/>
+ </id>
+ <property name="name" not-null="true"/>
+ <loader query-ref="person"/>
+</class>]]></programlisting>
+
+ <para>Isto também funciona com stored procedures.
+ </para>
+
+ <para>Você pode tembém definir uma query para iniciar collection:
+ </para>
+
+ <programlisting><![CDATA[<set name="employments"
inverse="true">
+ <key/>
+ <one-to-many class="Employment"/>
+ <loader query-ref="employments"/>
+</set>]]></programlisting>
+
+ <programlisting><![CDATA[<sql-query name="employments">
+ <load-collection alias="emp" role="Person.employments"/>
+ SELECT {emp.*}
+ FROM EMPLOYMENT emp
+ WHERE EMPLOYER = :id
+ ORDER BY STARTDATE ASC, EMPLOYEE ASC
+</sql-query>]]></programlisting>
+
+ <para>You could even define an entity loader that loads a collection by
+ join fetching:</para>
+
+ <programlisting><![CDATA[<sql-query name="person">
+ <return alias="pers" class="Person"/>
+ <return-join alias="emp" property="pers.employments"/>
+ SELECT NAME AS {pers.*}, {emp.*}
+ FROM PERSON pers
+ LEFT OUTER JOIN EMPLOYMENT emp
+ ON pers.ID = emp.PERSON_ID
+ WHERE ID=?
+</sql-query>]]></programlisting>
+ </sect1>
+</chapter>
\ No newline at end of file
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/query_sql.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/session_api.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/session_api.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/session_api.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1248 @@
+<chapter id="objectstate">
+ <title>Trabalhando com objetos</title>
+
+ <para>
+ O Hibernate é uma solução completa de mapeamento objeto/relacional que não apenas
+ poupa o desenvolvedor dos detalhes de baixo nível do sistema de gerenciamento do
+ banco de dados, mas também oferece um <emphasis>gerenciamento de estado
</emphasis>
+ para objetos. Isto é, ao contrário do gerenciamento de <literal>instruções
</literal>
+ SQL em camadas de persistência JDBC/SQL comuns, uma visão natural da persistência
+ orientada a objetos em aplicações Java.
+ </para>
+
+ <para>
+ Em outras palavras, desenvolvedores de aplicações Hibernate podem sempre pensar
em
+ relação ao <emphasis>estado</emphasis> de seus objetos, e não
necessariamente em
+ relação a execução de instruções SQL. Este parte é responsabilidade do Hibernate
e
+ é relevante aos desenvolvedores de aplicações apenas quando estão ajustando
+ a performance do sistema.
+ </para>
+
+ <sect1 id="objectstate-overview">
+ <title>Estado dos objetos no Hibernate</title>
+
+ <para>
+ O Hibernate define e suporta os seguintes estados de um objetos:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Transient</emphasis> - um objeto é transiente
se ele foi instanciando
+ usando apenas o operador <literal>new</literal>, e não
foi associado com uma
+ <literal>Session</literal> do Hibernate. Ele não terá uma
representação
+ persistente no banco de dados e nenhum identificador será atribuído
para ele.
+ Instâncias transientes serão destruídas pelo coletor de lixo se a
aplicação
+ não manter sua referência. Use uma
<literal>Session</literal> do Hibernate
+ para tornar o objeto persistente ( e deixe o Hibernate gerenciar as
+ instruções SQL que serão necessárias para executar esta transição).
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Persistent</emphasis> -– uma instância
persistente possui uma
+ representação no banco de dados e um identificador. Ele pode ter sido
salvo
+ ou carregado, assim, ele está por definição no escopo de uma
+ <literal>Session</literal>. O Hibernate irá detectar
qualquer mudança feita a
+ um objeto persistente e sincronizar o seu estado com o banco de dados
quando
+ completar a unidade de trabalho. Desenvolvedores não executam
instruções manuais
+ de <literal>UPDATE</literal>, ou instruções de
<literal>DELETE</literal>
+ quando o objeto deve ser passado para transiente.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Detached</emphasis> – uma instância desaclopada
é um objeto que
+ foi persistido, mas sua <literal>Session</literal> foi
fechada. A referência
+ ao objeto continua válida, é claro, e a instância destacada
desaclopada pode
+ ser acoplada a uma nova <literal>Session</literal> no
futuro, fazendo-o
+ ( e todas as modificações sofridas) persistente novamente. Essa
característica
+ possibilita um modelo de programação para unidades de trabalho que
rodam
+ durante muito tempo que requer um pensamento por tempo do usuário.
Podemos
+ chamar-las de <emphasis>transações da
aplicação</emphasis>, i.e. uma unidade
+ de trabalho do ponto de vista do usuário.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Agora iremos discutir os estados e suas transições ( e os métodos do
Hibernate que
+ disparam uma transição) em mais detalhes.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-makingpersistent" revision="1">
+ <title>Tornando os objetos persistentes</title>
+
+ <para>
+ Instâncias recentemente instanciadas de uma classe persistente são
+ consideradas <emphasis>transientes </emphasis> pelo Hibernate.
+ Podemos tornar uma instância transiente em
<emphasis>persistente</emphasis>
+ associando-a a uma sessão:
+ </para>
+
+ <programlisting><![CDATA[DomesticCat fritz = new DomesticCat();
+fritz.setColor(Color.GINGER);
+fritz.setSex('M');
+fritz.setName("Fritz");
+Long generatedId = (Long) sess.save(fritz);]]></programlisting>
+
+ <para>
+ Se <literal>Cat</literal> possui um identificador gerado, o
identificador
+ é gerado e atribuído a <literal>cat</literal> quando
<literal>save()</literal>
+ for chamada. Se <literal>Cat</literal> possuir um identificador
+ <literal>Associado</literal>, ou uma chave composta, o
identificador deve ser
+ atribuído à instância de <literal>cat</literal> antes que
<literal>save()</literal>
+ seja chamado. Pode-se usar também <literal>persist()</literal>
ao invés de
+ <literal>save()</literal>, com a semântica definada no novo
esboço do EJB3.
+ </para>
+
+ <para>
+ Alternativamente, pode-se atribuir o identificador usando uma versão
+ sobrecarregada de <literal>save()</literal>.
+ </para>
+
+<programlisting><![CDATA[DomesticCat pk = new DomesticCat();
+pk.setColor(Color.TABBY);
+pk.setSex('F');
+pk.setName("PK");
+pk.setKittens( new HashSet() );
+pk.addKitten(fritz);
+sess.save( pk, new Long(1234) );]]></programlisting>
+
+ <para>
+ Se o objeto persistido possuir objetos associados (e.g. a coleção
+ <literal>kittens</literal> no exemplo anterior), esses objetos
podem ser
+ tornar persistente em qualquer ordem que se queira ao menos que se tenha uma
+ restrição <literal>NOT NULL</literal> em uma coluna de chave
estrangeira.
+ Nunca há risco de violação de restrições de chave estrangeira. Assim,
+ pode-se violar uma restrição <literal>NOT NULL</literal> se
+ <literal>save()</literal> for usada nos objetos em uma ordem
errada.
+ </para>
+
+ <para>
+ Geralmente você não deve se importar com esses detalhes, muito provavelmente
se
+ usará a característica de <emphasis>persistência transitiva
</emphasis> do Hibernate
+ para salvar os objetos associados automaticamente. Então, enquanto uma
restrição
+ <literal>NOT NULL</literal> não ocorrer – Hibernate tomará conta
de tudo.
+ Persistência transitiva será discutida futuramente nesse capítulo.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-loading">
+ <title>Carregando o objetos</title>
+
+ <para>
+ O método <literal>load()</literal> de uma <literal>
Session</literal> nos
+ fornece um meio para recuperar uma instância persistente se o identificador
+ for conhecido. <literal>load()</literal> recebe uma classe do
objeto e carregará
+ o estado em uma instância mais recente dessa classe, no estado persistente.
+ </para>
+
+ <programlisting><![CDATA[Cat fritz = (Cat) sess.load(Cat.class,
generatedId);]]></programlisting>
+
+<programlisting><![CDATA[// you need to wrap primitive identifiers
+long id = 1234;
+DomesticCat pk = (DomesticCat) sess.load( DomesticCat.class, new Long(id)
);]]></programlisting>
+
+ <para>
+ Alternatively, you can load state into a given instance:
+Alternativamente, pode-se carregar um estado em uma instância dada:
+ </para>
+
+<programlisting><![CDATA[Cat cat = new DomesticCat();
+// load pk's state into cat
+sess.load( cat, new Long(pkId) );
+Set kittens = cat.getKittens();]]></programlisting>
+
+ <para>
+ Repare que <literal>load()</literal> irá lançar uma exceção
irrecuperável
+ se não houver na tabela no banco de dados um registro que combine.
+ Se a classe for mapeada com um proxy, <literal>load()</literal>
+ simplesmente retorna um proxy não inicializado e realmente não chamará
+ o banco de dados até que um método do proxy seja invocado.
+ Esse comportamento é muito útil se deseja-se criar uma associação
+ com um objeto sem que realmente o carregue do bando de dados.
+ Isto também permite que sejam carregadas múltiplas instâncias como um
+ grupo se <literal>batch-size</literal> estiver para o mapeamento
da
+ classe.
+ </para>
+
+ <para>
+ Se você não tiver certeza da existencia do registro no banco, você deve
+ usar o metodo <literal>get()</literal>, que consulta o banco
+ imediantamente e retorna um null se não existir o registro.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id);
+if (cat==null) {
+ cat = new Cat();
+ sess.save(cat, id);
+}
+return cat;]]></programlisting>
+
+ <para>
+ Também pode-se carregar um objeto usando <literal>SELECT ... FOR
UPDATE</literal>,
+ usando um <literal>LockMode</literal>. Veja a documentação da API
para maiores
+ informações.
+ </para>
+
+ <programlisting><![CDATA[Cat cat = (Cat) sess.get(Cat.class, id,
LockMode.UPGRADE);]]></programlisting>
+
+ <para>
+ Note that any associated instances or contained collections are
+ <emphasis>not</emphasis> selected <literal>FOR
UPDATE</literal>, unless you decide
+ to specify <literal>lock</literal> or
<literal>all</literal> as a
+ cascade style for the association.
+ </para>
+
+ <para>
+ O recarregamento de um objeto e todas as suas coleções é possível a qualquer
momento,
+ usando o método <literal>refresh()</literal>. Util quando as
triggers do banco de
+ dados são usados para inicializar algumas propriedades do objeto.
+ </para>
+
+ <programlisting><![CDATA[sess.save(cat);
+sess.flush(); //force the SQL INSERT
+sess.refresh(cat); //re-read the state (after the trigger
executes)]]></programlisting>
+
+ <para>
+ Uma importante questão geralmente aparece neste ponto: O quanto Hibernate
carrega
+ do banco de dados e quantos SQL <literal>SELECT</literal> ele
irá usar? Isto
+ depende da estratégia de <emphasis>recuperação</emphasis>usada e
explicada na
+ <xref linkend="performance-fetching"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-querying" revision="1">
+ <title>Consultando</title>
+
+ <para>
+ Se o identificador do objeto que se está buscando não for conhecido,
+ uma consulta será necessária. O Hibernate suporta uma linguagem de consulta
+ (HQL) orientada a objetos fácil mas poderosa. Para criação via programação
+ de consultas, o Hibernate suporta características sofisticadas de consulta
+ por Critério e Exemplo (QBCe QBE). Pode-se também expressar a consulta
+ por meio de SQL nativa do banco de dados, com suporte opcional do Hibernate
+ para conversão do conjunto de reultados em objetos.
+ </para>
+
+ <sect2 id="objectstate-querying-executing"
revision="1">
+ <title>Executando consultas</title>
+
+ <para>
+ Consultas HQL e SQL nativa são representadas por uma instância de
<literal>org.hibernate.Query</literal>.
+ Esta interface oferece métodos para associação de parâmetros, tratamento
de conjunto de resultados,
+ e para a execução de consultas reais. Você pode obter uma
<literal>Query</literal> usando a
+ <literal>Session</literal> atual:
+ </para>
+
+ <programlisting><![CDATA[List cats = session.createQuery(
+ "from Cat as cat where cat.birthdate < ?")
+ .setDate(0, date)
+ .list();
+
+List mothers = session.createQuery(
+ "select mother from Cat as cat join cat.mother as mother where cat.name =
?")
+ .setString(0, name)
+ .list();
+
+List kittens = session.createQuery(
+ "from Cat as cat where cat.mother = ?")
+ .setEntity(0, pk)
+ .list();
+
+Cat mother = (Cat) session.createQuery(
+ "select cat.mother from Cat as cat where cat = ?")
+ .setEntity(0, izi)
+ .uniqueResult();]]
+
+Query mothersWithKittens = (Cat) session.createQuery(
+ "select mother from Cat as mother left join fetch mother.kittens");
+Set uniqueMothers = new HashSet(mothersWithKittens.list());]]></programlisting>
+
+ <para>
+ Geralmente uma consulta é executada ao invocar
<literal>list()</literal>,
+ o resultado da consulta será carregado completamente em uma coleção na
memória.
+ Instâncias de entidades recuperadas por uma consulta estão no estado
persistente.
+ O <literal>uniqueResult()</literal> oferece um atalho se você
souber de
+ previamente que a consulta retornará apenas um único objeto. Repare que
consultas
+ que fazem uso de buscas de coleções de forma ansiosa (eager) geralmente
retornam
+ duplicatas dos objetos raiz ( mas com suas coleções inicializadas ).
Pode-se
+ filtrar estas duplicatas através de um simples
<literal>Set</literal>.
+ </para>
+
+ <sect3 id="objectstate-querying-executing-iterate">
+ <title>Interagindo com resultados</title>
+
+ <para>
+ Ocasionalmente, deves-se ser capaz de atingir performances melhores
com
+ a execução de consultas usando o método
<literal>iterate()</literal>.
+ Geralmente isso será o caso esperado apenas se as instâncias dos
entidades
+ reais retornadas pela consulta já estiverem na sessão ou no caché de
segundo
+ nível. Caso elas ainda não tenham sido armazenadas,
<literal>iterate()</literal>
+ será mais devagar do que <literal>list()</literal> e pode
ser necessário vários
+ acessos ao banco de dados para um simples consulta, geralmente
<emphasis>1</emphasis>
+ para a seleção inicial que retorna apenas identificadores, e
<emphasis>n</emphasis>
+ consultas adicionais para inicializar as instâncias reais.
+ </para>
+
+ <programlisting><![CDATA[// fetch ids
+Iterator iter = sess.createQuery("from eg.Qux q order by
q.likeliness").iterate();
+while ( iter.hasNext() ) {
+ Qux qux = (Qux) iter.next(); // fetch the object
+ // something we couldnt express in the query
+ if ( qux.calculateComplicatedAlgorithm() ) {
+ // delete the current instance
+ iter.remove();
+ // dont need to process the rest
+ break;
+ }
+}]]></programlisting>
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-tuples">
+ <title>Consultas que retornam tuplas</title>
+
+ <para>
+ Algumas vezes as consultas do Hibernate retornam tuplas de objetos,
nesse caso
+ cada tupla é retornada como um array:
+ </para>
+
+ <programlisting><![CDATA[Iterator kittensAndMothers =
sess.createQuery(
+ "select kitten, mother from Cat kitten join kitten.mother mother")
+ .list()
+ .iterator();
+
+while ( kittensAndMothers.hasNext() ) {
+ Object[] tuple = (Object[]) kittensAndMothers.next();
+ Cat kitten = tuple[0];
+ Cat mother = tuple[1];
+ ....
+}]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-scalar"
revision="1">
+ <title>Resultados escalares</title>
+
+ <para>
+ Consultas devem especificar uma propriedade da classe na clausula
+ <literal>select</literal>. Elas também podem chamar
funções SQL de agregaçãos.
+ Propriedades ou agregações são considerados resultados agregados
+ ( e não entidades no estado persistente).
+ </para>
+
+ <programlisting><![CDATA[Iterator results = sess.createQuery(
+ "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
+ "group by cat.color")
+ .list()
+ .iterator();
+
+while ( results.hasNext() ) {
+ Object[] row = (Object[]) results.next();
+ Color type = (Color) row[0];
+ Date oldest = (Date) row[1];
+ Integer count = (Integer) row[2];
+ .....
+}]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-parameters">
+ <title>Bind parameters</title>
+
+ <para>
+ Methods on <literal>Query</literal> are provided for
binding values to
+ named parameters or JDBC-style <literal>?</literal>
parameters.
+ <emphasis>Contrary to JDBC, Hibernate numbers parameters from
zero.</emphasis>
+ Named parameters are identifiers of the form
<literal>:name</literal> in
+ the query string. The advantages of named parameters are:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ named parameters are insensitive to the order they occur in
the
+ query string
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ they may occur multiple times in the same query
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ they are self-documenting
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting><![CDATA[//named parameter (preferred)
+Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
+q.setString("name", "Fritz");
+Iterator cats = q.iterate();]]></programlisting>
+
+ <programlisting><![CDATA[//positional parameter
+Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
+q.setString(0, "Izi");
+Iterator cats = q.iterate();]]></programlisting>
+
+ <programlisting><![CDATA[//named parameter list
+List names = new ArrayList();
+names.add("Izi");
+names.add("Fritz");
+Query q = sess.createQuery("from DomesticCat cat where cat.name in
(:namesList)");
+q.setParameterList("namesList", names);
+List cats = q.list();]]></programlisting>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-pagination">
+ <title>Pagination</title>
+
+ <para>
+ If you need to specify bounds upon your result set (the maximum
number of rows
+ you want to retrieve and / or the first row you want to retrieve) you
should
+ use methods of the <literal>Query</literal> interface:
+ </para>
+
+ <programlisting><![CDATA[Query q = sess.createQuery("from
DomesticCat cat");
+q.setFirstResult(20);
+q.setMaxResults(10);
+List cats = q.list();]]></programlisting>
+
+ <para>
+ Hibernate knows how to translate this limit query into the native
+ SQL of your DBMS.
+ </para>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-scrolling">
+ <title>Scrollable iteration</title>
+
+ <para>
+ If your JDBC driver supports scrollable
<literal>ResultSet</literal>s, the
+ <literal>Query</literal> interface may be used to obtain
a
+ <literal>ScrollableResults</literal> object, which allows
flexible
+ navigation of the query results.
+ </para>
+
+ <programlisting><![CDATA[Query q = sess.createQuery("select
cat.name, cat from DomesticCat cat " +
+ "order by cat.name");
+ScrollableResults cats = q.scroll();
+if ( cats.first() ) {
+
+ // find the first name on each page of an alphabetical list of cats by name
+ firstNamesOfPages = new ArrayList();
+ do {
+ String name = cats.getString(0);
+ firstNamesOfPages.add(name);
+ }
+ while ( cats.scroll(PAGE_SIZE) );
+
+ // Now get the first page of cats
+ pageOfCats = new ArrayList();
+ cats.beforeFirst();
+ int i=0;
+ while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1)
);
+
+}
+cats.close()]]></programlisting>
+
+ <para>
+ Note that an open database connection (and cursor) is required for
this
+ functionality, use
<literal>setMaxResult()</literal>/<literal>setFirstResult()</literal>
+ if you need offline pagination functionality.
+ </para>
+
+ </sect3>
+
+ <sect3 id="objectstate-querying-executing-named"
revision="1">
+ <title>Externalizing named queries</title>
+
+ <para>
+ You may also define named queries in the mapping document. (Remember
to use a
+ <literal>CDATA</literal> section if your query contains
characters that could
+ be interpreted as markup.)
+ </para>
+
+ <programlisting><![CDATA[<query
name="ByNameAndMaximumWeight"><![CDATA[
+ from eg.DomesticCat as cat
+ where cat.name = ?
+ and cat.weight > ?
+] ]></query>]]></programlisting>
+
+ <para>
+ Parameter binding and executing is done programatically:
+ </para>
+
+ <programlisting><![CDATA[Query q =
sess.getNamedQuery("ByNameAndMaximumWeight");
+q.setString(0, name);
+q.setInt(1, minWeight);
+List cats = q.list();]]></programlisting>
+
+ <para>
+ Note that the actual program code is independent of the query
language that
+ is used, you may also define native SQL queries in metadata, or
migrate
+ existing queries to Hibernate by placing them in mapping files.
+ </para>
+
+ <para>
+ Also note that a query declaration inside a
<literal><hibernate-mapping></literal>
+ element requires a global unique name for the query, while a query
declaration inside a
+ <literal><class></literal> element is made
unique automatically by prepending the
+ fully qualified name of the class, for example
+ <literal>eg.Cat.ByNameAndMaximumWeight</literal>.
+ </para>
+
+ </sect3>
+
+ </sect2>
+
+ <sect2 id="objectstate-filtering" revision="1">
+ <title>Filtering collections</title>
+ <para>
+ A collection <emphasis>filter</emphasis> is a special type of
query that may be applied to
+ a persistent collection or array. The query string may refer to
<literal>this</literal>,
+ meaning the current collection element.
+ </para>
+
+ <programlisting><![CDATA[Collection blackKittens =
session.createFilter(
+ pk.getKittens(),
+ "where this.color = ?")
+ .setParameter( Color.BLACK, Hibernate.custom(ColorUserType.class) )
+ .list()
+);]]></programlisting>
+
+ <para>
+ The returned collection is considered a bag, and it's a copy of the
given
+ collection. The original collection is not modified (this is contrary to
+ the implication of the name "filter", but consistent with
expected behavior).
+ </para>
+
+ <para>
+ Observe that filters do not require a <literal>from</literal>
clause (though they may have
+ one if required). Filters are not limited to returning the collection
elements themselves.
+ </para>
+
+ <programlisting><![CDATA[Collection blackKittenMates =
session.createFilter(
+ pk.getKittens(),
+ "select this.mate where this.color = eg.Color.BLACK.intValue")
+ .list();]]></programlisting>
+
+ <para>
+ Even an empty filter query is useful, e.g. to load a subset of elements
in a
+ huge collection:
+ </para>
+
+ <programlisting><![CDATA[Collection tenKittens =
session.createFilter(
+ mother.getKittens(), "")
+ .setFirstResult(0).setMaxResults(10)
+ .list();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="objecstate-querying-criteria" revision="1">
+ <title>Criteria queries</title>
+
+ <para>
+ HQL is extremely powerful but some developers prefer to build queries
dynamically,
+ using an object-oriented API, rather than building query strings.
Hibernate provides
+ an intuitive <literal>Criteria</literal> query API for these
cases:
+ </para>
+
+ <programlisting><![CDATA[Criteria crit =
session.createCriteria(Cat.class);
+crit.add( Expression.eq( "color", eg.Color.BLACK ) );
+crit.setMaxResults(10);
+List cats = crit.list();]]></programlisting>
+
+ <para>
+ The <literal>Criteria</literal> and the associated
<literal>Example</literal>
+ API are discussed in more detail in <xref
linkend="querycriteria"/>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="objectstate-querying-nativesql"
revision="2">
+ <title>Queries in native SQL</title>
+
+ <para>
+ You may express a query in SQL, using
<literal>createSQLQuery()</literal> and
+ let Hibernate take care of the mapping from result sets to objects. Note
+ that you may at any time call
<literal>session.connection()</literal> and
+ use the JDBC <literal>Connection</literal> directly. If you
chose to use the
+ Hibernate API, you must enclose SQL aliases in braces:
+ </para>
+
+ <programlisting><![CDATA[List cats = session.createSQLQuery(
+ "SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10",
+ "cat",
+ Cat.class
+).list();]]></programlisting>
+
+ <programlisting><![CDATA[List cats = session.createSQLQuery(
+ "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " +
+ "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " +
+ "FROM CAT {cat} WHERE ROWNUM<10",
+ "cat",
+ Cat.class
+).list()]]></programlisting>
+
+ <para>
+ SQL queries may contain named and positional parameters, just like
Hibernate queries.
+ More information about native SQL queries in Hibernate can be found in
+ <xref linkend="querysql"/>.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="objectstate-modifying" revision="1">
+ <title>Modifying persistent objects</title>
+
+ <para>
+ <emphasis>Transactional persistent instances</emphasis> (ie.
objects loaded, saved, created or
+ queried by the <literal>Session</literal>) may be manipulated by
the application
+ and any changes to persistent state will be persisted when the
<literal>Session</literal>
+ is <emphasis>flushed</emphasis> (discussed later in this
chapter). There is no need
+ to call a particular method (like <literal>update()</literal>,
which has a different
+ purpose) to make your modifications persistent. So the most straightforward
way to update
+ the state of an object is to <literal>load()</literal> it,
+ and then manipulate it directly, while the
<literal>Session</literal> is open:
+ </para>
+
+ <programlisting><![CDATA[DomesticCat cat = (DomesticCat) sess.load(
Cat.class, new Long(69) );
+cat.setName("PK");
+sess.flush(); // changes to cat are automatically detected and
persisted]]></programlisting>
+
+ <para>
+ Sometimes this programming model is inefficient since it would require both
an SQL
+ <literal>SELECT</literal> (to load an object) and an SQL
<literal>UPDATE</literal>
+ (to persist its updated state) in the same session. Therefore Hibernate
offers an
+ alternate approach, using detached instances.
+ </para>
+
+ <para>
+ <emphasis>Note that Hibernate does not offer its own API for direct
execution of
+ <literal>UPDATE</literal> or
<literal>DELETE</literal> statements. Hibernate is a
+ <emphasis>state management</emphasis> service, you don't have
to think in
+ <emphasis>statements</emphasis> to use it. JDBC is a perfect API
for executing
+ SQL statements, you can get a JDBC <literal>Connection</literal>
at any time
+ by calling <literal>session.connection()</literal>. Furthermore,
the notion
+ of mass operations conflicts with object/relational mapping for online
+ transaction processing-oriented applications. Future versions of Hibernate
+ may however provide special mass operation functions. See <xref
linkend="batch"/>
+ for some possible batch operation tricks.</emphasis>
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-detached" revision="2">
+ <title>Modifying detached objects</title>
+
+ <para>
+ Many applications need to retrieve an object in one transaction, send it to
the
+ UI layer for manipulation, then save the changes in a new transaction.
+ Applications that use this kind of approach in a high-concurrency
environment
+ usually use versioned data to ensure isolation for the "long" unit
of work.
+ </para>
+
+ <para>
+ Hibernate supports this model by providing for reattachment of detached
instances
+ using the <literal>Session.update()</literal> or
<literal>Session.merge()</literal>
+ methods:
+ </para>
+
+ <programlisting><![CDATA[// in the first session
+Cat cat = (Cat) firstSession.load(Cat.class, catId);
+Cat potentialMate = new Cat();
+firstSession.save(potentialMate);
+
+// in a higher layer of the application
+cat.setMate(potentialMate);
+
+// later, in a new session
+secondSession.update(cat); // update cat
+secondSession.update(mate); // update mate]]></programlisting>
+
+ <para>
+ If the <literal>Cat</literal> with identifier
<literal>catId</literal> had already
+ been loaded by <literal>secondSession</literal> when the
application tried to
+ reattach it, an exception would have been thrown.
+ </para>
+
+ <para>
+ Use <literal>update()</literal> if you are sure that the session
does
+ not contain an already persistent instance with the same identifier, and
+ <literal>merge()</literal> if you want to merge your
modifications at any time
+ without consideration of the state of the session. In other words,
<literal>update()</literal>
+ is usually the first method you would call in a fresh session, ensuring that
+ reattachment of your detached instances is the first operation that is
executed.
+ </para>
+
+ <para>
+ The application should individually <literal>update()</literal>
detached instances
+ reachable from the given detached instance if and
<emphasis>only</emphasis> if it wants
+ their state also updated. This can be automated of course, using
<emphasis>transitive
+ persistence</emphasis>, see <xref
linkend="objectstate-transitive"/>.
+ </para>
+
+ <para>
+ The <literal>lock()</literal> method also allows an application
to reassociate
+ an object with a new session. However, the detached instance has to be
unmodified!
+ </para>
+
+ <programlisting><![CDATA[//just reassociate:
+sess.lock(fritz, LockMode.NONE);
+//do a version check, then reassociate:
+sess.lock(izi, LockMode.READ);
+//do a version check, using SELECT ... FOR UPDATE, then reassociate:
+sess.lock(pk, LockMode.UPGRADE);]]></programlisting>
+
+ <para>
+ Note that <literal>lock()</literal> can be used with various
+ <literal>LockMode</literal>s, see the API documentation and the
+ chapter on transaction handling for more information. Reattachment is not
+ the only usecase for <literal>lock()</literal>.
+ </para>
+
+ <para>
+ Other models for long units of work are discussed in <xref
linkend="transactions-optimistic"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-saveorupdate">
+ <title>Automatic state detection</title>
+
+ <para>
+ Hibernate users have requested a general purpose method that either saves a
+ transient instance by generating a new identifier or updates/reattaches
+ the detached instances associated with its current identifier.
+ The <literal>saveOrUpdate()</literal> method implements this
functionality.
+ </para>
+
+ <programlisting><![CDATA[// in the first session
+Cat cat = (Cat) firstSession.load(Cat.class, catID);
+
+// in a higher tier of the application
+Cat mate = new Cat();
+cat.setMate(mate);
+
+// later, in a new session
+secondSession.saveOrUpdate(cat); // update existing state (cat has a non-null id)
+secondSession.saveOrUpdate(mate); // save the new instance (mate has a null
id)]]></programlisting>
+
+ <para>
+ The usage and semantics of <literal>saveOrUpdate()</literal>
seems to be confusing
+ for new users. Firstly, so long as you are not trying to use instances from
one session
+ in another new session, you should not need to use
<literal>update()</literal>,
+ <literal>saveOrUpdate()</literal>, or
<literal>merge()</literal>. Some whole
+ applications will never use either of these methods.
+ </para>
+
+ <para>
+ Usually <literal>update()</literal> or
<literal>saveOrUpdate()</literal> are used in
+ the following scenario:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ the application loads an object in the first session
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the object is passed up to the UI tier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ some modifications are made to the object
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the object is passed back down to the business logic tier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the application persists these modifications by calling
+ <literal>update()</literal> in a second session
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ <literal>saveOrUpdate()</literal> does the following:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ if the object is already persistent in this session, do nothing
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if another object associated with the session has the same
identifier,
+ throw an exception
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object has no identifier property,
<literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object's identifier has the value assigned to a newly
instantiated
+ object, <literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if the object is versioned (by a
<literal><version></literal> or
+ <literal><timestamp></literal>), and the
version property value
+ is the same value assigned to a newly instantiated object,
+ <literal>save()</literal> it
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ otherwise <literal>update()</literal> the object
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ and <literal>merge()</literal> is very different:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ if there is a persistent instance with the same identifier currently
+ associated with the session, copy the state of the given object onto
+ the persistent instance
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ if there is no persistent instance currently associated with the
session,
+ try to load it from the database, or create a new persistent
instance
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the persistent instance is returned
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ the given instance does not become associated with the session, it
+ remains detached
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="objectstate-deleting" revision="1">
+ <title>Deleting persistent objects</title>
+
+ <para>
+ <literal>Session.delete()</literal> will remove an object's
state from the database.
+ Of course, your application might still hold a reference to a deleted
object.
+ It's best to think of <literal>delete()</literal> as making a
persistent instance
+ transient.
+ </para>
+
+ <programlisting><![CDATA[sess.delete(cat);]]></programlisting>
+
+ <para>
+ You may delete objects in any order you like, without risk of foreign key
+ constraint violations. It is still possible to violate a <literal>NOT
+ NULL</literal> constraint on a foreign key column by deleting objects
in
+ the wrong order, e.g. if you delete the parent, but forget to delete the
+ children.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-replicating" revision="1">
+ <title>Replicating object between two different datastores</title>
+
+ <para>
+ It is occasionally useful to be able to take a graph of persistent instances
+ and make them persistent in a different datastore, without regenerating
identifier
+ values.
+ </para>
+
+ <programlisting><![CDATA[//retrieve a cat from one database
+Session session1 = factory1.openSession();
+Transaction tx1 = session1.beginTransaction();
+Cat cat = session1.get(Cat.class, catId);
+tx1.commit();
+session1.close();
+
+//reconcile with a second database
+Session session2 = factory2.openSession();
+Transaction tx2 = session2.beginTransaction();
+session2.replicate(cat, ReplicationMode.LATEST_VERSION);
+tx2.commit();
+session2.close();]]></programlisting>
+
+ <para>
+ The <literal>ReplicationMode</literal> determines how
<literal>replicate()</literal>
+ will deal with conflicts with existing rows in the database.
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>ReplicationMode.IGNORE</literal> - ignore the
object when there is
+ an existing database row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.OVERWRITE</literal> - overwrite
any existing database
+ row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.EXCEPTION</literal> - throw an
exception if there is
+ an existing database row with the same identifier
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ReplicationMode.LATEST_VERSION</literal> -
overwrite the row if its
+ version number is earlier than the version number of the object, or
ignore
+ the object otherwise
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Usecases for this feature include reconciling data entered into different
database
+ instances, upgrading system configuration information during product
upgrades,
+ rolling back changes made during non-ACID transactions and more.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-flushing">
+ <title>Flushing the Session</title>
+
+ <para>
+ From time to time the <literal>Session</literal> will execute the
SQL statements
+ needed to synchronize the JDBC connection's state with the state of
objects held in
+ memory. This process, <emphasis>flush</emphasis>, occurs by
default at the following
+ points
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ before some query executions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ from
<literal>org.hibernate.Transaction.commit()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ from <literal>Session.flush()</literal>
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The SQL statements are issued in the following order
+ </para>
+
+ <orderedlist spacing="compact">
+ <listitem>
+ <para>
+ all entity insertions, in the same order the corresponding objects
+ were saved using <literal>Session.save()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all entity updates
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection deletions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection element deletions, updates and insertions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all collection insertions
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ all entity deletions, in the same order the corresponding objects
+ were deleted using <literal>Session.delete()</literal>
+ </para>
+ </listitem>
+ </orderedlist>
+
+ <para>
+ (An exception is that objects using <literal>native</literal> ID
generation are
+ inserted when they are saved.)
+ </para>
+
+ <para>
+ Except when you explicity <literal>flush()</literal>, there are
absolutely no
+ guarantees about <emphasis>when</emphasis> the
<literal>Session</literal> executes
+ the JDBC calls, only the <emphasis>order</emphasis> in which they
are executed.
+ However, Hibernate does guarantee that the
<literal>Query.list(..)</literal>
+ will never return stale data; nor will they return the wrong data.
+ </para>
+
+ <para>
+ It is possible to change the default behavior so that flush occurs less
frequently.
+ The <literal>FlushMode</literal> class defines three different
modes: only flush
+ at commit time (and only when the Hibernate
<literal>Transaction</literal> API
+ is used), flush automatically using the explained routine, or never flush
unless
+ <literal>flush()</literal> is called explicitly. The last mode is
useful for long running
+ units of work, where a <literal>Session</literal> is kept open
and disconnected for
+ a long time (see <xref
linkend="transactions-optimistic-longsession"/>).
+ </para>
+
+ <programlisting><![CDATA[sess = sf.openSession();
+Transaction tx = sess.beginTransaction();
+sess.setFlushMode(FlushMode.COMMIT); // allow queries to return stale state
+
+Cat izi = (Cat) sess.load(Cat.class, id);
+izi.setName(iznizi);
+
+// might return stale data
+sess.find("from Cat as cat left outer join cat.kittens kitten");
+
+// change to izi is not flushed!
+...
+tx.commit(); // flush occurs
+sess.close();]]></programlisting>
+
+ <para>
+ During flush, an exception might occur (e.g. if a DML operation violates a
constraint).
+ Since handling exceptions involves some understanding of Hibernate's
transactional
+ behavior, we discuss it in <xref linkend="transactions"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-transitive" revision="1">
+ <title>Transitive persistence</title>
+
+ <para>
+ It is quite cumbersome to save, delete, or reattach individual objects,
+ especially if you deal with a graph of associated objects. A common case is
+ a parent/child relationship. Consider the following example:
+ </para>
+
+ <para>
+ If the children in a parent/child relationship would be value typed (e.g. a
collection
+ of addresses or strings), their lifecycle would depend on the parent and no
+ further action would be required for convenient "cascading" of
state changes.
+ When the parent is saved, the value-typed child objects are saved as
+ well, when the parent is deleted, the children will be deleted, etc. This
+ even works for operations such as the removal of a child from the
collection;
+ Hibernate will detect this and, since value-typed objects can't have
shared
+ references, delete the child from the database.
+ </para>
+
+ <para>
+ Now consider the same scenario with parent and child objects being entities,
+ not value-types (e.g. categories and items, or parent and child cats).
Entities
+ have their own lifecycle, support shared references (so removing an entity
from
+ the collection does not mean it can be deleted), and there is by default no
+ cascading of state from one entity to any other associated entities.
Hibernate
+ does not implement <emphasis>persistence by
reachability</emphasis> by default.
+ </para>
+
+ <para>
+ For each basic operation of the Hibernate session - including
<literal>persist(), merge(),
+ saveOrUpdate(), delete(), lock(), refresh(), evict(),
replicate()</literal> - there is a
+ corresponding cascade style. Respectively, the cascade styles are named
<literal>create,
+ merge, save-update, delete, lock, refresh, evict, replicate</literal>.
If you want an
+ operation to be cascaded along an association, you must indicate that in the
mapping
+ document. For example:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
cascade="persist"/>]]></programlisting>
+
+ <para>
+ Cascade styles my be combined:
+ </para>
+
+ <programlisting><![CDATA[<one-to-one name="person"
cascade="persist,delete,lock"/>]]></programlisting>
+
+ <para>
+ You may even use <literal>cascade="all"</literal> to
specify that <emphasis>all</emphasis>
+ operations should be cascaded along the association. The default
<literal>cascade="none"</literal>
+ specifies that no operations are to be cascaded.
+ </para>
+
+ <para>
+ A special cascade style, <literal>delete-orphan</literal>,
applies only to one-to-many
+ associations, and indicates that the <literal>delete()</literal>
operation should
+ be applied to any child object that is removed from the association.
+ </para>
+
+
+ <para>
+ Recommendations:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ It doesn't usually make sense to enable cascade on a
<literal><many-to-one></literal>
+ or <literal><many-to-many></literal>
association. Cascade is often useful for
+ <literal><one-to-one></literal> and
<literal><one-to-many></literal>
+ associations.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If the child object's lifespan is bounded by the lifespan of the
of the parent
+ object make it a <emphasis>lifecycle object</emphasis> by
specifying
+
<literal>cascade="all,delete-orphan"</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Otherwise, you might not need cascade at all. But if you think that
you will often be
+ working with the parent and children together in the same
transaction, and you want to save
+ yourself some typing, consider using
<literal>cascade="persist,merge,save-update"</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Mapping an association (either a single valued association, or a collection)
with
+ <literal>cascade="all"</literal> marks the association
as a
+ <emphasis>parent/child</emphasis> style relationship where
save/update/delete of the
+ parent results in save/update/delete of the child or children.
+ </para>
+ <para>
+ Futhermore, a mere reference to a child from a persistent parent will result
in
+ save/update of the child. This metaphor is incomplete, however. A child which
becomes
+ unreferenced by its parent is <emphasis>not</emphasis>
automatically deleted, except
+ in the case of a <literal><one-to-many></literal>
association mapped with
+ <literal>cascade="delete-orphan"</literal>. The precise
semantics of cascading
+ operations for a parent/child relationship are as follows:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ If a parent is passed to <literal>persist()</literal>,
all children are passed to
+ <literal>persist()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is passed to <literal>merge()</literal>, all
children are passed to
+ <literal>merge()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is passed to <literal>save()</literal>,
<literal>update()</literal> or
+ <literal>saveOrUpdate()</literal>, all children are
passed to <literal>saveOrUpdate()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a transient or detached child becomes referenced by a persistent
parent,
+ it is passed to <literal>saveOrUpdate()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a parent is deleted, all children are passed to
<literal>delete()</literal>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If a child is dereferenced by a persistent parent,
<emphasis>nothing
+ special happens</emphasis> - the application should explicitly
delete
+ the child if necessary - unless
<literal>cascade="delete-orphan"</literal>,
+ in which case the "orphaned" child is deleted.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Finally, note that cascading of operations can be applied to an object graph
at
+ <emphasis>call time</emphasis> or at <emphasis>flush
time</emphasis>. All operations,
+ if enabled, are cascaded to associated entities reachable when the operation
is
+ executed. However, <literal>save-upate</literal> and
<literal>delete-orphan</literal>
+ are transitive for all associated entities reachable during flush of the
+ <literal>Session</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="objectstate-metadata">
+ <title>Usando metadados</title>
+
+ <para>
+ O Hibernate requer um modelo muito rico a nível de metadados de todas as
entidades e tipos de
+ valores. De tempos em tempos, este modelo é muito útil à própria aplicação.
Por exemplo, a
+ aplicação pode usar o metadados do Hibernate que executa um algoritmo
"inteligente" que
+ compreende quais objetos podem ser copiados (por exemplo, tipos de valores
mutáveis) ou
+ não (por exemplo, tipos de valores imutáveis e, possivelmente, entidades
associadas).
+ </para>
+ <para>
+ O Hibernate expõe o metadados via interfaces
<literal>ClassMetadata</literal>
+ e <literal>CollectionMetadata</literal> e pela hierarquia
<literal>Type</literal>.
+ Instâncias das interfaces de metadados podem ser obtidas a partir do
+ <literal>SessionFactory</literal>.
+ </para>
+
+ <programlisting><![CDATA[Cat fritz = ......;
+ClassMetadata catMeta = sessionfactory.getClassMetadata(Cat.class);
+
+Object[] propertyValues = catMeta.getPropertyValues(fritz);
+String[] propertyNames = catMeta.getPropertyNames();
+Type[] propertyTypes = catMeta.getPropertyTypes();
+
+// get a Map of all properties which are not collections or associations
+Map namedValues = new HashMap();
+for ( int i=0; i<propertyNames.length; i++ ) {
+ if ( !propertyTypes[i].isEntityType() && !propertyTypes[i].isCollectionType()
) {
+ namedValues.put( propertyNames[i], propertyValues[i] );
+ }
+}]]></programlisting>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/session_api.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/toolset_guide.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/toolset_guide.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/toolset_guide.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,604 @@
+<chapter id="toolsetguide" revision="2">
+ <title>Toolset Guide</title>
+
+ <para>
+ Roundtrip engineering with Hibernate is possible using a set of Eclipse plugins,
+ commandline tools, as well as Ant tasks.
+ </para>
+
+ <para>
+ The <emphasis>Hibernate Tools</emphasis> currently include plugins
for the Eclipse
+ IDE as well as Ant tasks for reverse engineering of existing databases:
+ </para>
+
+ <itemizedlist>
+ <listitem><para>
+ <emphasis>Mapping Editor:</emphasis> An editor for Hibernate XML
mapping files,
+ supporting auto-completion and syntax highlighting. It also supports
semantic
+ auto-completion for class names and property/field names, making it much more
versatile than a normal XML editor.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>Console:</emphasis> The console is a new view in
Eclipse. In addition to
+ a tree overview of your console configurations, you also get an interactive
view
+ of your persistent classes and their relationships. The console allows you
to
+ execute HQL queries against your database and browse the result directly in
+ Eclipse.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>Development Wizards:</emphasis> Several wizards are
provided with the
+ Hibernate Eclipse tools; you can use a wizard to quickly generate Hibernate
configuration
+ (cfg.xml) files, or you may even completely reverse engineer an existing
database schema
+ into POJO source files and Hibernate mapping files. The reverse engineering
wizard
+ supports customizable templates.
+ </para></listitem>
+ <listitem><para>
+ <emphasis>Ant Tasks:</emphasis>
+ </para></listitem>
+
+ </itemizedlist>
+
+ <para>
+ Please refer to the <emphasis>Hibernate Tools</emphasis> package and
it's documentation
+ for more information.
+ </para>
+
+ <para>
+ However, the Hibernate main package comes bundled with an integrated tool (it can
even
+ be used from "inside" Hibernate on-the-fly):
<emphasis>SchemaExport</emphasis> aka
+ <literal>hbm2ddl</literal>.
+ </para>
+
+ <sect1 id="toolsetguide-s1" revision="2">
+ <title>Automatic schema generation</title>
+
+ <para>
+ DDL may be generated from your mapping files by a Hibernate utility. The
generated
+ schema includes referential integrity constraints (primary and foreign keys)
for
+ entity and collection tables. Tables and sequences are also created for
mapped
+ identifier generators.
+ </para>
+
+ <para>
+ You <emphasis>must</emphasis> specify a SQL
<literal>Dialect</literal> via the
+ <literal>hibernate.dialect</literal> property when using this
tool, as DDL
+ is highly vendor specific.
+ </para>
+
+ <para>
+ First, customize your mapping files to improve the generated schema.
+ </para>
+
+ <sect2 id="toolsetguide-s1-2" revision="3">
+ <title>Customizing the schema</title>
+
+ <para>
+ Many Hibernate mapping elements define optional attributes named
<literal>length</literal>,
+ <literal>precision</literal> and
<literal>scale</literal>. You may set the length, precision
+ and scale of a column with this attribute.
+
+ </para>
+
+ <programlisting><![CDATA[<property name="zip"
length="5"/>]]></programlisting>
+ <programlisting><![CDATA[<property name="balance"
precision="12" scale="2"/>]]></programlisting>
+
+ <para>
+ Some tags also accept a <literal>not-null</literal> attribute
(for generating a
+ <literal>NOT NULL</literal> constraint on table columns) and
a <literal>unique</literal>
+ attribute (for generating <literal>UNIQUE</literal>
constraint on table columns).
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="bar"
column="barId" not-null="true"/>]]></programlisting>
+
+ <programlisting><![CDATA[<element column="serialNumber"
type="long" not-null="true"
unique="true"/>]]></programlisting>
+
+ <para>
+ A <literal>unique-key</literal> attribute may be used to
group columns in
+ a single unique key constraint. Currently, the specified value of the
+ <literal>unique-key</literal> attribute is
<emphasis>not</emphasis> used
+ to name the constraint in the generated DDL, only to group the columns in
+ the mapping file.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="org"
column="orgId" unique-key="OrgEmployeeId"/>
+<property name="employeeId"
unique-key="OrgEmployee"/>]]></programlisting>
+
+ <para>
+ An <literal>index</literal> attribute specifies the name of
an index that
+ will be created using the mapped column or columns. Multiple columns may
be
+ grouped into the same index, simply by specifying the same index name.
+ </para>
+
+ <programlisting><![CDATA[<property name="lastName"
index="CustName"/>
+<property name="firstName"
index="CustName"/>]]></programlisting>
+
+ <para>
+ A <literal>foreign-key</literal> attribute may be used to
override the name
+ of any generated foreign key constraint.
+ </para>
+
+ <programlisting><![CDATA[<many-to-one name="bar"
column="barId"
foreign-key="FKFooBar"/>]]></programlisting>
+
+ <para>
+ Many mapping elements also accept a child
<literal><column></literal> element.
+ This is particularly useful for mapping multi-column types:
+ </para>
+
+ <programlisting><![CDATA[<property name="name"
type="my.customtypes.Name"/>
+ <column name="last" not-null="true" index="bar_idx"
length="30"/>
+ <column name="first" not-null="true" index="bar_idx"
length="20"/>
+ <column name="initial"/>
+</property>]]></programlisting>
+
+ <para>
+ The <literal>default</literal> attribute lets you specify a
default value for
+ a column (you should assign the same value to the mapped property before
+ saving a new instance of the mapped class).
+ </para>
+
+ <programlisting><![CDATA[<property name="credits"
type="integer" insert="false">
+ <column name="credits" default="10"/>
+</property>]]></programlisting>
+
+ <programlisting><![CDATA[<version name="version"
type="integer" insert="false">
+ <column name="version" default="0"/>
+</property>]]></programlisting>
+
+ <para>
+ The <literal>sql-type</literal> attribute allows the user to
override the default
+ mapping of a Hibernate type to SQL datatype.
+ </para>
+
+ <programlisting><![CDATA[<property name="balance"
type="float">
+ <column name="balance" sql-type="decimal(13,3)"/>
+</property>]]></programlisting>
+
+ <para>
+ The <literal>check</literal> attribute allows you to specify
a check constraint.
+ </para>
+
+ <programlisting><![CDATA[<property name="foo"
type="integer">
+ <column name="foo" check="foo > 10"/>
+</property>]]></programlisting>
+
+ <programlisting><![CDATA[<class name="Foo"
table="foos" check="bar < 100.0">
+ ...
+ <property name="bar" type="float"/>
+</class>]]></programlisting>
+
+
+ <table frame="topbot" id="schemattributes-summary"
revision="2">
+ <title>Summary</title>
+ <tgroup cols="3">
+ <colspec colwidth="1*"/>
+ <colspec colwidth="1*"/>
+ <colspec colwidth="2.5*"/>
+ <thead>
+ <row>
+ <entry>Attribute</entry>
+ <entry>Values</entry>
+ <entry>Interpretation</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>length</literal></entry>
+ <entry>number</entry>
+ <entry>column length</entry>
+ </row>
+ <row>
+
<entry><literal>precision</literal></entry>
+ <entry>number</entry>
+ <entry>column decimal precision</entry>
+ </row>
+ <row>
+
<entry><literal>scale</literal></entry>
+ <entry>number</entry>
+ <entry>column decimal scale</entry>
+ </row>
+ <row>
+
<entry><literal>not-null</literal></entry>
+
<entry><literal>true|false</literal></entry>
+ <entry>specfies that the column should be
non-nullable</entry>
+ </row>
+ <row>
+
<entry><literal>unique</literal></entry>
+
<entry><literal>true|false</literal></entry>
+ <entry>specifies that the column should have a unique
constraint</entry>
+ </row>
+ <row>
+
<entry><literal>index</literal></entry>
+
<entry><literal>index_name</literal></entry>
+ <entry>specifies the name of a (multi-column)
index</entry>
+ </row>
+ <row>
+
<entry><literal>unique-key</literal></entry>
+
<entry><literal>unique_key_name</literal></entry>
+ <entry>specifies the name of a multi-column unique
constraint</entry>
+ </row>
+ <row>
+
<entry><literal>foreign-key</literal></entry>
+
<entry><literal>foreign_key_name</literal></entry>
+ <entry>
+ specifies the name of the foreign key constraint
generated
+ for an association, for a
<literal><one-to-one></literal>,
+
<literal><many-to-one></literal>,
<literal><key></literal>,
+ or
<literal><many-to-many></literal> mapping element. Note that
+ <literal>inverse="true"</literal>
sides will not be considered
+ by <literal>SchemaExport</literal>.
+ </entry>
+ </row>
+ <row>
+
<entry><literal>sql-type</literal></entry>
+ <entry><literal>SQL column
type</literal></entry>
+ <entry>
+ overrides the default column type (attribute of
+ <literal><column></literal>
element only)
+ </entry>
+ </row>
+ <row>
+
<entry><literal>default</literal></entry>
+ <entry>SQL expression</entry>
+ <entry>
+ specify a default value for the column
+ </entry>
+ </row>
+ <row>
+
<entry><literal>check</literal></entry>
+ <entry>SQL expression</entry>
+ <entry>
+ create an SQL check constraint on either column or table
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ The <literal><comment></literal> element allows
you to specify comments
+ for the generated schema.
+ </para>
+
+ <programlisting><![CDATA[<class name="Customer"
table="CurCust">
+ <comment>Current customers only</comment>
+ ...
+</class>]]></programlisting>
+
+ <programlisting><![CDATA[<property name="balance">
+ <column name="bal">
+ <comment>Balance in USD</comment>
+ </column>
+</property>]]></programlisting>
+
+ <para>
+ This results in a <literal>comment on table</literal> or
+ <literal>comment on column</literal> statement in the
generated
+ DDL (where supported).
+ </para>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-3" revision="2">
+ <title>Running the tool</title>
+
+ <para>
+ The <literal>SchemaExport</literal> tool writes a DDL script
to standard out and/or
+ executes the DDL statements.
+ </para>
+
+ <para>
+ <literal>java -cp
</literal><emphasis>hibernate_classpaths</emphasis>
+ <literal>org.hibernate.tool.hbm2ddl.SchemaExport</literal>
<emphasis>options mapping_files</emphasis>
+ </para>
+
+ <table frame="topbot">
+ <title><literal>SchemaExport</literal> Command Line
Options</title>
+ <tgroup cols="2">
+ <colspec colwidth="1.5*"/>
+ <colspec colwidth="2*"/>
+ <thead>
+ <row>
+ <entry>Option</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>--quiet</literal></entry>
+ <entry>don't output the script to
stdout</entry>
+ </row>
+ <row>
+
<entry><literal>--drop</literal></entry>
+ <entry>only drop the tables</entry>
+ </row>
+ <row>
+
<entry><literal>--create</literal></entry>
+ <entry>only create the tables</entry>
+ </row>
+ <row>
+
<entry><literal>--text</literal></entry>
+ <entry>don't export to the database</entry>
+ </row>
+ <row>
+
<entry><literal>--output=my_schema.ddl</literal></entry>
+ <entry>output the ddl script to a file</entry>
+ </row>
+ <row>
+
<entry><literal>--naming=eg.MyNamingStrategy</literal></entry>
+ <entry>select a
<literal>NamingStrategy</literal></entry>
+ </row>
+ <row>
+
<entry><literal>--config=hibernate.cfg.xml</literal></entry>
+ <entry>read Hibernate configuration from an XML
file</entry>
+ </row>
+ <row>
+
<entry><literal>--properties=hibernate.properties</literal></entry>
+ <entry>read database properties from a
file</entry>
+ </row>
+ <row>
+
<entry><literal>--format</literal></entry>
+ <entry>format the generated SQL nicely in the
script</entry>
+ </row>
+ <row>
+
<entry><literal>--delimiter=;</literal></entry>
+ <entry>set an end of line delimiter for the
script</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ You may even embed <literal>SchemaExport</literal> in your
application:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = ....;
+new SchemaExport(cfg).create(false, true);]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-4">
+ <title>Properties</title>
+
+ <para>
+ Database properties may be specified
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>as system properties with
<literal>-D</literal><emphasis><property></emphasis></para>
+ </listitem>
+ <listitem>
+ <para>in
<literal>hibernate.properties</literal></para>
+ </listitem>
+ <listitem>
+ <para>in a named properties file with
<literal>--properties</literal></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ The needed properties are:
+ </para>
+
+ <table frame="topbot">
+ <title>SchemaExport Connection Properties</title>
+ <tgroup cols="2">
+ <colspec colwidth="1.5*"/>
+ <colspec colwidth="2*"/>
+ <thead>
+ <row>
+ <entry>Property Name</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>hibernate.connection.driver_class</literal></entry>
+ <entry>jdbc driver class</entry>
+ </row>
+ <row>
+
<entry><literal>hibernate.connection.url</literal></entry>
+ <entry>jdbc url</entry>
+ </row>
+ <row>
+
<entry><literal>hibernate.connection.username</literal></entry>
+ <entry>database user</entry>
+ </row>
+ <row>
+
<entry><literal>hibernate.connection.password</literal></entry>
+ <entry>user password</entry>
+ </row>
+ <row>
+
<entry><literal>hibernate.dialect</literal></entry>
+ <entry>dialect</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-5">
+ <title>Using Ant</title>
+
+ <para>
+ You can call <literal>SchemaExport</literal> from your Ant
build script:
+ </para>
+
+ <programlisting><![CDATA[<target
name="schemaexport">
+ <taskdef name="schemaexport"
+ classname="org.hibernate.tool.hbm2ddl.SchemaExportTask"
+ classpathref="class.path"/>
+
+ <schemaexport
+ properties="hibernate.properties"
+ quiet="no"
+ text="no"
+ drop="no"
+ delimiter=";"
+ output="schema-export.sql">
+ <fileset dir="src">
+ <include name="**/*.hbm.xml"/>
+ </fileset>
+ </schemaexport>
+</target>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-6" revision="2">
+ <title>Incremental schema updates</title>
+
+ <para>
+ The <literal>SchemaUpdate</literal> tool will update an
existing schema with "incremental" changes.
+ Note that <literal>SchemaUpdate</literal> depends heavily
upon the JDBC metadata API, so it will
+ not work with all JDBC drivers.
+ </para>
+
+ <para>
+ <literal>java -cp
</literal><emphasis>hibernate_classpaths</emphasis>
+ <literal>org.hibernate.tool.hbm2ddl.SchemaUpdate</literal>
<emphasis>options mapping_files</emphasis>
+ </para>
+
+ <table frame="topbot">
+ <title><literal>SchemaUpdate</literal> Command Line
Options</title>
+ <tgroup cols="2">
+ <colspec colwidth="1.5*"/>
+ <colspec colwidth="2*"/>
+ <thead>
+ <row>
+ <entry>Option</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>--quiet</literal></entry>
+ <entry>don't output the script to
stdout</entry>
+ </row>
+ <row>
+
<entry><literal>--text</literal></entry>
+ <entry>don't export the script to the
database</entry>
+ </row>
+ <row>
+
<entry><literal>--naming=eg.MyNamingStrategy</literal></entry>
+ <entry>select a
<literal>NamingStrategy</literal></entry>
+ </row>
+ <row>
+
<entry><literal>--properties=hibernate.properties</literal></entry>
+ <entry>read database properties from a
file</entry>
+ </row>
+ <row>
+
<entry><literal>--config=hibernate.cfg.xml</literal></entry>
+ <entry>specify a
<literal>.cfg.xml</literal> file</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ You may embed <literal>SchemaUpdate</literal> in your
application:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = ....;
+new SchemaUpdate(cfg).execute(false);]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-7">
+ <title>Using Ant for incremental schema updates</title>
+
+ <para>
+ You can call <literal>SchemaUpdate</literal> from the Ant
script:
+ </para>
+
+ <programlisting><![CDATA[<target
name="schemaupdate">
+ <taskdef name="schemaupdate"
+ classname="org.hibernate.tool.hbm2ddl.SchemaUpdateTask"
+ classpathref="class.path"/>
+
+ <schemaupdate
+ properties="hibernate.properties"
+ quiet="no">
+ <fileset dir="src">
+ <include name="**/*.hbm.xml"/>
+ </fileset>
+ </schemaupdate>
+</target>]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-8" revision="1">
+ <title>Schema validation</title>
+
+ <para>
+ The <literal>SchemaValidator</literal> tool will validate
that the existing database schema "matches"
+ your mapping documents. Note that
<literal>SchemaValidator</literal> depends heavily upon the JDBC
+ metadata API, so it will not work with all JDBC drivers. This tool is
extremely useful for testing.
+ </para>
+
+ <para>
+ <literal>java -cp
</literal><emphasis>hibernate_classpaths</emphasis>
+ <literal>org.hibernate.tool.hbm2ddl.SchemaValidator</literal>
<emphasis>options mapping_files</emphasis>
+ </para>
+
+ <table frame="topbot">
+ <title><literal>SchemaValidator</literal> Command Line
Options</title>
+ <tgroup cols="2">
+ <colspec colwidth="1.5*"/>
+ <colspec colwidth="2*"/>
+ <thead>
+ <row>
+ <entry>Option</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+
<entry><literal>--naming=eg.MyNamingStrategy</literal></entry>
+ <entry>select a
<literal>NamingStrategy</literal></entry>
+ </row>
+ <row>
+
<entry><literal>--properties=hibernate.properties</literal></entry>
+ <entry>read database properties from a
file</entry>
+ </row>
+ <row>
+
<entry><literal>--config=hibernate.cfg.xml</literal></entry>
+ <entry>specify a
<literal>.cfg.xml</literal> file</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para>
+ You may embed <literal>SchemaValidator</literal> in your
application:
+ </para>
+
+ <programlisting><![CDATA[Configuration cfg = ....;
+new SchemaValidator(cfg).validate();]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="toolsetguide-s1-9">
+ <title>Using Ant for schema validation</title>
+
+ <para>
+ You can call <literal>SchemaValidator</literal> from the Ant
script:
+ </para>
+
+ <programlisting><![CDATA[<target
name="schemavalidate">
+ <taskdef name="schemavalidator"
+ classname="org.hibernate.tool.hbm2ddl.SchemaValidatorTask"
+ classpathref="class.path"/>
+
+ <schemavalidator
+ properties="hibernate.properties">
+ <fileset dir="src">
+ <include name="**/*.hbm.xml"/>
+ </fileset>
+ </schemaupdate>
+</target>]]></programlisting>
+
+ </sect2>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/toolset_guide.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/transactions.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/transactions.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/transactions.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1147 @@
+<chapter id="transactions" revision="2">
+ <title>Transações e Concorrência</title>
+
+ <para>
+ O ponto o mais importante sobre o Hibernate e o controle de concorrência é que é
muito
+ fácil de ser compreendido. O Hibernate usa diretamente conexões de JDBC e
recursos de
+ JTA sem adicionar nenhum comportamento de bloqueio a mais. Nós altamente
recomendamos
+ que você gaste algum tempo com o JDBC, o ANSI e a especificação de isolamento de
transação
+ de seu sistema de gerência da base de dados.
+ </para>
+
+ <para>
+ O Hibernate não bloqueia objetos na memória. Sua aplicação pode esperar o
comportamento
+ tal qual definido pelo nível de isolamento de suas transações de banco de dados.
+ Note que graças ao <literal>Session</literal>, que também é um cache
de escopo de
+ transação, o Hibernate fornece leituras repetíveis para procurar por
identificadores
+ e consultas de entidade (não pesquisas de relatórios que retornam valores
escalares).
+ </para>
+
+ <para>
+ Além do versionamento para o controle automático de concorrência otimista, o
Hibernate
+ oferece também uma API (menor) para bloqueio pessimista de linhas usando a
sintaxe
+ <literal>SELECT FOR UPDATE</literal>. O controle de concorrência
otimista e esta
+ API são discutidos mais tarde neste capítulo.
+ </para>
+
+ <para>
+ Nós começamos a discussão do controle de concorrência no Hibernate com a
granularidade
+ do <literal>Configuration</literal>,
<literal>SessionFactory</literal>, e
+ <literal>Session</literal>, além de transações de base de dados e
conversações longas.
+ </para>
+
+ <sect1 id="transactions-basics" revision="1">
+ <title>Session e escopos de transações</title>
+
+ <para>
+ Um <literal>SessionFactory</literal> é objeto threadsafe
compartilhado por
+ todas as threads da aplicação que consome muitos recursos na sua criação.
+ É criado uma unica vez no inicio da execução da aplicação a partir da
+ instância de uma <literal>Configuration</literal>.
+ </para>
+
+ <para>
+ Uma <literal>Session</literal> é um objeto de baixo custo de
criação, não é threadsafe,
+ deve ser usado uma vez, para uma única requisição, uma conversação, uma única
unidade
+ do trabalho e então deve ser descartado. Um
<literal>Session</literal> não obterá um
+ JDBC <literal>Connection</literal> (ou um
<literal>Datasource</literal>) a menos que
+ necessite, conseqüentemente não consome nenhum recurso até ser usado.
+ </para>
+
+ <para>
+ Para completar, você também tem que pensar sobre as transações de base de
dados.
+ Uma transação tem que ser tão curta quanto possível, para reduzir a disputa
pelo
+ bloqueio na base de dados. Transações longas impedirão que sua aplicação
escale a
+ carga altamente concorrente. Por isso, em um projeto raramente é para manter
+ uma transação de base de dados aberta durante o tempo que o usuário pensa,
+ até que a unidade do trabalho esteja completa.
+ </para>
+
+ <para>
+ Qual é o escopo de uma unidade de trabalho? Pode uma únicoa
<literal>Session</literal>
+ do Hibernate gerenciar diversas transações ou é esta um o relacionamento
um-para-um dos
+ escopos? Quando deve você abrir e fechar uma
<literal>Session</literal> e como você
+ demarca os limites da transação?
+ </para>
+
+ <sect2 id="transactions-basics-uow" revision="1">
+ <title>Unidade de trabalho</title>
+
+ <para>
+ Primeiro, não use o antipattern
<emphasis>sessão-por-operação</emphasis>,
+ isto é, não abra e não feche uma <literal>Session</literal>
para cada simples chamada
+ ao banco de de dados em uma única thread! Naturalmente, o mesmo é
verdadeiro para
+ transações. As chamadas a banco de dados em uma aplicação são feitas
usando uma
+ seqüência planejada, elas são agrupadas em unidades de trabalho atômicas.
+ (Veja que isso também significa que um auto-commit depois de cada
sentença SQL é
+ inútil em uma aplicação, esta modalidade é ideal para o trabalho ad hoc
do console
+ do SQL. O Hibernate impede, ou espera que o servidor de aplicação impessa
isso,
+ o uso da modalidade de auto-commit.) As transações nunca são opcionais,
toda a
+ comunicação com um banco de dados tem que ocorrer dentro de uma
transação, não
+ importa se você vai ler ou escrever dados. Como explicado, o
comportamento auto-commit
+ para leitura de dados deve ser evitado, como muitas transações pequenas
são
+ improváveis de executar melhor do que uma unidade claramente definida do
trabalho. A
+ última opção também muito mais manutenível e extensível.
+ </para>
+
+ <para>
+ O pattern mais comum em uma aplicação multi-usuário cliente/servidor é
+ <emphasis>sessão-por-requisição</emphasis>. Neste modelo, uma
requisição do cliente é
+ enviada ao servidor (onde a camada de persistência do Hibernate roda),
uma
+ <literal>Session</literal> nova do Hibernate é aberta, e
todas as operações da base de
+ dados são executadas nesta unidade do trabalho. Logo que o trabalho for
completado
+ (e a resposta para o cliente for preparada), a sessão é descarregad e
fechada.
+ Você usaria também uma única transação de base de dados para servir às
requisições
+ dos clientes, começando e commitando-o quando você abre e fecha a
<literal>Session</literal>.
+ O relacionamento entre os dois é um-para-um e este modelo é um ajuste
perfeito para muitas
+ aplicações.
+ </para>
+
+ <para>
+ O desafio encontra-se na implementação. O Hibernate fornece gerência
integrada da "sessão atual"
+ para simplificar este pattern. Tudo que você tem que fazer é iniciar uma
transação quando uma
+ requisição tem que ser processada e termina a transação antes que a
resposta seja enviada ao
+ cliente. Você pode fazer onde quiser, soluções comuns são
<literal>ServletFilter</literal>,
+ interceptador AOP com um pointcut (ponto de corte) nos métodos de serviço
ou em um
+ container de proxy/interceptação. Um container de EJB é uma maneira
padronizada para
+ implementar aspectos cross-cutting tais como a demarcação da transação em
EJB session beans,
+ declarativamente com CMT. Se você se decidir usar demarcação programática
de transação,
+ de preferencia a API <literal>Transaction</literal> do
Hibernate mostrada mais adiante neste
+ capítulo, para fácilidade no uso e portabilidade de código.
+ </para>
+
+ <para>
+ Seu código de aplicação pode acessar a "sessão atual" para
processar a requisição
+ fazendo uma chamada simples a
<literal>sessionFactory.getCurrentSession()</literal> em
+ qualquer lugar e com a frequencia necessária. Você sempre conseguirá uma
+ <literal>Session</literal> limitada a transação atual. Isto
tem que ser configurado
+ para recurso local ou os ambientes JTA. Veja <xref
linkend="architecture-current-session"/>.
+ </para>
+
+ <para>
+ Às vezes é conveniente estender o escopo de uma
<literal>Session</literal> e de
+ uma transação do banco de dados até que a "visão esteja
renderizada". É especialmente
+ útil em aplicações servlet que utilizam uma fase de rendenderização
separada depois
+ que a requisição ter sido processada. Estendendo a transação até que
renderização da
+ visão esteja completa é fácil de fazer se você implementar seu próprio
interceptador.
+ Entretanto, não se pode fazer facilmente se você confiar em EJBs com
transações
+ gerenciadas por contêiner, porque uma transação será terminada quando um
método de
+ EJB retornar, antes da renderização de toda visão puder começar.
+ Veja o website e o fórum do Hibernate para dicas e exemplos em torno
deste
+ pattern <emphasis>Open Session in View</emphasis>.
+
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-basics-apptx" revision="1">
+ <title>Longas conversações</title>
+
+ <para>
+ O pattern sessão-por-requisição não é o único conceito útil que você pode
usar ao projetar
+ unidades de trabalho. Muitos processos de negócio requerem uma totalidade
de séries de
+ interações com o usuário intercaladas com acessos a uma base de dados. Em
aplicações web
+ e corporativas não é aceitável para uma transação atrapalhe uma interação
do usuário.
+ Considere o seguinte exemplo:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ A primeira tela de um diálogo abre os dados carregado pelo
usuário em através de
+ <literal>Session</literal> e transação particulares.
O usuário está livre
+ modificar os objetos.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O usuário clica em "Salvar" após 5 minutos e espera
suas modificações serem persistidas;
+ espera também que ele era a única pessoa que edita esta
informação e que nenhuma
+ modificação conflitante possa ocorrer.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Nós chamamos esta unidade de trabalho, do ponto da visão do usuário,
executando uma
+ longa <emphasis>conversação</emphasis> (ou
<emphasis>transação da aplicação</emphasis>).
+ Há muitas maneiras de você pode implementar em sua aplicação.
+
+ </para>
+
+ <para>
+ Uma primeira implementação simples pode manter
a<literal>Session</literal> e a transação
+ aberta durante o tempo de interação do usuário, com bloqueios na base de
dados para impedir
+ a modificação concorrente e para garantir o isolamento e a atomicidade.
Esse é naturalmente
+ um anti-pattern, desde que a disputa do bloqueio não permitiria o
escalonameneto da
+ aplicação com o número de usuários concorrentes.
+ </para>
+
+ <para>
+ Claramente, nós temos que usar diversas transações para implementar a
conversação.
+ Neste caso, Manter o isolamento dos processos de negócio torna-se
responsabilidade
+ parcial da camada da aplicação. Uma única conversação geralmente usa
diversas transações.
+ Ela será atômica se somente uma destas transações (a última) armazenar
os
+ dados atualizados, todas as outras simplesmente leram os dados (por
exemplo em um
+ diálogo do estilo wizard que mede diversos ciclos de
requisição/resposta). Isto é mais
+ fácil de implementar do que pode parecer, especialmente se você usar as
+ características do Hibernate:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>Versionamento automático</emphasis> - O
Hibernate pode fazer o
+ controle automático de concorrência otimista para você, ele pode
+ automaticamente detectar se uma modificação concorrente
+ ocorreu durante o tempo de interação do usuário. Geralmente nós
verificamos
+ somente no fim da conversação.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Detached Objects</emphasis>- se você se
decidir usar o já discutido
+ pattern <emphasis>session-per-request</emphasis>,
todas as instâncias carregadas
+ estarão no estado destacado durante o tempo em que o usuário
estiver pensando.
+ O Hibernate permite que você reatache os objetos e persita as
modificações,
+ esse pattern é chamado
+
<emphasis>session-per-request-with-detached-objects</emphasis>.
+ É usado versionamento automatico para isolar as modificações
concorrentes.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>Extended (or Long) Session</emphasis> A
<literal>Session</literal>
+ do Hibernate pode ser desligada da conexão básica do JDBC depois
que a
+ transação foi commitada e ser reconectado quando uma nova
requisição do
+ cliente ocorrer. Este pattern é conhecido como
+ <emphasis>session-per-conversation</emphasis> e faz o
reatamento uniforme
+ desnecessário. Versionamento automático é usado para isolar
modificações
+ concorrentes e a
<emphasis>session-per-conversation</emphasis> usualmente
+ não é permitido para ser nivelado automaticamente, e sim
explicitamente.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Ambos
<emphasis>session-per-request-with-detached-objects</emphasis> e
+ <emphasis>session-per-conversation</emphasis> possuem
vantagens e desvantagens,
+ nos discutiremos mais tarde neste capítulo no contexto do controle de
+ concorrência otimista.
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-basics-identity">
+ <title>Considerando a identidade do objeto</title>
+
+ <para>
+ Uma aplicação pode acessar concorrentemente o mesmo estado persistente em
duas
+ <literal>Session</literal>s diferentes. Entretanto, uma
instância de uma classe
+ persistente nunca é compartilhada entre duas instâncias
<literal>Session</literal>.
+ Por tanto, há duas noções diferentes da identidade:
+ </para>
+
+ <variablelist spacing="compact">
+ <varlistentry>
+ <term>Identidade da base de dados</term>
+ <listitem>
+ <para>
+ <literal>foo.getId().equals( bar.getId()
)</literal>
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Identidade da JVM</term>
+ <listitem>
+ <para>
+ <literal>foo==bar</literal>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>
+ Então para os objetos acoplados a um
<literal>Session</literal> em <literal>particular </literal>
+ (isto é no escopo de um <literal>Session</literal>), as duas
noções são equivalentes e a
+ identidade da JVM para a identidade da base de dados é garantida pelo
Hibernate. Entretanto,
+ quando a aplicação pode acessar concorrentemente o "mesmo"
objeto do negócio (identidade
+ persistente) em duas sessões diferentes, as duas instâncias serão
realmente "diferentes"
+ (identidade de JVM). Os conflitos são resolvidos usando (versionamento
automático) no
+ flush/commit, usando abordagem otimista.
+
+ </para>
+
+ <para>
+ Este caminho deixa o Hibernate e o banco dedados se preocuparem com a
concorrência; também
+ fornece uma escalabilidade melhor, garantindo que a identidade em
unidades de trabalho
+ único-encadeadas não necessite de bloqueio dispendioso ou de outros meios
de sincronização.
+ A aplicação nunca necessita sincronizar qualquer objeto de negócio tão
longo que transpasse
+ uma única thread por <literal>Session</literal>. Dentro de
uma <literal>Session</literal> a
+ aplicação pode usar com segurança o <literal>==</literal>
para comparar objetos.
+ </para>
+
+ <para>
+ Com tudo, uma aplicação que usa <literal>==</literal> fora de
uma <literal>Session</literal>,
+ pode ver resultados inesperados. Isto pode ocorrer mesmo em alguns
lugares inesperados, por
+ exemplo, se você colocar duas instâncias desacopladas em um mesmo
<literal>Set</literal>.
+ Ambos podem ter a mesma identidade na base de dados (isto é eles
representam a mesma linha
+ em uma tabela), mas a identidade da JVM pela definição não garantida para
instâncias em estado
+ desacoplado. O desenvolvedor tem que sobrescrever os métodos
<literal>equals()</literal> e
+ <literal>hashCode()</literal> em classes persistentes e
implementar sua própria noção da
+ igualdade do objeto. Advertência: nunca use o identificador da base de
dados para implementar
+ a igualdade, use atributos de negócio, uma combinação única, geralmente
imutável. O
+ identificador da base de dados mudará se um objeto transiente passar para
o estado persistente.
+ Se a instância transiente (geralmente junto com instâncias desacopladas)
for inserida em um
+ <literal>Set</literal>, mudar o hashcode quebra o contrato do
<literal>Set</literal>.
+ Atributos para chaves de negócio não têm que ser tão estável quanto às
chaves primárias
+ da base de dados, você somente tem que garantir a estabilidade durante o
tempo que
+ os objetos estiverem no mesmo Set. Veja o website do Hibernate para uma
discussão mais
+ completa sobre o assunto. Note também que esta não é uma caracteristica
do Hibernate,
+ mas simplesmente como a identidade e a igualdade do objeto de Java têm
que ser implementadas.
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-basics-issues">
+ <title>Edições comuns</title>
+
+ <para>
+ Nunca use o anti-patterns
<emphasis>session-per-user-session</emphasis> ou
+ <emphasis>session-per-application</emphasis> (naturalmente,
há umas exceções raras a
+ essa regra). Note que algumas das seguintes edições podem também
aparecer com patterns
+ recomendados, certifique-se que tenha compreendido as implicações antes
de fazer
+ uma decisão de projeto:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Uma <literal>Session</literal> não é threadsafe. As
coisas que são supostas para trabalhar
+ concorrentemente, como requisições HTTP, session beans, ou Swing,
causarão condições de
+ disputa se uma instância <literal>Session</literal>
for compartilhada. Se você mantiver
+ sua <literal>Session</literal> do Hibernate em seu
<literal>HttpSession</literal>
+ (discutido mais tarde), você deve considerar sincronizar o acesso
a sua sessão do HTTP.
+ Caso contrário, um usuário que clica em reload várias muito
rapidamente pode usar o
+ mesmo <literal>Session</literal> em duas threads
executando concorrentemente.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Uma exceção lançada pelo Hibernate significa que você tem que dar
rollback na sua
+ transação no banco de dados e fechar a
<literal>Session</literal> imediatamente
+ (discutido mais tarde em maiores detalhes). Se sua
<literal>Session</literal> é
+ limitado pela aplicação, você tem que parar a aplicação. Dando
rollback na
+ transação no banco de dados não põe seus objetos do negócio em um
estado anterior
+ que estavam no início da transação. Isto significa que o estado
da base de dados
+ e os objetos de negócio perdem a sincronização. Geralmente não é
um problema
+ porque as exceções não são recuperáveis e você tem que iniciar
após o
+ rollback de qualquer maneira.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ O <literal>Session</literal> guarda em cache cada
objeto que está no estado persistente
+ (guardado e checado para estado "sujo" pelo Hibernate).
Isto significa que ele cresce
+ infinitamente até que você obtenha uma OutOfMemoryException, se
você o mantiver aberto
+ por muito tempo ou simplesmente carregar dados demais. Uma
solução é chamar
+ <literal>clear()</literal> e
<literal>evict()</literal> para controlar o cache
+ da <literal>Session</literal>, mas você deve
considerar uma Store Procedure
+ se precisar de operações que envolvam grande volume de dados.
Algumas soluções são
+ mostradas no <xref linkend="batch"/>. Manter uma
<literal>Session</literal> aberta
+ durante uma sessão do usuário significa também uma probabilidade
elevada de se acabar
+ com dados velhos.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="transactions-demarcation">
+ <title>Demarcação de transações de bancos de dados</title>
+
+ <para>
+ Os limites de uma transação de banco de dados (ou sistema) são sempre
necessários. Nenhuma
+ comunicação com o banco de dados pode ocorrer fora de uma transação de banco
de dados (isto
+ parece confundir muitos desenvolvedores que estão usados modo auto-commit).
Sempre use os
+ limites desobstruídos da transação, até mesmo para operações somente leitura.
Dependendo
+ de seu nível de isolamento e capacidade da base de dados isto pode não ser
requerido,
+ mas não há nenhum aspecto negativo se você demarca sempre transações
explicitamente.
+ Certamente, uma única transação será melhor executada do que muitas
transações pequenas,
+ até mesmo para dados de leitura.
+ </para>
+
+ <para>
+ Uma aplicação do Hibernate pode funcionar em ambientes não gerenciados (isto
é aplicações standalone, Web
+ simples ou Swing) e ambientes gerenciados J2EE. Em um ambiente não
gerenciado, o Hibernate é geralmente
+ responsável pelo seu próprio pool de conexões. O desenvolvedor tem que
manualmente ajustar limites das
+ transaçãos, ou seja, começar, commitar, ou dar rollback nas transações ele
mesmo. Um ambiente gerenciado
+ fornece transações gerenciadas por contêiner (CMT - container-managed
transactions), com um conjunto
+ da transações definido declarativamente em descritores de deployment de EJB
session beans, por exemplo.
+ A demarcação programática é então já não é necessário.
+ </para>
+
+ <para>
+ Entretanto, é freqüentemente desejável manter sua camada de persistência
portável entre ambientes
+ de recurso locais não gerenciados e sistemas que podem confiar em JTA, mas
usar BMT em vez de CMT.
+ Em ambos os casos você usaria demarcação de transação programática. O
Hibernate oferece uma API
+ chamada Transaction que traduz dentro do sistema de transação nativa de seu
ambiente de deployment.
+ Esta API é realmente opcional, mas nós encorajamos fortemente seu uso a menos
que você estiver
+ em um CMT session bean.
+ </para>
+
+ <para>
+ Geralmente, finalizar um <literal>Session</literal>envolve quatro
fases distintas:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ flush da sessão
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ commitar a transação
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ fechar a sessão
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ tratar as exceções
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ A limpeza da sessão já foi bem discutida, agora nós daremos uma olhada na
demarcação da
+ transação e na manipulação de exceção em ambientes controlados e não
controlados.
+ </para>
+
+
+ <sect2 id="transactions-demarcation-nonmanaged"
revision="2">
+ <title>Ambiente não gerenciado</title>
+
+ <para>
+ Se uma camada de persistência do Hibernate roda em um ambiente não
gerenciado, as conexões
+ do banco de dados são geralmente tratadas pelos pools de conexões simples
+ (isto é, não baseados em DataSource) dos quais o Hibernate obtém as
conexões assim
+ que necessita. A maneira de se manipular uma sessão/transação é mais ou
menos assim:
+ </para>
+
+ <programlisting><![CDATA[// Non-managed environment idiom
+Session sess = factory.openSession();
+Transaction tx = null;
+try {
+ tx = sess.beginTransaction();
+
+ // do some work
+ ...
+
+ tx.commit();
+}
+catch (RuntimeException e) {
+ if (tx != null) tx.rollback();
+ throw e; // or display error message
+}
+finally {
+ sess.close();
+}]]></programlisting>
+
+ <para>
+ Você não pode chamar <literal>flush()</literal> do
<literal>Session()</literal>
+ explicitamente - a chamada ao <literal>commit()</literal>
dispara automaticamente
+ a sincronização para a sessão (dependendo do <xref
linkend="objectstate-flushing">
+ FlushMode</xref>). Uma chamada ao
<literal>close()</literal> marca o fim de uma sessão.
+ A principal implicação do <literal>close()</literal> é que a
conexão JDBC será abandonada
+ pela sessão. Este código Java é portável e funciona em ambientes não
gerenciado e de JTA.
+ </para>
+
+ <para>
+ Uma solução muito mais flexível é gerência integrada de contexto da
"sessão atual"
+ do Hibernate, como descrito anteriormente:
+ </para>
+
+ <programlisting><![CDATA[// Non-managed environment idiom with
getCurrentSession()
+try {
+ factory.getCurrentSession().beginTransaction();
+
+ // do some work
+ ...
+
+ factory.getCurrentSession().getTransaction().commit();
+}
+catch (RuntimeException e) {
+ factory.getCurrentSession().getTransaction().rollback();
+ throw e; // or display error message
+}]]></programlisting>
+
+ <para>
+ Você muito provavelmente nunca verá estes fragmentos de código em uma
aplicação
+ regular; as exceções fatais (do sistema) devem sempre ser pegas no
"alto".
+ Ou seja, o código que executa chamadas do Hibernate (na camada de
persistência)
+ e o código que trata <literal>RuntimeException</literal> (e
geralmente pode
+ somente limpar acima e na saída) estão em camadas diferentes. O
gerenciamento do
+ contexto atual feito pelo Hibernate pode significativamente simplificar
este
+ projeto, como tudo que você necessita é do acesso a um
<literal>SessionFactory</literal>.
+ A manipulação de exceção é discutida mais tarde neste capítulo.
+ </para>
+
+ <para>
+ Note que você deve selecionar
<literal>org.hibernate.transaction.JDBCTransactionFactory</literal>
+ (que é o padrão) e para o segundo exemplo
<literal>"thread"</literal> como seu
+ <literal>hibernate.current_session_context_class</literal>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-demarcation-jta" revision="3">
+ <title>Usando JTA</title>
+
+ <para>
+ Se sua camada de persistência funcionar em um servidor de aplicação (por
exemplo,
+ dentro dos EJB session beans), cada conexão do datasource obtida pelo
Hibernate
+ automaticamente fará parte da transação global de JTA. Você pode também
instalar uma
+ implementação standalone de JTA e usá-la sem EJB. O Hibernate oferece
duas estratégias
+ para a integração de JTA.
+ </para>
+
+ <para>
+ Se você usar bean-managed transactions (BMT - transações gerenciadas por
bean) o Hibernate dirá
+ ao servidor de aplicação para começar e para terminar uma transação de
BMT se você usar a API
+ Transaction. Assim, o código de gerência de transação é idêntico ao
ambiente não gerenciado.
+ </para>
+
+ <programlisting><![CDATA[// BMT idiom
+Session sess = factory.openSession();
+Transaction tx = null;
+try {
+ tx = sess.beginTransaction();
+
+ // do some work
+ ...
+
+ tx.commit();
+}
+catch (RuntimeException e) {
+ if (tx != null) tx.rollback();
+ throw e; // or display error message
+}
+finally {
+ sess.close();
+}]]></programlisting>
+
+ <para>
+ Se você quiser usar um <literal>Session</literal> limitada
por transação, isto é,
+ a funcionalidade do <literal>getCurrentSession()</literal>
para a propagação fácil
+ do contexto, você terá que usar diretamente a API JTA
<literal>UserTransaction</literal>:
+ </para>
+
+ <programlisting><![CDATA[// BMT idiom with getCurrentSession()
+try {
+ UserTransaction tx = (UserTransaction)new InitialContext()
+ .lookup("java:comp/UserTransaction");
+
+ tx.begin();
+
+ // Do some work on Session bound to transaction
+ factory.getCurrentSession().load(...);
+ factory.getCurrentSession().persist(...);
+
+ tx.commit();
+}
+catch (RuntimeException e) {
+ tx.rollback();
+ throw e; // or display error message
+}]]></programlisting>
+
+ <para>
+ Com CMT, a demarcação da transação é feita em descritores de deployment
do session beans,
+ não programaticamente, conseqüentemente, o código é reduzido a:
+ </para>
+
+ <programlisting><![CDATA[// CMT idiom
+ Session sess = factory.getCurrentSession();
+
+ // do some work
+ ...
+]]></programlisting>
+
+ <para>
+ Em um CMT/EJB mesmo um rollback acontece automaticamente, desde que uma
exeção <literal>RuntimeException</literal>
+ não tratável seja lançada por um método de um session bean que informa ao
contêiner ajustar a
+ transação global ao rollback. <emphasis>Isto significa que você não
necessita usar a API
+ <literal>Transaction</literal> do Hibernate em tudo com BMT
ou CMT e você obtém a propagação
+ automática do Session "atual" limitada à
transação.</emphasis>
+ </para>
+
+ <para>
+ Veja que você deverá escolher
<literal>org.hibernate.transaction.JTATransactionFactory</literal>
+ se você usar o JTA diretamente (BMT) e
<literal>org.hibernate.transaction.CMTTransactionFactory</literal>
+ em um CMT session bean, quando você configura a fábrica de transação do
Hibernate. Lembre-se também de
+ configurar o
<literal>hibernate.transaction.manager_lookup_class</literal>. Além disso,
certifique-se
+ que seu
<literal>hibernate.current_session_context_class</literal> ou não é
configurado (compatibilidade
+ com o legado) ou é definido para
<literal>"jta"</literal>.
+
+ </para>
+
+ <para>
+ A operação <literal>getCurrentSession()</literal> tem um
aspecto negativo em um ambiente JTA.
+ Há uma advertência para o uso do método liberado de conexão
<literal>after_statement</literal>,
+ o qual é usado então por padrão. Devido a uma limitação simples da
especificação JTA, não é
+ possível para o Hibernate automaticamente limpar quaisquer instâncias
<literal>ScrollableResults</literal>
+ ou <literal>Iterator</literal> abertas retornadas pelo
<literal>scroll()</literal> ou
+ <literal>iterate()</literal>. Você
<emphasis>deve</emphasis> liberar o cursor subjacente da
+ base de dados chamando
<literal>ScrollableResults.close()</literal> ou
+ <literal>Hibernate.close(Iterator)</literal> explicitamente
de um bloco <literal>finally</literal>.
+ (Claro que a maioria de aplicações podem facilmente evitar o uso do
<literal>scroll()</literal> ou
+ do <literal>iterate()</literal> em todo código provindo do
JTA ou do CMT.)
+
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-demarcation-exceptions">
+ <title>Tratamento de Exceção</title>
+
+ <para>
+ Se a <literal>Session</literal> levantar uma exceção
(incluindo qualquer
+ <literal>SQLException</literal>), você deve imediatamente dar
um rollback
+ na transação do banco, chamando
<literal>Session.close()</literal> e descartando
+ a instância da <literal>Session</literal>. Certos métodos da
<literal>Session</literal>
+ <literal>não</literal> deixarão a sessão em um estado
inconsistente. Nenhuma exceção
+ lançada pelo Hibernate pode ser recuperada. Certifique-se que a
<literal>Session</literal>
+ será fechada chamando <literal>close()</literal> no bloco
<literal>finally</literal>.
+ </para>
+
+ <para>
+ A exceção <literal>HibernateException</literal>, a qual
envolve a maioria dos erros
+ que podem ocorrer em uma camada de persistência do Hibernate, é uma
exceção unchecked (
+ não estava em umas versões mais antigas de Hibernate). Em nossa opinião,
nós não devemos
+ forçar o desenvolvedor a tratar uma exceção irrecuperável em uma camada
mais baixa.
+ Na maioria dos sistemas, as exceções unchecked e fatais são tratadas em
um dos primeiros
+ frames da pilha da chamada do método (isto é, em umas camadas mais
elevadas) e uma mensagem
+ de erro é apresentada ao usuário da aplicação (ou a alguma outra ação
apropriada é feita).
+ Note que Hibernate pode também lançar outras exceções unchecked que não
são um
+ <literal>HibernateException</literal>. Estas, também são,
irrecuperáveis e uma ação
+ apropriada deve ser tomada.
+ </para>
+
+ <para>
+ O Hibernate envolve <literal>SQLException</literal>s lançadas
ao interagir com a base de dados
+ em um <literal>JDBCException</literal>. Na realidade, o
Hibernate tentará converter a exceção em
+ em uma sub classe mais significativa da
<literal>JDBCException</literal>. A
+ <literal>SQLException</literal> subjacente está sempre
disponível através de
+ <literal>JDBCException.getCause()</literal>.
+ </para>
+
+ <para>
+ O Hibernate converte a <literal>SQLException</literal> em uma
sub classe
+ <literal>JDBCException</literal> apropriada usando
<literal>SQLExceptionConverter</literal>
+ associado ao SessionFactory. Por padrão, o
<literal>SQLExceptionConverter</literal> é definido
+ pelo dialeto configurado; entretanto, é também possível conectar em uma
implementação customizada
+ (veja o javadoc para mais detalhes da classe
<literal>SQLExceptionConverterFactory</literal>).
+ Os subtipos padrão de <literal>JDBCException</literal> são:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>JDBCConnectionException</literal> - indica
um erro com a comunicação subjacente de JDBC.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>SQLGrammarException</literal> - indica um
problema da gramática ou da sintaxe com o SQL emitido.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>ConstraintViolationException</literal> -
indica algum forma de violação de confinamento de integridade.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LockAcquisitionException</literal> - indica
um erro ao adquirir um nível de bloqueio necessário para realizar a operação de
requisição.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>GenericJDBCException</literal> - uma exceção
genérica que não cai em algumas das outras categorias.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect2>
+
+ <sect2 id="transactions-demarcation-timeout">
+ <title>Timeout de Transação</title>
+
+ <para>
+ Uma característica extremamente importante fornecida por um ambiente
+ gerenciado como EJB e que nunca é fornecido pelo código não gerenciado é
o timeout
+ de transação. Timeouts de transação asseguram que nenhuma transação possa
+ reter indefinidamente recursos enquanto não retorna nenhuma resposta ao
usuário.
+ Fora de um ambiente controlado (JTA), o Hibernate não pode fornecer
inteiramente
+ esta funcionalidade. Entretanto, o Hibernate pode afinal controlar as
operações
+ do acesso a dados, assegurando que o nível de deadlocks e queries do
banco de
+ dados com imensos resultados definidos sejam limitados pelo timeout. Em
um ambiente
+ gerenciado, o Hibernate pode delegar o timeout da transação ao JTA. Esta
funcionalidade
+ é abstraída pelo objeto <literal>Transaction</literal> do
Hibernate.
+ </para>
+
+ <programlisting><![CDATA[
+Session sess = factory.openSession();
+try {
+ //set transaction timeout to 3 seconds
+ sess.getTransaction().setTimeout(3);
+ sess.getTransaction().begin();
+
+ // do some work
+ ...
+
+ sess.getTransaction().commit()
+}
+catch (RuntimeException e) {
+ sess.getTransaction().rollback();
+ throw e; // or display error message
+}
+finally {
+ sess.close();
+}]]></programlisting>
+
+ <para>
+ Veja que <literal>setTimeout()</literal> não pode ser chamado
em um CMT bean,
+ onde os timeouts das transações devem ser definidos declarativamente.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="transactions-optimistic">
+ <title>Controle de concorrência otimista</title>
+
+ <para>
+ O único caminho que é consistente com a elevada concorrência e escalabilidade
+ é controle de concorrência otimista com versionamento. Checagem de versão usa
+ número de versão, ou timestamps, para detectar conflitos de atualizações (e
para
+ impedir atualizações perdidas). O Hibernate fornece três caminhos possíveis
para
+ escrever aplicações que usam concorrência otimista. Os casos de uso que nós
mostramos
+ estão no contexto de conversações longas, mas a checagem de versão também tem
o
+ benefício de impedir atualizações perdidas em únicas transações.
+ </para>
+
+ <sect2 id="transactions-optimistic-manual">
+ <title>Checagem de versão da aplicação</title>
+
+ <para>
+ Em uma implementação sem muita ajuda do Hibernate, cada interação com o
banco de dados
+ ocorre em uma nova <literal>Session</literal> e o
desenvolvedor é responsável para
+ recarregar todas as instâncias persistentes da base de dados antes de
manipulá-las.
+ Este caminho força a aplicação a realizar sua própria checagem de versão
para assegurar
+ a conversação do isolamento da transação. Este caminho é menos eficiente
em termos de
+ acesso ao banco de dados. É a caminho mais similar a EJBs entity.
+ </para>
+
+ <programlisting><![CDATA[// foo is an instance loaded by a previous
Session
+session = factory.openSession();
+Transaction t = session.beginTransaction();
+
+int oldVersion = foo.getVersion();
+session.load( foo, foo.getKey() ); // load the current state
+if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();
+foo.setProperty("bar");
+
+t.commit();
+session.close();]]></programlisting>
+
+ <para>
+ A propriedade <literal>version</literal> é mapeada usando
<literal><version></literal>,
+ e o Hibernate vai incrementá-lo-á automaticamente durante o flush se a
entidade
+ estiver alterada.
+ </para>
+
+ <para>
+ Claro, se você se estiver operando em um ambiente de baixa concorrência
de dados
+ e não requerer a checagem de versão, você pode usar este caminho e apenas
saltar a
+ checagem de versão. Nesse caso, o <emphasis>ultimo commit realizdo
</emphasis> é
+ a estratégia padrão para suas conversações longas. Mantenha em mente que
isto pode
+ confundir os usuários da aplicação, assim como eles podem experimentar
atualizações
+ perdidas sem mensagens de erro ou uma possibilidade ajustar mudanças de
conflito.
+
+ </para>
+
+ <para>
+ Claro que, checagem manual da versão é somente praticável em
circunstâncias triviais
+ e não para a maioria de aplicações. Freqüentemente, os grafos completos
de objetos
+ modificados têm que ser verificados, não somente únicas instâncias. O
Hibernate oferece
+ checagem de versão automática com uma
<literal>Session</literal> estendida ou instâncias
+ desatachadas como o paradigma do projeto.
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-optimistic-longsession">
+ <title>Sessão estendida e versionamento automático</title>
+
+ <para>
+ Uma única instância de <literal>Session</literal> e suas
instâncias persistentes
+ são usadas para a conversação inteira, isto é conhecido como
+ <emphasis>session-per-conversation</emphasis>. O Hibernate
verifica versões da instância
+ no momento dio flush, lançando uma exceção se a modificação concorrente
for detectada.
+ Até o desenvolvedor pegar e tratar essa exceção (as opções comuns são a
oportunidade
+ para que o usuário intercale as mudanças ou reinicie a conversação do
negócio com
+ dados não antigos).
+ </para>
+
+ <para>
+ The <literal>Session</literal> is disconnected from any
underlying JDBC connection
+ when waiting for user interaction. This approach is the most efficient in
terms
+ of database access. The application need not concern itself with version
checking or
+ with reattaching detached instances, nor does it have to reload instances
in every
+ database transaction.
+ A <literal>Session</literal> é desconectada de toda a conexão
JDBC subjacente
+ enquanto espera a interação do usuário. Este caminho é a mais eficiente
em termos
+ de acesso a bancos de dados. A aplicação não necessita concernir-se com a
checagem
+ de versão ou com as instâncias destacadas reatadas, nem tem que
recarregar instâncias
+ em cada transação.
+ </para>
+
+ <programlisting><![CDATA[// foo is an instance loaded earlier by the
old session
+Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start
transaction
+
+foo.setProperty("bar");
+
+session.flush(); // Only for last transaction in conversation
+t.commit(); // Also return JDBC connection
+session.close(); // Only for last transaction in
conversation]]></programlisting>
+ <para>
+ O objeto <literal>foo</literal> sabe que
<literal>Session</literal> já foi carregada. Começando
+ uma nova transação em uma sessão velha obtém uma conexão nova e recomeça
a sessão. Commitando
+ uma transação desconecta uma sessão da conexão JDBC e retorna a conexão
ao pool. Após a reconexão,
+ forçar uma checagem de versão em dados que você não está atualizando,
você pode chamar
+ <literal>Session.lock()</literal> com o
<literal>LockMode.READ</literal> em todos os objetos
+ que possam ter sido atualizados por uma outra transação. Você não
necessita bloquear nenhum
+ dado para atualizar. Geralmente você configuraria
<literal>FlushMode.NEVER</literal> em uma
+ <literal>Session</literal> estendida, de modo que somente o
último ciclo da transação tenha
+ permissão de persistir todas as modificações feitas nesta conversação.
Disso, somente esta última
+ transação incluiria a operação <literal>flush()</literal> e
então chamar também <literal>close()</literal>
+ da sessão para terminar a conversação.
+ </para>
+
+ <para>
+ Este pattern é problemático se a <literal>Session</literal>
for demasiadamente grande para
+ ser armazenado durante o tempo que usuário pensar, por exemplo um
<literal>HttpSession</literal>
+ estiver mantido tão pequeno quanto possível. Como o
<literal>Session</literal> é também cache
+ de primeiro nível (imperativo) e contém todos os objetos carregados, nós
podemos provavelmente
+ usar esta estratégia somente para alguns ciclos de requisição/resposta.
Você deve usar a
+ <literal>Session</literal> somente para uma única
conversação, porque ela logo também
+ estará com dados velhos.
+ </para>
+
+ <para>
+ (Note que versões mais atuais de Hibernate requerem a desconexão e o
reconexão explícitas de
+ uma <literal>Session</literal>. Estes métodos são
desatualizados, como o início e término de
+ uma transação tem o mesmo efeito.)
+ </para>
+
+ <para>
+ Note também que você deve manter a <literal>Session</literal>
desconectada fechada
+ para a camada de persistência. Ou seja, use um EJB stateful session bean
para
+ prender a <literal>Session</literal> em um ambiente do três
camadas e não o
+ transferir à camada web (ou até serializá-lo para uma camada separada)
+ para armazená-lo no <literal>HttpSession</literal>.
+
+ </para>
+
+ <para>
+ O pattern sessão estendida, ou
<emphasis>session-per-conversation</emphasis>, é mais
+ difícil de implementar com gerenciamento automático de sessão atual. Você
precisa fornecer
+ sua própria implementação do
<literal>CurrentSessionContext</literal> para isto
+ (veja o Hibernate Wiki para exemplos).
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-optimistic-detached">
+ <title>Objetos destacados e versionamento automático</title>
+
+ <para>
+ Cada interação com o armazenamento persistente ocorre em uma
<literal>Session</literal> nova.
+ Entretanto, as mesmas instâncias persistentes são reusadas para cada
interação com o banco de dados.
+ A aplicação manipula o estado das instâncias desatachadas originalmente
carregadas em um outro
+ <literal>Session</literal> e reata-os então usando
<literal>Session.update()</literal>,
+ <literal>Session.saveOrUpdate()</literal> ou
<literal>Session.merge()</literal>.
+ </para>
+
+ <programlisting><![CDATA[// foo is an instance loaded by a previous
Session
+foo.setProperty("bar");
+session = factory.openSession();
+Transaction t = session.beginTransaction();
+session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded
already
+t.commit();
+session.close();]]></programlisting>
+
+ <para>
+ Outra vez, o Hibernate verificará versões da instância durante o flush,
+ lançando uma exceção se ocorrer conflitos de atualizações.
+ </para>
+
+ <para>
+ Você pode também chamar o <literal>lock()</literal> em vez de
<literal>update()</literal>
+ e usar <literal>LockMode.READ</literal> (executando uma
checagem de versão, ignorando
+ todos os caches) se você estiver certo de que o objeto não foi
modificado.
+ </para>
+
+ </sect2>
+
+ <sect2 id="transactions-optimistic-customizing">
+ <title>Versionamento automático customizado</title>
+
+ <para>
+ Você pode desabilitar o incremento da versão automática de Hibernate para
propriedades
+ e coleções particulares configurando o mapeamento do atributo
<literal>optimistic-lock</literal>
+ para false. O Hibernate então não irá incrementa versões se a propriedade
estiver
+ modificada.
+ </para>
+
+ <para>
+ Os esquemas da base de dados legada são freqüentemente estáticos e não
podem ser modificados.
+ Ou outras aplicações puderam também acessar a mesma base de dados e não
sabem tratar a
+ versão dos números ou timestamps. Em ambos os casos, o versionamento não
pode confiar em uma
+ coluna particular em uma tabela. Para forçar uma checagem de versão sem
uma versão ou mapeamento
+ da propriedade do timestamp com uma comparação do estado de todos os
campos em uma linha,
+ configure <literal>optimistic-lock="all"</literal>
no mapeamento <literal><class></literal>.
+ Note que isto conceitualmente é somente feito em trabalhos se Hibernate
puder comparar o estado
+ velho e novo, isto é, se você usa um único
<literal>Session</literal> longo e não
+ session-per-request-with-detached-objects.
+ </para>
+
+ <para>
+ Às vezes a modificação concorrente pode ser permitida tão longa quanto às
mudanças que
+ tiveram sido feitas que não sobrepuseram. Se você configurar
<literal>optimistic-lock="dirty"</literal>
+ ao mapear o <literal><class></literal>, o
Hibernate comparará somente campos
+ modificados durante o flush.
+ </para>
+
+ <para>
+ Em ambos os casos, com as colunas dedicadas da versão/timestamp ou com
comparação do
+ campo cheio/modificados, o Hibernate usa uma única declaração UPDATE (com
uma cláusula
+ WHERE apropriada ) por entidade para executar a checagem da versão e
atualizar a informação.
+ Se você usa a persistência transitiva para cascatear o reatamento das
entidades associadas,
+ o Hibernate pode executar atualizações desnecessárias. Isso não é
geralmente um problema,
+ mas triggers <emphasis>on update</emphasis> em um banco de
dados podem ser executados
+ mesmo quando nenhuma mudança foi feita nas instâncias destacadas. Você
pode customizar
+ este comportamento configurando
<literal>select-before-update="true"</literal> no
+ mapeamento <literal><class></literal>,
forçando o Hibernate a dá um SELECT nas
+ instâncias para assegurar-se esse as mudanças ocorreram realmente, antes
de atualizar
+ a linha.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="transactions-locking">
+ <title>Locking pessimista</title>
+
+ <para>
+ Não se pretende que os usuários gastam muitas horas se preocupando com suas
estratégias de
+ locking. Geralmente é o bastante para especificar um nível de isolamento para
as conexões
+ JDBC e então deixar simplesmente o banco de dados fazer todo o trabalho.
Entretanto, os
+ usuários avançados podem às vezes desejar obter locks pessimistas exclusivos,
ou re-obter
+ locks no início de uma nova transação.
+ </para>
+
+ <para>
+ O Hibernate usará sempre o mecanismo de lock da base de dados, nunca trava
objetos
+ na memória!
+ </para>
+
+ <para>
+ A classe <literal>LockMode</literal> define os diferentes níveis
de lock que o Hibernate
+ pode adquirir. Um lock é obtido pelos seguintes mecanismos:
+
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>LockMode.WRITE</literal> é adquirido
automaticamente quando o Hibernate atualiza
+ ou insere uma linha.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LockMode.UPGRADE</literal> pode ser adquirido
explicitamente pelo usuário
+ usando <literal>SELECT ... FOR UPDATE</literal> em um
banco de dados que suporte
+ esse sintaxe.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LockMode.UPGRADE_NOWAIT</literal> pode ser
adquirido explicitamente pelo usuário
+ usando <literal>SELECT ... FOR UPDATE NOWAIT</literal> no
Oracle.
+
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LockMode.READ</literal> é adquirido
automaticamente quando o Hibernate lê
+ dados em um nível Repeatable Read ou Serializable isolation. Pode ser
readquirido
+ explicitamente pelo usuário.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>LockMode.NONE</literal> representa a ausência do lock.
Todos os objetos mudam para
+ esse estado de lock no final da <literal>Transaction</literal>.
Objetos associados com a sessão
+ através do método <literal>update()</literal> ou
<literal>saveOrUpdate()</literal> também são
+ inicializados com esse lock mode.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ O lock obtido "explicitamente pelo usuário" se dá em uma das
seguintes maneiras:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ Uma chamada a <literal>Session.load()</literal>,
especificando
+ o <literal>LockMode</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Uma chamada a <literal>Session.lock()</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Uma chamada a <literal>Query.setLockMode()</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Se uma <literal>Session.load()</literal> é invocada com
<literal>UPGRADE</literal> ou
+ <literal>UPGRADE_NOWAIT</literal>, e o objeto requisitado ainda
não foi carregado
+ pela sessão, o objeto é carregado usando <literal>SELECT ... FOR
UPDATE</literal>.
+ Se <literal>load()</literal> for chamado para um objeto que já
foi carregado
+ com um lock menos restritivo que o novo lock solicitado, o Hibernate invoca o
+ método <literal>lock()</literal> para aquele objeto.
+ </para>
+
+ <para>
+ O método <literal>Session.lock()</literal> executa uma
verificação no número da versão
+ se o modo de lock especificado for <literal>READ</literal>,
<literal>UPGRADE</literal> ou
+ <literal>UPGRADE_NOWAIT</literal>.. (No caso do
<literal>UPGRADE</literal> ou
+ <literal>UPGRADE_NOWAIT</literal>, é usado <literal>SELECT
... FOR UPDATE</literal>.)
+ </para>
+
+ <para>
+ Se o banco de dados não suportar o lock mode solicitado, o Hibernate vai usar
um modo
+ alternativo apropriado (ao invés de lançar uma exceção). Isso garante que a
aplicação
+ vai ser portável.
+ </para>
+
+ </sect1>
+
+ <sect1 id="transactions-connection-release">
+ <title>Modos de liberar a Connection</title>
+
+ <para>
+ O comportamento legado do Hibernate (2.x) em consideração ao gerenciamento da
conexão
+ via JDBC fez com que a <literal>Session</literal> precisasse
obter uma conexão
+ quando ela precisasse pela primeira vez e depois manter a conexão enquanto
+ a sessão não fosse fechada. O Hibernate 3.x introduz a idéia de modos de
liberar a
+ sessão, para informar a sessão a forma como deve manusear a sua conexão JDBC.
+ Veja que essa discussão só é pertinente para conexões fornecidas com um
+ <literal>ConnectionProvider</literal> configurado; conexões
fornecidas pelo usuário
+ estão fora do escopo dessa discussão. Os diferentes modos de liberação estão
definidos
+ pelos valores da enumeração
+ <literal>org.hibernate.ConnectionReleaseMode</literal>:
+
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>ON_CLOSE</literal> - essencialmente é o modo
legado descrito acima. A sessão
+ do Hibernate obtêm a conexão quando precisar executar alguma operação
JDBC pela
+ primeira vez e mantem enquanto a conexão não for fechada.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>AFTER_TRANSACTION</literal> – informa que a
conexão deve ser
+ liberada após a conclusão de uma
<literal>org.hibernate.Transaction</literal>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>AFTER_STATEMENT</literal> (também conhecida com
liberação agressiva) – informa
+ que a conexão deve ser liberada após a execução de cada statement. A
liberação agressiva
+ não ocorre se o statement deixa pra trás algum recurso aberto
associado com a sessão
+ obtida; atualmente, a única situação em que isso é possível é com o
uso de
+ <literal>org.hibernate.ScrollableResults</literal>.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ O parâmetro de configuração
<literal>hibernate.connection.release_mode</literal> é usado
+ para especificar qual modo de liberação deve ser usado. Opções disponíveis:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para>
+ <literal>auto</literal> (padrão) – essa opção delega ao
modo de liberação retornado pelo
+ método
<literal>org.hibernate.transaction.TransactionFactory.getDefaultReleaseMode()</literal>.
+ Para JTATransactionFactory, ele retorna
ConnectionReleaseMode.AFTER_STATEMENT; para
+ JDBCTransactionFactory, ele retorna
ConnectionReleaseMode.AFTER_TRANSACTION.
+ Raramente é uma boa idéia alterar padrão, como frequencia ao se fazer
isso temos falhas
+ que parecem bugs e/ou suposições inválidas no código do usuário.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>on_close</literal> - indica o uso da
ConnectionReleaseMode.ON_CLOSE. Essa opção
+ foi deixada para manter a compatibilidade, mas seu uso é fortemente
desencorajado.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>after_transaction</literal> – indica o uso da
ConnectionReleaseMode.AFTER_TRANSACTION.
+ Essa opção nada deve ser usada com ambientes JTA. Também note que no
caso da
+ ConnectionReleaseMode.AFTER_TRANSACTION, se a sessão foi colocada no
modo auto-commit a
+ conexão vai ser liberada de forma similar ao modo AFTER_STATEMENT.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>after_statement</literal> – indica o uso
ConnectionReleaseMode.AFTER_STATEMENT.
+ Adicionalmente, o <literal>ConnectionProvider</literal>
configurado é consultado para
+ verificar se suporta essa configuração
((<literal>supportsAggressiveRelease()</literal>).
+ Se não suportar, o modo de liberação é redefinido como
ConnectionRelease-Mode.AFTER_TRANSACTION.
+ Essa configuração só é segura em ambientes onde podemos readquirir a
mesma conexão JDBC
+ toda vez que o método
<literal>ConnectionProvider.getConnection()</literal> for chamado ou
+ em um ambiente auto-commit onde não importa se nós recuperamos a
mesma conexão.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/transactions.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/tutorial.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/tutorial.xml 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/tutorial.xml 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,1530 @@
+<chapter id="tutorial">
+ <title>Introdução ao Hibernate</title>
+
+ <sect1 id="tutorial-intro" revision="1">
+ <title>Prefácio</title>
+
+ <para>
+ Este capítulo é um tutorial introdutório
para novos usuários do Hibernate. Nós iniciaremos com uma simples linha de
comando em uma aplicação usando uma base de dados em
memória tornando isto um passo de fácil de compreender.
+ </para>
+
+ <para>
+ Este tutorial é voltado para novos usuários do Hibernate, mas
requer um conhecimento de Java e SQL. Este tutorial é baseado no tutorial de
Michael Gloegl, as bibliotecas Third Party foram nomeadas para JDK 1.4 e 5.0. Você pode
precisar de outras bibliotecas para JDK 1.3.
+ </para>
+
+ <para>
+ O código fonte para o tutorial está incluído no diretório da distribuição
+ <literal>doc/reference/tutorial/</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-firstapp" revision="2">
+ <title>Parte 1 – A primeira aplicação Hibernate</title>
+
+ <para>
+ Primeiro, iremos criar uma simples aplicação Hibernate
baseada em console. Usaremos uma base de dados Java (HSQL DB), então
não teremos que instalar nenhum servidor de base de dados.
+ </para>
+
+ <para>
+ Vamos supor que precisemos de uma aplicação com um
banco de dados pequeno que possa armazenar e atender os eventos que queremos, e as
informaççes sobre os hosts destes eventos.
+ </para>
+
+ <para>
+ A primeira coisa que devemos fazer é configurar nosso
diretório de desenvolvimento,
+ e colocar todas as bibliotecas Java que precisamos dentro dele.
Faça o download da
+ distribuição do Hibernate no site do Hibernate.
Descompacte o pacote e coloque todas
+ as bibliotecas necessárias encontradas no diretório
<literal>/lib</literal>, dentro do
+ diretório <literal>/lib</literal> do seu novo projeto.
Você deverá ter algo parecido
+ com isso:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ antlr.jar
+ cglib.jar
+ asm.jar
+ asm-attrs.jars
+ commons-collections.jar
+ commons-logging.jar
+ hibernate3.jar
+ jta.jar
+ dom4j.jar
+ log4j.jar ]]></programlisting>
+
+ <para>
+ Esta é a configuração mínima
requerida das bibliotecas (observe que também foi copiado
+ o hibernate3.jar da pasta principal do Hibernate) para o Hibernate
<emphasis>na hora do desenvolvimento</emphasis>. O Hibernate permite que você
utilize mais ou menos bibliotecas.
+ Veja o arquivo <literal>README.txt</literal> no
diretório <literal>lib/</literal> da
distribuição
+ do Hibernate para maiores informaççes sobre bibliotecas
requeridas e opcionais.
+ (Atualmente, a biblioteca Log4j não é requerida, mas
é preferida por muitos desenvolvedores.)
+ </para>
+
+ <para>
+ Agora, iremos criar uma classe que representa o evento que queremos armazenar
na base de dados..
+ </para>
+
+ <sect2 id="tutorial-firstapp-firstclass" revision="1">
+ <title>A primeira Classe</title>
+
+ <para>
+ Nossa primeira classe de persistência é uma simples classe JavaBean com
algumas propriedades:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+import java.util.Date;
+
+public class Event {
+ private Long id;
+
+ private String title;
+ private Date date;
+
+ public Event() {}
+
+ public Long getId() {
+ return id;
+ }
+
+ private void setId(Long id) {
+ this.id = id;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+}]]></programlisting>
+
+ <para>
+ Você pode ver que esta classe usa o padrão JavaBean para o nomeamento
convencional da propriedade getter e dos métodos setter, como também a visibilidade
private dos campos. Este é um padrão de projeto recomendado, mas não requerido. O
Hibernate pode também acessar campos diretamente, o benefício para os métodos de acesso é
a robustez para o Refactoring. O construtor sem argumento é requerido para instanciar um
objeto desta classe com a reflexão.
+ </para>
+
+ <para>
+ A propriedade <literal>id</literal> mantém um único valor de
identificação para um evento
+ particular. Todas as classes persistentes da entidade (bem como aquelas
classes dependentes
+ de menos importância) precisam de uma propriedade de identificação, caso
nós queiramos usar o
+ conjunto completo de características do Hibernate. De fato, a maioria das
aplicações
+ (esp. aplicações web) precisam destinguir os objetos pelo identificador,
então você deverá
+ considerar esta, uma característica em lugar de uma limitação. Porém, nós
normalmente não
+ manipulamos a identidade de um objeto, consequentemente o método setter
deverá ser privado.
+ O Hibernate somente nomeará os identificadores quando um objeto for
salvo. Você pode ver como
+ o Hibernate pode acessar métodos públicos, privados, e protegidos, como
também campos
+ (públicos, privados, protegidos) diretamente. A escolha está até você, e
você pode combinar
+ isso para adaptar seu projeto de aplicação
+ </para>
+
+ <para>
+ O construtor sem argumentos é um requerimento para todas as classes
persistentes;
+ O Hibernate tem que criar para você os objetos usando Java Reflection. O
construtor
+ pode ser privado, porém, a visibilidade do pacote é requerida para a
procuração da
+ geração em tempo de execução e recuperação eficiente dos dados sem a
instrumentação
+ de bytecode
+ </para>
+
+ <para>
+ Coloque este fonte Java no diretório chamado
<literal>src</literal> na pasta de desenvolvimento,
+ e em seu pacote correto. O diretório deverá ser parecido como este:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java]]></programlisting>
+
+ <para>
+ No próximo passo, iremos falar sobre as classes de persistência do
Hibernate..
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-mapping" revision="1">
+ <title>O mapeamento do arquivo</title>
+
+ <para>
+ O Hibernate precisa saber como carregar e armazenar objetos da classe de
+ persistência. Isto será onde o mapeamento do arquivo do Hibernate entrará
em
+ jogo. O arquivo mapeado informa ao Hibernate, qual tabela no banco de
dados
+ ele deverá acessar, e quais as colunas na tabela ele deverá usar.
+ </para>
+
+ <para>
+ A estrutura básica de um arquivo de mapeamento é parecida com:
+ </para>
+
+ <programlisting><![CDATA[<?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>
+[...]
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Note que o Hibernate DTD é muito sofisticado. Você pode usar isso para
auto-conclusão
+ no mapeamento XML dos elementos e atributos no seu editor ou IDE. Você
também pode
+ abrir o arquivo DTD no seu editor – é a maneira mais fácil de ter uma
visão geral
+ de todos os elementos e atributos e dos padrões, como também alguns
comentários.
+ Note que o Hibernate não irá carregar o arquivo DTD da web, e sim do
diretório
+ da aplicação (classpath). O arquivo DTD está incluído no
<literal>hibernate3.jar</literal> como
+ também no diretório <literal>src/</literal> da distribuição
do Hibernate.
+ </para>
+
+ <para>
+ Nós omitiremos a declaração do DTD nos exemplos futuros para encurtar o
código. Isto, é claro, não é opcional.
+ </para>
+
+ <para>
+ Entre os dois tags <literal>hibernate-mapping</literal>,
inclua um elemento <literal>class</literal>.
+ Todas as classes persistentes da entidade (novamente, poderá haver
+ mais tarde, dependências sobre as classes que não são classes-primárias
+ de entidades) necessitam do tal mapeamento, para uma tabela na base
+ de dados SQL
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Mais adiante iremos dizer ao Hibernate como fazer para persistir e
carregar objetos da classe
+ <literal>Event</literal> da tabela
<literal>EVENTS</literal>, cada instancia representada por
+ uma coluna na tabela. Agora, continuaremos com o mapeamento de uma única
propriedade identificadora
+ para as chaves primárias da tabela. Além disso, nós não iremos se
importar com esta propriedade
+ identificadora, nós iremos configurar uma estratégia de geração de id’s
para uma chave primária
+ de uma surrogate key:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+ <id name="id" column="EVENT_ID">
+ <generator class="native"/>
+ </id>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ O elemento <literal>id</literal> é a declaração da
propriedade identificadora,
+ o <literal>name="id"</literal> declara o nome da
propriedade Java –
+ o Hibernate irá usar os métodos getter e setter para acessar a
propriedade.
+ O atributo da coluna informa ao Hibernate qual coluna da tabela
<literal>EVENTS</literal> nós
+ iremos usar como chave primária. O elemento
<literal>generator</literal> especifica
+ a estratégia de geração do identificador, neste caso usaremos
<literal>native</literal>, que
+ escolhe a melhor estratégia dependendo da base de dados (dialeto)
configurada.
+ O Hibernate suporta a base de dados gerada, globalmente única, bem como a
atribuição
+ aos identificadores da aplicação (ou toda estratégia escrita para uma
extensão).
+ </para>
+
+ <para>
+ Finalmente incluiremos as declarações para as propriedades persistentes
da classe
+ no arquivo mapeado. Por default, nenhuma das propriedades da classe é
considerada persistente:
+ </para>
+
+ <programlisting><![CDATA[
+<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+ <id name="id" column="EVENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="date" type="timestamp"
column="EVENT_DATE"/>
+ <property name="title"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Da mesma maneira que com o elemento <literal>id</literal>, o
atributo <literal>name</literal> do elemento
+ <literal>property</literal> informa ao Hibernate qual método
getter e setter deverá usar.
+ Assim, neste caso, o Hibernate irá procurar pelo
<literal>getDate()/setDate()</literal>,
+ como também pelo <literal>getTitle()/setTitle()</literal>.
+ </para>
+
+ <para>
+ Porque fazer o mapeamento da propriedade
<literal>date</literal> incluído no
+ atributo <literal>column</literal>, e no title não fazer?
+ Sem o atributo <literal>column</literal> o Hibernate por
padrão usa o nome
+ da propriedade como o nome da coluna. Isto trabalha muito
+ bem para o <literal>title</literal>. Entretanto o
<literal>date</literal> é uma palavra-chave reservada
+ na maioria dos bancos de dados, assim nós melhoramos o mapeamentos
+ disto com um nome diferente.
+ </para>
+
+ <para>
+ A próxima coisa interessante é que mapemanto do
<literal>title</literal>
+ também falta o atributo <literal>type</literal>. O tipo que
declaramos e o uso nos
+ arquivos mapeados, não são como você pôde esperar, atributos de dados
Java.
+ Eles não são como os tipos de base de dados SQL.
+ Esses tipos podem ser chamados de <emphasis>Tipos de mapeamento
Hibernate</emphasis>, que são conversores
+ que podem traduzir tipos de dados do Java para os tipos de dados SQL e
vice-versa.
+ Novamente, o Hibernate irá tentar determinar a conversão correta e
mapeará o <literal>type</literal>
+ próprio, caso o tipo do atributo não estiver presente no mapeamento.
+ Em alguns casos, esta detecção automática (que usa Reflection sobre as
classes Java)
+ poderá não ter padrão que você espera ou necessita.
+ Este é o caso com a propriedade <literal>date</literal>. O
Hibernate não pode saber se a propriedade
+ (que é do <literal>java.util.Date</literal>) pode mapear para
uma coluna do tipo <literal>date</literal>
+ do SQL, <literal>timestamp</literal>, ou
<literal>time</literal> .
+ Nós preservamos a informação cheia de datas e horas pelo mapeamento da
propriedade com um conversor
+ <literal>timestamp</literal>.
+ </para>
+
+ <para>
+ Este arquivo de mapeamento deve ser salvo como
<literal>Event.hbm.xml</literal>,
+ corretamente no diretório próximo ao arquivo fonte da Classe Java
<literal>Event</literal>.
+ O nomeamento dos arquivos de mapeamento podem ser arbitrários, porém o
sufixo
+ <literal>hbm.xml</literal> é uma convenção da comunidade dos
desenvolvedores do Hibernate.
+ Esta estrutura do diretório deve agora se parecer com isso:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java
+ Event.hbm.xml]]></programlisting>
+
+ <para>
+ Nós iremos continuar com a configuração principal do Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-configuration"
revision="2">
+ <title>Configuração do Hibernate</title>
+
+ <para>
+ Agora nós temos uma classe persistente e este arquivo de mapeamento no
lugar.
+ Está na hora de configurar o Hibernate. Antes de fazermos isso, iremos
precisar de uma base de dados.
+ O HSQL DB, um SQL DBMS feito em java, pode ser baixado através do site do
HSQL DB.
+ Atualmente, você só precisa baixar o
<literal>hsqldb.jar</literal>.
+ Coloque este arquivo no diretório da pasta de desenvolvimento
<literal>lib/</literal>.
+ </para>
+
+ <para>
+ Crie um diretório chamado <literal>data</literal> no
diretório root de desenvolvimento –
+ Isto será onde o HSQL DB irá armazenar arquivos de dados. Agora iremos
iniciar o banco de dados
+ executando <literal>java -classpath ../lib/hsqldb.jar
org.hsqldb.Server</literal> neste diretório de dados.
+ Você pode ver ele iniciando e conectando ao socket TCP/IP, isto será onde
nossa aplicação irá se
+ conectar depois. Se você deseja iniciar uma nova base de dados durante
este tutorial,
+ finalize o HSQL DB(pressionando o <literal>CTRL + C</literal>
na janela), delete todos os
+ arquivos no diretório <literal>data/</literal>, e inicie o
HSQL BD novamente.
+ </para>
+
+ <para>
+ O Hibernate é uma camada na sua aplicação na qual se conecta com a base
de dados, para isso
+ necessita de informação da conexão. As conexões são feitas através de um
pool de conexão JDBC,
+ na qual teremos que configurar. A distribuição do Hibernate contém
diversas ferramentas de pooling
+ da conexão JDBC de fonte aberta, mas iremos usar o pool de conexão
interna para este tutorial.
+ Note que você tem que copiar a biblioteca necessária em seu classpath e
use configurações
+ diferentes para pooling de conexão caso você deseje utilizar um software
de pooling JDBC terceirizado
+ para qualidade de produção.
+ </para>
+
+ <para>
+ Para as configurações do Hibernate, nós podemos usar um arquivo simples
<literal>hibernate.properties</literal>,
+ um arquivo mais ligeiramente sofisticado
<literal>hibernate.cfg.xml</literal> ou até mesmo uma
+ instalação programática completa. A maioria dos usuários preferem
utilizar o arquivo de configuração XML
+ </para>
+
+ <programlisting><![CDATA[<?xml version='1.0'
encoding='utf-8'?>
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+
+ <session-factory>
+
+ <!-- Database connection settings -->
+ <property
name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property
name="connection.url">jdbc:hsqldb:hsql://localhost</property>
+ <property name="connection.username">sa</property>
+ <property name="connection.password"></property>
+
+ <!-- JDBC connection pool (use the built-in) -->
+ <property name="connection.pool_size">1</property>
+
+ <!-- SQL dialect -->
+ <property
name="dialect">org.hibernate.dialect.HSQLDialect</property>
+
+ <!-- Enable Hibernate's automatic session context management -->
+ <property
name="current_session_context_class">thread</property>
+
+ <!-- Disable the second-level cache -->
+ <property
name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
+
+ <!-- Echo all executed SQL to stdout -->
+ <property name="show_sql">true</property>
+
+ <!-- Drop and re-create the database schema on startup -->
+ <property name="hbm2ddl.auto">create</property>
+
+ <mapping resource="events/Event.hbm.xml"/>
+
+ </session-factory>
+
+</hibernate-configuration>]]></programlisting>
+
+ <para>
+ Note que esta configuração XML usa um diferente DTD. Nós configuraremos
+ as <literal>SessionFactory</literal> do Hibernate – uma
factory global responsável
+ por uma base de dedados particular. Se você tiver diversas bases de
dados,
+ use diversas configurações
<literal><session-factory></literal>, geralmente
+ em diversos arquivos de configuração (para uma partida mais fácil).
+ </para>
+
+ <para>
+ As primeiras quatro <literal>propriedades</literal> do
elemento contém a configuração
+ necessária para a conexão ao JDBC. A propriedade
<literal>propriedade</literal> dialect
+ do elemento especifica a variante particular do SQL que o Hibernate gera.
+ O gerenciamento automático de sessão do Hibernate para contextos de
persistência
+ estará disponível em breve. A opção
<literal>hbm2ddl.auto</literal> habilita a geração
+ automática de schemas da base de dados – diretamente na base de dados.
+ Isto também pode ser naturalmente desligado (removendo a opção de
configuração) ou redirecionando
+ para um arquivo com ajuda do <literal>SchemaExport</literal>
nas tarefas do Ant.
+ Finalmente, iremos adicionar os arquivos das classes de persistência
mapeadas na configuração.
+ </para>
+
+ <para>
+ Copie este arquivo no diretório fonte, assim isto irá terminar na raiz
(root) do
+ classpath. O Hibernate automaticamente procura por um arquivo chamado
+ <literal>hibernate.cfg.xml</literal> na raiz do classpath, no
startup.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-ant" revision="1">
+ <title>Construindo com o Ant</title>
+
+ <para>
+ Nos iremos, agora, construir o tutorial com Ant. Você ira precisar o Ant
instalado –
+ se encontra disponível <ulink
url="http://ant.apache.org/bindownload.cgi">na página de download do
Ant</ulink>.
+ Como instalar o Ant, não será abordado aqui. Caso tenha alguma dúvida,
por favor,
+ vá ao <ulink
url="http://ant.apache.org/manual/index.html">Ant manual</ulink>.
+ Depois que tiver instalado o Ant, podemos começar a criar o arquivo de
construção <literal>build.xml</literal>.
+ Este arquivo será chamado de <literal>build.xml</literal> e
posto diretamente no diretório de desenvolvimento.
+ </para>
+
+ <para>
+ Um arquivo básico de build, se parece com isto:
+ </para>
+
+ <programlisting><![CDATA[<project
name="hibernate-tutorial" default="compile">
+
+ <property name="sourcedir" value="${basedir}/src"/>
+ <property name="targetdir" value="${basedir}/bin"/>
+ <property name="librarydir" value="${basedir}/lib"/>
+
+ <path id="libraries">
+ <fileset dir="${librarydir}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <target name="clean">
+ <delete dir="${targetdir}"/>
+ <mkdir dir="${targetdir}"/>
+ </target>
+
+ <target name="compile" depends="clean, copy-resources">
+ <javac srcdir="${sourcedir}"
+ destdir="${targetdir}"
+ classpathref="libraries"/>
+ </target>
+
+ <target name="copy-resources">
+ <copy todir="${targetdir}">
+ <fileset dir="${sourcedir}">
+ <exclude name="**/*.java"/>
+ </fileset>
+ </copy>
+ </target>
+
+</project>]]></programlisting>
+
+ <para>
+ Isto irá avisar ao Ant para adicionar todos os arquivos no diretório lib
terminando com
+ <literal>.jar</literal>, para o classpath usado para
compilação. Irá também copiar todos os
+ arquivos não-java para o diretório alvo (arquivos de configuração,
mapeamento). Se você rodar
+ o ant agora, deverá ter esta saída.
+ </para>
+
+ <programlisting><![CDATA[C:\hibernateTutorial\>ant
+Buildfile: build.xml
+
+copy-resources:
+ [copy] Copying 2 files to C:\hibernateTutorial\bin
+
+compile:
+ [javac] Compiling 1 source file to C:\hibernateTutorial\bin
+
+BUILD SUCCESSFUL
+Total time: 1 second ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-helpers" revision="3">
+ <title>Startup and helpers</title>
+
+ <para>
+ É hora de carregar e arquivar alguns objetos
<literal>Event</literal>, mas primeiro
+ nós temos de completar o setup com algum código de infraestrutura. Este
startup
+ inclui a construção de um objeto
<literal>SessionFactory</literal> global e armazenar
+ isto em algum lugar de fácil acesso para o código da aplicação.
+ Uma <literal>SessionFactory</literal> pode abrir novas
<literal>Session</literal>'s.
+ Uma <literal>Session</literal> representa uma unidade
single-theaded do trabalho, a
+ <literal>SessionFactory</literal> é um objeto global
thread-safe, instanciado uma vez.
+ </para>
+
+ <para>
+ Nos iremos criar uma classe de ajuda
<literal>HibernateUtil</literal>, que toma
+ conta do startup e faz acesso a uma
<literal>SessionFactory</literal> conveniente.
+ Vamos dar uma olhada na implementação:
+ </para>
+
+ <programlisting><![CDATA[package util;
+
+import org.hibernate.*;
+import org.hibernate.cfg.*;
+
+public class HibernateUtil {
+
+ private static final SessionFactory sessionFactory;
+
+ static {
+ try {
+ // Create the SessionFactory from hibernate.cfg.xml
+ sessionFactory = new Configuration().configure().buildSessionFactory();
+ } catch (Throwable ex) {
+ // Make sure you log the exception, as it might be swallowed
+ System.err.println("Initial SessionFactory creation failed." +
ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public static SessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+
+}]]></programlisting>
+
+ <para>
+ Esta classe não só produz a global
<literal>SessionFactory</literal> no seu static initializer
+ (chamado uma vez pela JVM quando a classe é carregada), mas também
esconde o fato
+ de que isto usa um static singleton. Ela pode muito bem, enxergar a
+ <literal>SessionFactory</literal> do JNDI em um application
server.
+ </para>
+
+ <para>
+ Se você der à <literal>SessionFactory</literal> um nome, no
seu arquivo de configuração.
+ O Hibernate irá, de fato, tentar uni-lo ao JNDI depois que estiver
construído.
+ Para evitar este completamente este código, você também poderia usar JMX
deployment
+ e deixar o contêiner JMX capaz, instanciar e unir um
<literal>HibernateService</literal>
+ no JNDI. Essas opções avançadas são discutidas no documento de referência
do Hibernate.
+ </para>
+
+ <para>
+ Coloque o <literal>HibernateUtil.java</literal> no diretório
de arquivos
+ de desenvolvimento(source), em um pacote após o
<literal>events</literal>:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java
+ Event.hbm.xml
+ +util
+ HibernateUtil.java
+ hibernate.cfg.xml
++data
+build.xml]]></programlisting>
+
+ <para>
+ Novamente, isto deve compilar sem problemas. Finalmente, nós precisamos
configurar
+ um sistema de logging – o Hibernate usa commons logging e deixa você
escolher entre o
+ Log4j e o logging do JDK 1.4 . A maioria dos desenvolvedores preferem o
Log4j: copie
+ <literal>log4j.properties</literal> da distribuição do
Hibernate (está no diretório
+ <literal>etc/</literal>), para seu diretório
<literal>src</literal>,
+ depois vá em hibernate.cfg.xml. Dê uma olhada no exemplo de configuração
e mude as
+ configurações se você quizer ter uma saída mais detalhada. Por default,
apenas as
+ mensagems de startup e shwwn do Hibernate é mostrada no stdout.
+ </para>
+
+ <para>
+ O tutorial de infra-estrutura está completo - e nós já estamos preparados
para algum
+ trabalho de verdade com o Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-workingpersistence"
revision="4">
+ <title>Carregando e salvando objetos</title>
+
+ <para>
+ Finalmente, nós podemos usar o Hibernate para carregar e armazenar
objetos.
+ Nós escrevemos uma classe <literal>EventManager</literal> com
um método main():
+ </para>
+
+ <programlisting><![CDATA[package events;
+import org.hibernate.Session;
+
+import java.util.Date;
+
+import util.HibernateUtil;
+
+public class EventManager {
+
+ public static void main(String[] args) {
+ EventManager mgr = new EventManager();
+
+ if (args[0].equals("store")) {
+ mgr.createAndStoreEvent("My Event", new Date());
+ }
+
+ HibernateUtil.getSessionFactory().close();
+ }
+
+ private void createAndStoreEvent(String title, Date theDate) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+
+ session.beginTransaction();
+
+ Event theEvent = new Event();
+ theEvent.setTitle(title);
+ theEvent.setDate(theDate);
+
+ session.save(theEvent);
+
+ session.getTransaction().commit();
+ }
+
+}]]></programlisting>
+
+ <para>
+ Nós criamos um novo objeto <literal>Event</literal>, e
passamos para o Hibernate.
+ O Hibernate sabe como tomar conta do SQL e executa
<literal>INSERT</literal>s
+ no banco de dados. Vamos dar uma olhada na
<literal>Session</literal> e no
+ código <literal>Transaction</literal>-handling antes de
executarmos.
+ </para>
+
+ <para>
+ Um <literal>Session</literal> é uma unidade simples de
trabalho. Por agora nós
+ iremos pegar coisas simples e assumir uma granularidade de um-pra-um
entre uma
+ <literal>Session</literal> do Hibernate e uma transação de
banco de dados.
+ Para proteger nosso código de um atual sistema subjacente de transação
(nesse
+ caso puro JDBC, mas também poderia rodar com JTA), nos usamos a API
+ <literal>Transaction</literal>, que está disponível na
<literal>Session</literal> do Hibernate.
+ </para>
+
+ <para>
+ O que a <literal>sessionFactory.getCurrentSession()</literal>
faz? Primeiro, você pode
+ chamar quantas vezes e de onde quiser, uma vez você recebe sua
<literal>SessionFactory</literal>
+ (fácil graças ao <literal>HibernateUtil</literal>). O método
<literal>getCurrentSession()</literal>
+ sempre retorna a unidade de trabalho "corrente". Lembra de que
nós mudamos a opção
+ de configuração desse mecanismo para thread no
<literal>hibernate.cfg.xml</literal>? Daqui em
+ diante, o escopo da unidade de trabalho corrente é a thread Java
+ corrente que executa nossa aplicação. Entretanto, esta não é toda a
verdade. Uma
+ <literal>Session</literal> começa quando é primeiramente
necessária, quando é feita a
+ primeira chamada à <literal>getCurrentSession()</literal>. É
então limitado pelo Hibernate
+ para thread corrente. Quando a transação termina, tanto com commit quanto
rollback,
+ o Hibernate também desune a <literal>Session</literal> da
thread e fecha isso pra você.
+ Se você chamar <literal>getCurrentSession()</literal>
novamente, você receberá uma nova
+ <literal>Session</literal> e pode começar uma nova unidade de
trabalho. Esse modelo de
+ programação de limite de thread
<emphasis>thread-bound</emphasis>, é o modo mais popular
+ de se usar o Hibernate.
+ </para>
+
+ <para>
+ Dê uma olhada no <xref linkend="transactions"/> para mais
informações a
+ respeito de manipulação de transação e demarcação. Nós também pulamos
qualquer
+ manipulação de erro e rollback no exemplo anterior.
+ </para>
+
+ <para>
+ Para executar esta primeira rotina, nos teremos que adicionar um ponto de
chamada
+ para o arquivo de build do Ant:
+ </para>
+
+ <programlisting><![CDATA[<target name="run"
depends="compile">
+ <java fork="true" classname="events.EventManager"
classpathref="libraries">
+ <classpath path="${targetdir}"/>
+ <arg value="${action}"/>
+ </java>
+</target>]]></programlisting>
+
+ <para>
+ O valor do argumento <literal>action</literal>, é setado na
linha de comando quando chamando esse ponto:
+ </para>
+
+ <programlisting><![CDATA[C:\hibernateTutorial\>ant run
-Daction=store]]></programlisting>
+
+ <para>
+ Você deverá ver, após a compilação, o startup do Hibernate e, dependendo
da sua
+ configuração, muito log de saída. No final você verá a seguinte linha:
+ </para>
+
+ <programlisting><![CDATA[[java] Hibernate: insert into EVENTS
(EVENT_DATE, title, EVENT_ID) values (?, ?, ?)]]></programlisting>
+
+ <para>
+ Este é o <literal>INSERT</literal> executado pelo Hibernate,
os pontos de interrogação
+ representam parêmetros de união do JDBC. Para ver os valores
substituídos, ou para diminuir a
+ verbalidade do log, check seu
l<literal>log4j.properties</literal>.
+ </para>
+
+ <para>
+ Agora nós gostaríamos de listar os eventos arquivados, então nós
adicionamos uma
+ opção para o método main:
+ </para>
+
+ <programlisting><![CDATA[if (args[0].equals("store")) {
+ mgr.createAndStoreEvent("My Event", new Date());
+}
+else if (args[0].equals("list")) {
+ List events = mgr.listEvents();
+ for (int i = 0; i < events.size(); i++) {
+ Event theEvent = (Event) events.get(i);
+ System.out.println("Event: " + theEvent.getTitle() +
+ " Time: " + theEvent.getDate());
+ }
+}]]></programlisting>
+
+ <para>
+ Nos também adicionamos um novo <literal>método
listEvents()</literal>:
+ </para>
+
+ <programlisting><![CDATA[private List listEvents() {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+
+ session.beginTransaction();
+
+ List result = session.createQuery("from Event").list();
+
+ session.getTransaction().commit();
+
+ return result;
+}]]></programlisting>
+
+ <para>
+ O que nós fazemos aqui, é usar uma query HQL (Hibernate Query Language),
+ para carregar todos os objetos <literal>Event</literal>
exitentes no banco de dados.
+ O Hibernate irá gerar o SQL apropriado, enviar para o banco de dados e
popular objetos
+ <literal>Event</literal> com os dados. Você pode criar
queries mais complexas com
+ HQL, claro.
+ </para>
+
+ <para>
+ Agora, para executar e testar tudo isso, siga os passos a seguir:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Execute <literal>ant run -Daction=store</literal>
para armazenar algo no banco de dados
+ e, claro, gerar o esquema do banco de dados antes pelo hbm2ddl.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Agora desabilite hbm2ddl comentando a propriedade no seu arquivo
<literal>hibernate.cfg.xml</literal>.
+ Normalmente só se deixa habilitado em teste unitários contínuos,
mas outra carga de hbm2ddl
+ pode <emphasis>remover</emphasis> tudo que você já
tenha arquivado. Sa configuração
+ <literal>create</literal>, atualmente são traduzidas
para "apague todas as tabelas do esquema,
+ então recrie todas quando a SessionFactory estiver pronta".
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Se você agora chamar o Ant com
<literal>-Daction=list</literal>, você deverá ver os
+ eventos que você acabou de criar. Você pode também chamar a ação
<literal>store</literal>
+ mais algumas vezes.
+ </para>
+
+ <para>
+ Nota: A maioria dos novos usuários do Hibernate falha nesse ponto e nós
regularmente, vemos
+ questões sobre mensagens de erro de <emphasis>tabela não encontrada
</emphasis> .
+ Entretanto, se você seguir os passos marcados acima, você não terá esse
problema,
+ com o hbm2ddl criando o esquema do banco de dados na primeira execução, e
restarts
+ subsequentes da aplicação irão usar este esquema. Se você mudar o
mapeamento e/ou
+ o esquema do banco de dados, terá de re-habilitar o hbm2ddl mais uma
vez.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="tutorial-associations">
+ <title>Part 2 - Mapeando associações</title>
+
+ <para>
+ Nós mapeamos uma classe de entidade de persistência para uma tabela. Agora
vamos continuar
+ e adicionar algumas associações de classe. Primeiro nos iremos adicionar
pessoas a nossa aplicação,
+ e armazenar os eventos de que elas participam.
+ </para>
+
+ <sect2 id="tutorial-associations-mappinguser"
revision="1">
+ <title>Mapeando a classe Person</title>
+
+ <para>
+ O primeiro código da classe <literal>Person</literal> é
simples:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+public class Person {
+
+ private Long id;
+ private int age;
+ private String firstname;
+ private String lastname;
+
+ public Person() {}
+
+ // Accessor methods for all properties, private setter for 'id'
+
+}]]></programlisting>
+
+ <para>
+ Crie um novo arquivo de mapeamento, chamado
<literal>Person.hbm.xml</literal> (não
+ esqueça a referencia ao DTD no topo)
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Person" table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="native"/>
+ </id>
+ <property name="age"/>
+ <property name="firstname"/>
+ <property name="lastname"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Finalmente, adicione o novo mapeamento a configuração do Hibernate:
+ </para>
+
+ <programlisting><![CDATA[<mapping
resource="events/Event.hbm.xml"/>
+<mapping resource="events/Person.hbm.xml"/>]]></programlisting>
+
+ <para>
+ Nos iremos agora criar uma associação entre estas duas entidades.
Obviamente,
+ pessoas (Person) podem participar de eventos, e eventos possuem
participantes.
+ As questões de design com que teremos de lidar são: direcionalidade,
multiplicidade e
+ comportamento de coleção.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-unidirset"
revision="3">
+ <title>Uma associação Set-based unidirectional</title>
+
+ <para>
+ Nos iremos adicionar uma coleção de eventos na classe
<literal>Person</literal>. Desse jeito
+ poderemos navegar pelos eventos de uma pessoa em particular, sem executar
uma query explicitamente –
+ apenas chamando <literal>aPerson.getEvents()</literal>. Nos
usaremos uma coleção Java, um
+ <literal>Set</literal>, porquê a coleção não conterá
elementos duplicados e a ordem não é
+ relevante para nós.
+ </para>
+
+ <para>
+ Vamos escrever o código para isto nas classes Java e então mapear:
+ </para>
+
+ <programlisting><![CDATA[public class Person {
+
+ private Set events = new HashSet();
+
+ public Set getEvents() {
+ return events;
+ }
+
+ public void setEvents(Set events) {
+ this.events = events;
+ }
+}]]></programlisting>
+
+ <para>
+ Antes de mapearmos esta associação, pense no outro lado. Claramente,
poderíamos apenas fazer isto de
+ forma unidirecional. Ou poderíamos criar outra coleção no
<literal>Event</literal>, se quisermos
+ ser capaz de navegar bidirecionalmente, i.e. um -
<literal>anEvent.getParticipants()</literal>.
+ Isto não é necessário, de perspectiva funcional. Você poderia sempre
executar uma query explicita
+ que retornasse os participantes de um evento em particular. Esta é uma
escolha de design que cabe
+ a você, mas o que é claro nessa discussão é a multiplicidade da
associação: "muitos" valores em ambos
+ os lados, nós chamamos isto uma associação
<emphasis>muitos-para-muitos</emphasis>. Daqui pra frente,
+ nos usaremos o mapeamento muitos-para-muitos do Hibernate:
+ </para>
+
+ <programlisting><![CDATA[<class name="events.Person"
table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="native"/>
+ </id>
+ <property name="age"/>
+ <property name="firstname"/>
+ <property name="lastname"/>
+
+ <set name="events" table="PERSON_EVENT">
+ <key column="PERSON_ID"/>
+ <many-to-many column="EVENT_ID" class="events.Event"/>
+ </set>
+
+</class>]]></programlisting>
+
+ <para>
+ O Hibernate suporta todo tipo de mapeamento de coleção , sendo um
<literal><set></literal> mais comum.
+ Para uma associação muitos-para-muitos (ou relacionamento de entidade
<emphasis>n:m</emphasis> ),
+ uma tabela de associação é necessária. Cada linha nessa tabela representa
um link entre uma pessoa e um
+ evento. O nome da tabela é configurado com o atributo
<literal>table</literal> do elemento
+ <literal>set</literal>. O nome da coluna identificadora na
associção, peloo lado da pessoa,
+ é definido com o elemento
<literal><key></literal> , o nome da coluna pelo lado dos
eventos,
+ e definido com o atributo <literal>column</literal> do
<literal><many-to-many></literal>.
+ Você também precisa dizer para o Hibernate a classe dos objetos na sua
coleção (a classe do outro
+ lado das coleções de referência).
+ </para>
+
+ <para>
+ O esquema de mapeamento para o banco de dados está a seguir:
+ </para>
+
+ <programlisting><![CDATA[
+ _____________ __________________
+ | | | | _____________
+ | EVENTS | | PERSON_EVENT | | |
+ |_____________| |__________________| | PERSON |
+ | | | | |_____________|
+ | *EVENT_ID | <--> | *EVENT_ID | | |
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |
+ | TITLE | |__________________| | AGE |
+ |_____________| | FIRSTNAME |
+ | LASTNAME |
+ |_____________|
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-working"
revision="1">
+ <title>Trabalhando a associação</title>
+
+ <para>
+ Vamos trazer juntos algumas pessoas e eventos em um novo método na classe
<literal>EventManager</literal>::
+ </para>
+
+ <programlisting><![CDATA[private void addPersonToEvent(Long
personId, Long eventId) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session.load(Person.class, personId);
+ Event anEvent = (Event) session.load(Event.class, eventId);
+
+ aPerson.getEvents().add(anEvent);
+
+ session.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ Após carregar um <literal>Person</literal> e um
<literal>Event</literal>, simplesmente
+ modifique a coleção usando os métodos normais de uma coleção. Como você
pode ver, não há chamada explícita
+ para <literal>update()</literal> ou
<literal>save()</literal>, o Hibernate detecta automaticamente
+ que a coleção foi modificada e necessita ser atualizada. Isso é chamado
de <emphasis>checagem
+ suja automática</emphasis>, e você também pode usá-la modificando o
nome ou a data de qualquer um dos
+ seus objetos. Assim que eles estiverem no estado
<emphasis>persistent</emphasis>, ou seja,
+ limitado por uma <literal>Session</literal> do Hibernate em
particular (i.e. eles foram carregados ou
+ salvos dentro de uma unidade de trabalho), o Hibernate monitora qualquer
alteração e executa o SQL
+ em modo de escrita em segundo plano. O processo de sincronização do
estado da memória com o banco de
+ dados, geralmente apenas no final de uma unidade de trabalho, é chamado
de <emphasis>flushing</emphasis>.
+ No nosso código, a unidade de trabalho termina com o commit da transação
do banco de dados –
+ como definido pela opção de configuração da
<literal>thread</literal> da classe
<literal>CurrentSessionContext</literal>.
+ </para>
+
+ <para>
+ Você pode também querer carregar pessoas e eventos em diferentes unidades
de trabalho.
+ Ou você modifica um objeto fora de uma
<literal>Session</literal>, quando não se encontra no
+ estado persistent (se já esteve neste estado anteriormente, chamamos esse
estado de
+ <emphasis>detached</emphasis>). Você pode até mesmo modificar
uma coleção quando esta
+ se encontrar no estado detached.
+ </para>
+
+ <programlisting><![CDATA[private void addPersonToEvent(Long
personId, Long eventId) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session
+ .createQuery("select p from Person p left join fetch p.events where p.id
= :pid")
+ .setParameter("pid", personId)
+ .uniqueResult(); // Eager fetch the collection so we can use it detached
+
+ Event anEvent = (Event) session.load(Event.class, eventId);
+
+ session.getTransaction().commit();
+
+ // End of first unit of work
+
+ aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
+
+ // Begin second unit of work
+
+ Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
+ session2.beginTransaction();
+
+ session2.update(aPerson); // Reattachment of aPerson
+
+ session2.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ A chamada <literal>update</literal> cria um objeto persistent
novamente, você poderia
+ dizer que ele liga o objeto a uma nova unidade de trabalho, assim
qualquer modificação
+ que você faça neste objeto enquanto estiver no estado detached pode ser
salvo no banco de dados.
+ Isso inclui qualquer modificação (adição/exclusão) que você faça em uma
coleção da entidade deste objeto.
+ </para>
+
+ <para>
+ Bom, isso não foi muito usado na nossa situação, porém, é um importante
conceito que você
+ pode aplicar em seus aplicativos. Agora, complete este exercício
adicionando uma nova ação
+ ao método main( ) da classe <literal>EventManager</literal>
e chame-o pela linha de comando.
+ Se você precisar dos identificadores de uma pessoa ou evento – o método
<literal>save()</literal>
+ retorna estes identificadores (você poderá modificar alguns dos métodos
anteriores para retornar aquele
+ identificador):
+ </para>
+
+ <programlisting><![CDATA[else if
(args[0].equals("addpersontoevent")) {
+ Long eventId = mgr.createAndStoreEvent("My Event", new Date());
+ Long personId = mgr.createAndStorePerson("Foo", "Bar");
+ mgr.addPersonToEvent(personId, eventId);
+ System.out.println("Added person " + personId + " to event " +
eventId);]]></programlisting>
+
+ <para>
+ Este foi um exemplo de uma associação entre duas classes igualmente
importantes, duas entidades.
+ Como mencionado anteriormente, há outras classes e tipos dentro de um
modelo típico,
+ geralmente "menos importante". Alguns você já viu, como um
<literal>int</literal> ou uma <literal>String</literal>.
+ Nós chamamos essas classes de <emphasis>value
types</emphasis>, e suas instâncias <emphasis>depend</emphasis>
+ de uma entidade particular. As instâncias desses tipos não possuem sua
própria identidade, nem são
+ compartilhados entre entidades (duas pessoas não referenciam o mesmo
objeto <literal>firstname</literal>
+ mesmo se elas tiverem o mesmo objeto firstname). Naturalmente, os value
types não são apenas encontrados
+ dentro da JDK (de fato, em um aplicativo Hibernate todas as classes JDK
são consideradas como value types),
+ mas você pode também criar suas classes como, por exemplo,
<literal>Address</literal> ou <literal>MonetaryAmount</literal>.
+
+ </para>
+
+ <para>
+ Você também pode criar uma coleção de value types. Isso é conceitualmente
muito diferente
+ de uma coleção de referências para outras entidades, mas em Java parece
ser quase a mesma coisa.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-valuecollections">
+ <title>Coleção de valores</title>
+
+ <para>
+ Nós adicionamos uma coleção de objetos de tipo de valores à entidade
<literal>Person</literal>.
+ Nós querermos armazenar endereços de e-mail, para isso utilizamos o tipo
<literal>String</literal>,
+ e a coleção novamente será um <literal>Set</literal>:
+ </para>
+ <programlisting><![CDATA[private Set emailAddresses = new
HashSet();
+
+public Set getEmailAddresses() {
+ return emailAddresses;
+}
+
+public void setEmailAddresses(Set emailAddresses) {
+ this.emailAddresses = emailAddresses;
+}]]></programlisting>
+
+ <para>
+ O mapeamento deste <literal>Set</literal>:
+ </para>
+
+ <programlisting><![CDATA[<set name="emailAddresses"
table="PERSON_EMAIL_ADDR">
+ <key column="PERSON_ID"/>
+ <element type="string" column="EMAIL_ADDR"/>
+</set>]]></programlisting>
+
+ <para>
+ A diferença comparada com o mapeamento anterior se encontra na parte
<literal>element</literal>,
+ que indica ao Hibernate que a coleção não contém referências à outra
entidade, mas uma coleção de
+ elementos do tipo <literal>String</literal> (a tag name em
miniscula indica que se trata de um
+ mapeamento do Hibernate para conversão de tipos). Mais uma vez, o
atributo <literal>table</literal>
+ do elemento <literal>set</literal> determina o nome da tabela
para a coleção. O elemento
+ <literal>key</literal> define o nome da coluna de chave
estrangeira na tabela de coleção.
+ O atributo <literal>column</literal> dentro do elemento
<literal>element</literal> define o
+ nome da coluna onde os valores da <literal>String</literal>
serão armazenados.
+ </para>
+
+ <para>
+ Dê uma olhada no esquema atualizado:
+ </para>
+
+ <programlisting><![CDATA[
+ _____________ __________________
+ | | | | _____________
+ | EVENTS | | PERSON_EVENT | | |
___________________
+ |_____________| |__________________| | PERSON | |
|
+ | | | | |_____________| | PERSON_EMAIL_ADDR
|
+ | *EVENT_ID | <--> | *EVENT_ID | | |
|___________________|
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> |
*PERSON_ID |
+ | TITLE | |__________________| | AGE | | *EMAIL_ADDR
|
+ |_____________| | FIRSTNAME |
|___________________|
+ | LASTNAME |
+ |_____________|
+ ]]></programlisting>
+
+ <para>
+ Você pode observar que a chave primária da tabela da coleção é de na
verdade uma chave composta,
+ usando ambas colunas. Isso também implica que cada pessoa não pode ter
endereços de e-mail
+ duplicados, o que é exatamente a semântica que precisamos para um set em
Java.
+ </para>
+
+ <para>
+ Você pode agora tentar adicionar elementos a essa coleção, do mesmo modo
que fizemos
+ anteriormente ligando pessoas e eventos. È o mesmo código em Java:
+ </para>
+
+ <programlisting><![CDATA[private void addEmailToPerson(Long
personId, String emailAddress) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session.load(Person.class, personId);
+
+ // The getEmailAddresses() might trigger a lazy load of the collection
+ aPerson.getEmailAddresses().add(emailAddress);
+
+ session.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ This time we didnt' use a <emphasis>fetch</emphasis>
query to initialize the collection.
+ Hence, the call to its getter method will trigger an additional select to
initialize
+ it, so we can add an element to it. Monitor the SQL log and try to
optimize this with
+ an eager fetch.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-bidirectional"
revision="1">
+ <title>Associações bidirecionais</title>
+
+ <para>
+ Agora iremos mapear uma associação bidirecional – fazendo a associação
entre pessoas e
+ eventos, de ambos os lados, em Java. Logicamente, o esquema do banco de
dados não muda,
+ nós continuamos tendo multiplicidades muitos-para-muitos. Um banco de
dados é mais flexível do que
+ uma linguagem de programação para redes, ele não precisa de nenhuma
direção de navegação – os
+ dados podem ser acessados em qualquer caminho possível.
+ </para>
+
+ <para>
+ Primeiramente, adicione uma coleção de participantes à classe
<literal>Event</literal>:
+ </para>
+
+ <programlisting><![CDATA[private Set participants = new HashSet();
+
+public Set getParticipants() {
+ return participants;
+}
+
+public void setParticipants(Set participants) {
+ this.participants = participants;
+}]]></programlisting>
+
+ <para>
+ Agora mapeie este lado da associação em
<literal>Event.hbm.xml</literal>.
+ </para>
+
+ <programlisting><![CDATA[<set name="participants"
table="PERSON_EVENT" inverse="true">
+ <key column="EVENT_ID"/>
+ <many-to-many column="PERSON_ID" class="events.Person"/>
+</set>]]></programlisting>
+
+ <para>
+ Como você pode ver, esses é uma mapeamento normal usando
<literal>set</literal> em ambos documenentos
+ de mapeamento. Observe que o nome das colunas em
<literal>key</literal> e <literal>many-to-many</literal>
+ estão trocados em ambos os documentos de mapeamento. A adição mais
importante feita está no atributo
+ <literal>inverse="true"</literal> no elemento set
do mapeamento da coleção da classe <literal>Event</literal>.
+ </para>
+
+ <para>
+ Isso significa que o Hibernate deve pegar o outro lado – a classe
<literal>Person</literal> –
+ quando necessitar encontrar informação sobre a relação entre as duas
entidades. Isso será muito
+ mais facilmente compreendido quando você analisar como a relação
bidirecional entre as entidades é criada.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-usingbidir">
+ <title>Trabalhando com links bidirecionais</title>
+
+ <para>
+ Primeiro tenha em mente que o Hibernate não afeta a semântica normal do
Java. Como nós criamos
+ um link entre uma <literal>Person</literal> e um
<literal>Event</literal> no exemplo unidirecional?
+ Nós adicionamos uma instância de <literal>Event</literal>, da
coleção de referências de eventos,
+ a uma instância de <literal>Person</literal>. Então,
obviamente, se nós queremos que este link funcione
+ bidirecionalmente, nós devemos fazer a mesma coisa para o outro lado –
adicionando uma referência de
+ <literal>Person</literal> na coleção de um
<literal>Event</literal>. Esse acerto de link de ambos
+ os lados é absolutamente necessário e você nunca deve esquecer de
faze-lo.
+ </para>
+
+ <para>
+ Muitos desenvolvedores programam de maneira defensiva e criam métodos
+ gerenciador de associações que ajusta corretamente ambos os lados:
+ </para>
+
+ <programlisting><![CDATA[protected Set getEvents() {
+ return events;
+}
+
+protected void setEvents(Set events) {
+ this.events = events;
+}
+
+public void addToEvent(Event event) {
+ this.getEvents().add(event);
+ event.getParticipants().add(this);
+}
+
+public void removeFromEvent(Event event) {
+ this.getEvents().remove(event);
+ event.getParticipants().remove(this);
+}]]></programlisting>
+
+ <para>
+ Observe que os métodos set e get da a coleção estão protegidos – isso
permite que classes e
+ subclasses do mesmo pacote continuem acessando os métodos, mas previne
que qualquer outra classe,
+ que não esteja no mesmo pacote, acesse a coleção diretamente. Você
provavelmente deve fazer a mesma
+ coisa para a coleção do outro lado.
+ </para>
+
+ <para>
+ E sobre o mapeamento do atributo <literal>inverse</literal>?
Pra você, e para o Java, um link bidirecional
+ é simplesmente o fato de ajustar corretamente as referências de ambos os
lados. O Hibernate, entretanto
+ não possui informação necessária para corretamente adaptar os estados
<literal>INSERT</literal> e
+ <literal>UPDATE</literal> do SQL, e precisa de ajuda para
manipular as propriedades das associações
+ bidirecionais. Fazer um lado da associação com o atributo
<literal>inverse</literal> instrui o Hibernate
+ para basicamente ignora-lo, considerando-o uma
<emphasis>cópia</emphasis> do outro lado. Isso é todo o
+ necessário para o Hibernate trabalhar com todas as possibilidades quando
transformando um modelo de
+ navegação bidirecional em esquema de banco de dados do SQL. As regras que
você possui para lembrar são
+ diretas: Todas associações bidirecionais necessitam que um lado possua o
atributo inverse. Em uma
+ associação de um-para-muitos, o lado de "muitos" deve conter o
atributo <literal>inverse</literal>,
+ já em uma associação de muitos-para-muitos você pode pegar qualquer lado,
não há diferença.
+ </para>
+
+ </sect2>
+
+ <para>
+ Agora, vamos portar este exemplo para um pequeno aplicativo para internet.
+
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-webapp">
+ <title>EventManager um aplicativo para internet</title>
+
+ <para>
+ Um aplicativo para internet do Hibernate usa uma
<literal>Session</literal> e uma <literal>Transaction</literal>
+ quase do mesmo modo que um aplicativo standalone. Entretanto, alguns patterns
comuns são úteis.
+ Nós agora criaremos um <literal>EventManagerServlet</literal>.
Esse servlet lista todos os eventos
+ salvos no banco de dados, e cria um formulário HTML para entrada de novos
eventos.
+ </para>
+
+ <sect2 id="tutorial-webapp-servlet" revision="1">
+ <title>Criando um servlet básico</title>
+
+ <para>
+ Crie uma nova classe no seu diretório fonte, no pacote
<literal>events</literal>:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+// Imports
+
+public class EventManagerServlet extends HttpServlet {
+
+ // Servlet code
+}]]></programlisting>
+
+ <para>
+ O servlet manuseia somente requisições <literal>GET</literal>
do HTTP,
+ portanto o método que iremos implementar é
<literal>doGet()</literal>:
+ </para>
+
+ <programlisting><![CDATA[protected void doGet(HttpServletRequest
request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+
+ SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
+
+ try {
+ // Begin unit of work
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().beginTransaction();
+
+ // Process request and render page...
+
+ // End unit of work
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().getTransaction().commit();
+
+ } catch (Exception ex) {
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().getTransaction().rollback();
+ throw new ServletException(ex);
+ }
+
+}]]></programlisting>
+
+ <para>
+ O pattern que estamos aplicando neste código é chamado
<emphasis>session-per-request</emphasis>.
+ Quando uma requisição chega ao servlet, uma nova
<literal>Session</literal> do Hibernate é
+ aberta através da primeira chamada para
<literal>getCurrentSession()</literal> em
+ <literal>SessionFactory</literal>. Então uma transação do
banco de dados é inicializada -
+ todo acesso a dados deve ocorrer dentro de uma transação, não importando
se o dado é de leitura ou escrita.
+ (nós não devemos usar o modo auto-commit em aplicações).
+
+ </para>
+
+ <para>
+ Agora, as possibilidades de ações de uma requisição serão processadas e
uma resposta HTML será renderizada.
+ Nós já iremos chegar nesta parte.
+ </para>
+
+ <para>
+ Finalmente, a unidade de trabalho termina quando o processamento e a
restituição são completados.
+ Se ocorrer algum erro durante o processamento ou a restituição, uma
exceção será lançada e a
+ transação do banco de dados encerrada. Isso completa o pattern
<literal>session-per-request</literal>.
+ Em vez de usar código de demarcação de transação em todo servlet você
pode também criar um filtro servlet.
+ Dê uma olhada no site do Hibernate e do Wiki para maiores informações
sobre esse pattern,
+ chamado <emphasis>Open Session in View</emphasis>.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-webapp-processing" revision="1">
+ <title>Processando e renderizando</title>
+
+ <para>
+ Vamos implementar o processamento da requisição e a restituição da página
HTML.
+ </para>
+
+<programlisting><![CDATA[// Write HTML header
+PrintWriter out = response.getWriter();
+out.println("<html><head><title>Event
Manager</title></head><body>");
+
+// Handle actions
+if ( "store".equals(request.getParameter("action")) ) {
+
+ String eventTitle = request.getParameter("eventTitle");
+ String eventDate = request.getParameter("eventDate");
+
+ if ( "".equals(eventTitle) || "".equals(eventDate) ) {
+ out.println("<b><i>Please enter event title and
date.</i></b>");
+ } else {
+ createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
+ out.println("<b><i>Added event.</i></b>");
+ }
+}
+
+// Print page
+printEventForm(out);
+listEvents(out, dateFormatter);
+
+// Write HTML footer
+out.println("</body></html>");
+out.flush();
+out.close();]]></programlisting>
+
+ <para>
+ O estilo de código acima, misturando linguagem HTML e Java não será
funcional em um aplicativo
+ mais complexo—tenha em mente que neste manual nós estamos
apenas ilustrando conceitos
+ básicos do Hibernate. O código imprime um cabeçalho HTML e um rodapé.
Dentro desta página,
+ é mostrado um formulário em HTML, para entrada de novos eventos, e uma
lista de todos
+ os eventos contidos no banco de dados. O primeiro método é trivial e
apenas imprime
+ uma página HTML:
+ </para>
+
+ <programlisting><![CDATA[private void printEventForm(PrintWriter
out) {
+ out.println("<h2>Add new event:</h2>");
+ out.println("<form>");
+ out.println("Title: <input name='eventTitle'
length='50'/><br/>");
+ out.println("Date (e.g. 24.12.2009): <input name='eventDate'
length='10'/><br/>");
+ out.println("<input type='submit' name='action'
value='store'/>");
+ out.println("</form>");
+}]]></programlisting>
+
+ <para>
+ O método <literal>listEvents()</literal> usa a
<literal>Session</literal> do Hibernate
+ associada a thread atual para executar um query:
+ </para>
+
+ <programlisting><![CDATA[private void listEvents(PrintWriter out,
SimpleDateFormat dateFormatter) {
+
+ List result = HibernateUtil.getSessionFactory()
+ .getCurrentSession().createCriteria(Event.class).list();
+ if (result.size() > 0) {
+ out.println("<h2>Events in database:</h2>");
+ out.println("<table border='1'>");
+ out.println("<tr>");
+ out.println("<th>Event title</th>");
+ out.println("<th>Event date</th>");
+ out.println("</tr>");
+ for (Iterator it = result.iterator(); it.hasNext();) {
+ Event event = (Event) it.next();
+ out.println("<tr>");
+ out.println("<td>" + event.getTitle() +
"</td>");
+ out.println("<td>" + dateFormatter.format(event.getDate()) +
"</td>");
+ out.println("</tr>");
+ }
+ out.println("</table>");
+ }
+}]]></programlisting>
+
+ <para>
+ Finalmente, a action <literal>store</literal> é passada pra o
método
+ <literal>createAndStoreEvent()</literal>, que também usa a
+ <literal>Session</literal> da thread atual:
+ </para>
+
+ <programlisting><![CDATA[protected void createAndStoreEvent(String
title, Date theDate) {
+ Event theEvent = new Event();
+ theEvent.setTitle(title);
+ theEvent.setDate(theDate);
+
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().save(theEvent);
+}]]></programlisting>
+
+ <para>
+ Pronto, o servlet está completo. Uma requisição para o servlet será
processada
+ em uma <literal>Session</literal> e uma
<literal>Transaction</literal> simples.
+ Como anteriormente, no aplicativo standalone, o Hibernate pode
automaticamente
+ associar esses objetos a thread atual em execução. Isso possibilita a
liberdade
+ de você modelar seu código e acessar o método
<literal>SessionFactory</literal>
+ do jeito que achar melhor. Geralmente você irá usar um design mais
sofisticado
+ e mover o código de acesso a dados para dentro de objetos de acesso a
dados
+ (o patter DAO). Leia o Hibernate Wiki para maiores exemplos.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-webapp-deploy">
+ <title>Instalando e testando</title>
+
+ <para>
+ Para fazer o deploy desta aplicação você tem que criar um arquivo para
web, um WAR.
+ Adicione o alvo Ant abaixo em seu
<literal>build.xml</literal>:
+ </para>
+
+<programlisting><![CDATA[<target name="war"
depends="compile">
+ <war destfile="hibernate-tutorial.war" webxml="web.xml">
+ <lib dir="${librarydir}">
+ <exclude name="jsdk*.jar"/>
+ </lib>
+
+ <classes dir="${targetdir}"/>
+ </war>
+</target>]]></programlisting>
+
+ <para>
+ Esta target cria um arquivo chamado
<literal>hibernate-tutorial.war</literal>
+ no diretório do seu projeto. Ele empacota todas as bibliotecas e o
arquivo de
+ descrição <literal>web.xml</literal>, o qual é esperado no
diretório base do seu projeto:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"
encoding="UTF-8"?>
+<web-app version="2.4"
+
xmlns="http://java.sun.com/xml/ns/j2ee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+ <servlet>
+ <servlet-name>Event Manager</servlet-name>
+ <servlet-class>events.EventManagerServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Event Manager</servlet-name>
+ <url-pattern>/eventmanager</url-pattern>
+ </servlet-mapping>
+</web-app>]]></programlisting>
+
+ <para>
+ Antes de você compilar e fazer o deploy desta aplicação web, note que uma
biblioteca
+ adicional é requerida: <literal>jsdk.jar</literal>. Esse é o
Java servlet development kit,
+ se você não possui esta biblioteca, faça seu download na página da Sun e
copie-a
+ para seu diretório de bibliotecas. Entretanto, será usado somente para a
compilação e
+ excluído do pacote WAR.
+ </para>
+
+ <para>
+ Para compilar e instalar execute <literal>ant war</literal>
no seu diretório do projeto
+ e copie o arquivo <literal>hibernate-tutorial.war</literal>
para o diretório
+ <literal>webapp</literal> do Tomcat. Se você não possui o
Tomcat instalado faça
+ o download e siga as instruções de instalação. Você não precisa modificar
+ nenhuma configuração do Tomcat para rodar este aplicativo.
+ </para>
+
+ <para>
+ Uma vez feito o deploy e com Tomcat rodando, acesse o aplicativo em
+
<literal>http://localhost:8080/hibernate-tutorial/eventmanager</literal>.
+ Veja o log do Tomcat para observar a inicialização do Hibernate quando a
+ primeira requisição chega ao servlet (o inicializador estático dentro de
+ <literal>HibernateUtil</literal> é chamado) e para ter uma
depuração
+ detalhada se ocorrer alguma exceção.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="tutorial-summary" revision="1">
+ <title>Sumário</title>
+
+ <para>
+ Este manual cobriu os princípios básicos para criação de uma aplicação
simples do Hibernate
+ e uma pequena aplicação web.
+ </para>
+
+ <para>
+ Se você já se sente seguro com o Hibernate, continue navegando na
documentação de referência
+ por tópicos que você acha interessante – os tópicos mais questionados são:
+ processo de transação (<xref linkend="transactions"/>), uso
da API (<xref linkend="objectstate"/>)
+ e características de consulta (<xref
linkend="objectstate-querying"/>).
+ </para>
+
+ <para>
+ Não esqueça de visitar o site do Hibernate para obter mais tutoriais
especializados.
+ </para>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/tutorial.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/tutorial1.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/tutorial1.xml 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/tutorial1.xml 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,1544 @@
+<chapter id="tutorial">
+ <title>Introdução ao Hibernate</title>
+
+ <sect1 id="tutorial-intro" revision="1">
+ <title>Prefácio</title>
+
+ <para>
+ Este capítulo é um tutorial introdutório
para novos usuários do Hibernate. Nós iniciaremos com uma simples
linha de comando em uma aplicação usando uma base de dados em
memória tornando isto um passo de fácil de compreender.
+ </para>
+
+ <para>
+ Este tutorial é voltado para novos usuários do
Hibernate, mas requer um conhecimento de Java e SQL. Este tutorial é baseado no
tutorial de Michael Gloegl, as bibliotecas Third Party foram nomeadas para JDK 1.4 e 5.0.
Você pode precisar de outras bibliotecas para JDK 1.3.
+ </para>
+
+ <para>
+ O código fonte para o tutorial está incluído no diretório da distribuição
+ <literal>doc/reference/tutorial/</literal>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-firstapp" revision="2">
+ <title>Parte 1 – A primeira aplicação Hibernate</title>
+
+ <para>
+ Primeiro, iremos criar uma simples aplicação Hibernate
baseada em console. Usaremos uma base de dados Java (HSQL DB), então
não teremos que instalar nenhum servidor de base de dados.
+ </para>
+
+ <para>
+ Vamos supor que precisemos de uma aplicação com um
banco de dados pequeno que possa armazenar e atender os eventos que queremos, e as
informaççes sobre os hosts destes eventos.
+ </para>
+
+ <para>
+ A primeira coisa que devemos fazer é configurar nosso
diretório de desenvolvimento,
+ e colocar todas as bibliotecas Java que precisamos dentro dele.
Faça o download da
+ distribuição do Hibernate no site do Hibernate.
Descompacte o pacote e coloque todas
+ as bibliotecas necessárias encontradas no diretório
<literal>/lib</literal>, dentro do
+ diretório <literal>/lib</literal> do seu novo projeto.
Você deverá ter algo parecido
+ com isso:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ antlr.jar
+ cglib.jar
+ asm.jar
+ asm-attrs.jars
+ commons-collections.jar
+ commons-logging.jar
+ hibernate3.jar
+ jta.jar
+ dom4j.jar
+ log4j.jar ]]></programlisting>
+
+ <para>
+ Esta é a configuração mínima
requerida das bibliotecas (observe que também foi copiado
+ o hibernate3.jar da pasta principal do Hibernate) para o Hibernate
<emphasis>na hora do desenvolvimento</emphasis>. O Hibernate permite que você
utilize mais ou menos bibliotecas.
+ Veja o arquivo <literal>README.txt</literal> no
diretório <literal>lib/</literal> da
distribuição
+ do Hibernate para maiores informaççes sobre bibliotecas
requeridas e opcionais.
+ (Atualmente, a biblioteca Log4j não é requerida, mas
é preferida por muitos desenvolvedores.)
+ </para>
+
+ <para>
+ Agora, iremos criar uma classe que representa o evento que queremos armazenar
na base de dados..
+ </para>
+
+ <sect2 id="tutorial-firstapp-firstclass" revision="1">
+ <title>A primeira Classe</title>
+
+ <para>
+ Nossa primeira classe de persistência é uma simples classe JavaBean com
algumas propriedades:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+import java.util.Date;
+
+public class Event {
+ private Long id;
+
+ private String title;
+ private Date date;
+
+ public Event() {}
+
+ public Long getId() {
+ return id;
+ }
+
+ private void setId(Long id) {
+ this.id = id;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date date) {
+ this.date = date;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+}]]></programlisting>
+
+ <para>
+ Você pode ver que esta classe usa o padrão JavaBean para o nomeamento
convencional da propriedade getter e dos métodos setter, como também a visibilidade
private dos campos. Este é um padrão de projeto recomendado, mas não requerido. O
Hibernate pode também acessar campos diretamente, o benefício para os métodos de acesso é
a robustez para o Refactoring. O construtor sem argumento é requerido para instanciar um
objeto desta classe com a reflexão.
+ </para>
+
+ <para>
+ A propriedade <literal>id</literal> mantém um único valor de
identificação para um evento
+ particular. Todas as classes persistentes da entidade (bem como aquelas
classes dependentes
+ de menos importância) precisam de uma propriedade de identificação, caso
nós queiramos usar o
+ conjunto completo de características do Hibernate. De fato, a maioria das
aplicações
+ (esp. aplicações web) precisam destinguir os objetos pelo identificador,
então você deverá
+ considerar esta, uma característica em lugar de uma limitação. Porém, nós
normalmente não
+ manipulamos a identidade de um objeto, consequentemente o método setter
deverá ser privado.
+ O Hibernate somente nomeará os identificadores quando um objeto for
salvo. Você pode ver como
+ o Hibernate pode acessar métodos públicos, privados, e protegidos, como
também campos
+ (públicos, privados, protegidos) diretamente. A escolha está até você, e
você pode combinar
+ isso para adaptar seu projeto de aplicação
+ </para>
+
+ <para>
+ O construtor sem argumentos é um requerimento para todas as classes
persistentes;
+ O Hibernate tem que criar para você os objetos usando Java Reflection. O
construtor
+ pode ser privado, porém, a visibilidade do pacote é requerida para a
procuração da
+ geração em tempo de execução e recuperação eficiente dos dados sem a
instrumentação
+ de bytecode
+ </para>
+
+ <para>
+ Coloque este fonte Java no diretório chamado
<literal>src</literal> na pasta de desenvolvimento,
+ e em seu pacote correto. O diretório deverá ser parecido como este:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java]]></programlisting>
+
+ <para>
+ No próximo passo, iremos falar sobre as classes de persistência do
Hibernate..
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-mapping" revision="1">
+ <title>O mapeamento do arquivo</title>
+
+ <para>
+ O Hibernate precisa saber como carregar e armazenar objetos da classe de
+ persistência. Isto será onde o mapeamento do arquivo do Hibernate entrará
em
+ jogo. O arquivo mapeado informa ao Hibernate, qual tabela no banco de
dados
+ ele deverá acessar, e quais as colunas na tabela ele deverá usar.
+ </para>
+
+ <para>
+ A estrutura básica de um arquivo de mapeamento é parecida com:
+ </para>
+
+ <programlisting><![CDATA[<?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>
+[...]
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Note que o Hibernate DTD é muito sofisticado. Você pode usar isso para
auto-conclusão
+ no mapeamento XML dos elementos e atributos no seu editor ou IDE. Você
também pode
+ abrir o arquivo DTD no seu editor – é a maneira mais fácil de ter uma
visão geral
+ de todos os elementos e atributos e dos padrões, como também alguns
comentários.
+ Note que o Hibernate não irá carregar o arquivo DTD da web, e sim do
diretório
+ da aplicação (classpath). O arquivo DTD está incluído no
<literal>hibernate3.jar</literal> como
+ também no diretório <literal>src/</literal> da distribuição
do Hibernate.
+ </para>
+
+ <para>
+ Nós omitiremos a declaração do DTD nos exemplos futuros para encurtar o
código. Isto, é claro, não é opcional.
+ </para>
+
+ <para>
+ Entre os dois tags <literal>hibernate-mapping</literal>,
inclua um elemento <literal>class</literal>.
+ Todas as classes persistentes da entidade (novamente, poderá haver
+ mais tarde, dependências sobre as classes que não são classes-primárias
+ de entidades) necessitam do tal mapeamento, para uma tabela na base
+ de dados SQL
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Mais adiante iremos dizer ao Hibernate como fazer para persistir e
carregar objetos da classe
+ <literal>Event</literal> da tabela
<literal>EVENTS</literal>, cada instancia representada por
+ uma coluna na tabela. Agora, continuaremos com o mapeamento de uma única
propriedade identificadora
+ para as chaves primárias da tabela. Além disso, nós não iremos se
importar com esta propriedade
+ identificadora, nós iremos configurar uma estratégia de geração de id’s
para uma chave primária
+ de coluna surrogate:
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+ <id name="id" column="EVENT_ID">
+ <generator class="native"/>
+ </id>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ O elemento <literal>id</literal> é a declaração da
propriedade identificadora,
+ o <literal>name="id"</literal> declara o nome da
propriedade Java –
+ o Hibernate irá usar os métodos getter e setter para acessar a
propriedade.
+ O atributo da coluna informa ao Hibernate qual coluna da tabela
<literal>EVENTS</literal> nós
+ iremos usar como chave primária. O elemento
<literal>generator</literal> especifica
+ a estratégia de geração do identificador, neste caso usaremos
<literal>native</literal>, que
+ escolhe a melhor estratégia dependendo da base de dados (dialeto)
configurada.
+ O Hibernate suporta a base de dados gerada, globalmente única, bem como a
atribuição
+ aos identificadores da aplicação (ou toda estratégia escrita para uma
extensão).
+ </para>
+
+ <para>
+ Finalmente incluiremos as declarações para as propriedades persistentes
da classe
+ no arquivo mapeado. Por default, nenhuma das propriedades da classe é
considerada persistente:
+ </para>
+
+ <programlisting><![CDATA[
+<hibernate-mapping>
+
+ <class name="events.Event" table="EVENTS">
+ <id name="id" column="EVENT_ID">
+ <generator class="native"/>
+ </id>
+ <property name="date" type="timestamp"
column="EVENT_DATE"/>
+ <property name="title"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Da mesma maneira que com o elemento <literal>id</literal>, o
atributo <literal>name</literal> do elemento
+ <literal>property</literal> informa ao Hibernate qual método
getter e setter deverá usar.
+ Assim, neste caso, o Hibernate irá procurar pelo
<literal>getDate()/setDate()</literal>,
+ como também pelo <literal>getTitle()/setTitle()</literal>.
+ </para>
+
+ <para>
+ Porque fazer o mapeamento da propriedade
<literal>date</literal> incluído no
+ atributo <literal>column</literal>, e no title não fazer?
+ Sem o atributo <literal>column</literal> o Hibernate por
padrão usa o nome
+ da propriedade como o nome da coluna. Isto trabalha muito
+ bem para o <literal>title</literal>. Entretanto o
<literal>date</literal> é uma palavra-chave reservada
+ na maioria dos bancos de dados, assim nós melhoramos o mapeamentos
+ disto com um nome diferente.
+ </para>
+
+ <para>
+ A próxima coisa interessante é que mapemanto do
<literal>title</literal>
+ também falta o atributo <literal>type</literal>. O tipo que
declaramos e o uso nos
+ arquivos mapeados, não são como você pôde esperar, atributos de dados
Java.
+ Eles não são como os tipos de base de dados SQL.
+ Esses tipos podem ser chamados de <emphasis>Tipos de mapeamento
Hibernate</emphasis>, que são conversores
+ que podem traduzir tipos de dados do Java para os tipos de dados SQL e
vice-versa.
+ Novamente, o Hibernate irá tentar determinar a conversão correta e
mapeará o <literal>type</literal>
+ próprio, caso o tipo do atributo não estiver presente no mapeamento.
+ Em alguns casos, esta detecção automática (que usa Reflection sobre as
classes Java)
+ poderá não ter padrão que você espera ou necessita.
+ Este é o caso com a propriedade <literal>date</literal>. O
Hibernate não pode saber se a propriedade
+ (que é do <literal>java.util.Date</literal>) pode mapear para
uma coluna do tipo <literal>date</literal>
+ do SQL, <literal>timestamp</literal>, ou
<literal>time</literal> .
+ Nós preservamos a informação cheia de datas e horas pelo mapeamento da
propriedade com um conversor
+ <literal>timestamp</literal>.
+ </para>
+
+ <para>
+ Este arquivo de mapeamento deve ser salvo como
<literal>Event.hbm.xml</literal>,
+ corretamente no diretório próximo ao arquivo fonte da Classe Java
<literal>Event</literal>.
+ O nomeamento dos arquivos de mapeamento podem ser arbitrários, porém o
sufixo
+ <literal>hbm.xml</literal> é uma convenção da comunidade dos
desenvolvedores do Hibernate.
+ Esta estrutura do diretório deve agora se parecer com isso:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java
+ Event.hbm.xml]]></programlisting>
+
+ <para>
+ Nós iremos continuar com a configuração principal do Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-configuration"
revision="2">
+ <title>Configuração do Hibernate</title>
+
+ <para>
+ Agora nós temos uma classe persistente e este arquivo de mapeamento no
lugar.
+ Está na hora de configurar o Hibernate. Antes de fazermos isso, iremos
precisar de uma base de dados.
+ O HSQL DB, um SQL DBMS feito em java, pode ser baixado através do site do
HSQL DB.
+ Atualmente, você só precisa baixar o
<literal>hsqldb.jar</literal>.
+ Coloque este arquivo no diretório da pasta de desenvolvimento
<literal>lib/</literal>.
+ </para>
+
+ <para>
+ Crie um diretório chamado <literal>data</literal> no
diretório root de desenvolvimento –
+ Isto será onde o HSQL DB irá armazenar arquivos de dados. Agora iremos
iniciar o banco de dados
+ executando <literal>java -classpath ../lib/hsqldb.jar
org.hsqldb.Server</literal> neste diretório de dados.
+ Você pode ver ele iniciando e conectando ao socket TCP/IP, isto será onde
nossa aplicação irá se
+ conectar depois. Se você deseja iniciar uma nova base de dados durante
este tutorial,
+ finalize o HSQL DB(pressionando o <literal>CTRL + C</literal>
na janela), delete todos os
+ arquivos no diretório <literal>data/</literal>, e inicie o
HSQL BD novamente.
+ </para>
+
+ <para>
+ O Hibernate é uma camada na sua aplicação na qual se conecta com a base
de dados, para isso
+ necessita de informação da conexão. As conexões são feitas através de um
pool de conexão JDBC,
+ na qual teremos que configurar. A distribuição do Hibernate contém
diversas ferramentas de pooling
+ da conexão JDBC de fonte aberta, mas iremos usar o pool de conexão
interna para este tutorial.
+ Note que você tem que copiar a biblioteca necessária em seu classpath e
use configurações
+ diferentes para pooling de conexão caso você deseje utilizar um software
de pooling JDBC terceirizado
+ para qualidade de produção.
+ </para>
+
+ <para>
+ Para as configurações do Hibernate, nós podemos usar um arquivo simples
<literal>hibernate.properties</literal>,
+ um arquivo mais ligeiramente sofisticado
<literal>hibernate.cfg.xml</literal> ou até mesmo uma
+ instalação programática completa. A maioria dos usuários preferem
utilizar o arquivo de configuração XML
+ </para>
+
+ <programlisting><![CDATA[<?xml version='1.0'
encoding='utf-8'?>
+<!DOCTYPE hibernate-configuration PUBLIC
+ "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+ "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+
+ <session-factory>
+
+ <!-- Database connection settings -->
+ <property
name="connection.driver_class">org.hsqldb.jdbcDriver</property>
+ <property
name="connection.url">jdbc:hsqldb:hsql://localhost</property>
+ <property name="connection.username">sa</property>
+ <property name="connection.password"></property>
+
+ <!-- JDBC connection pool (use the built-in) -->
+ <property name="connection.pool_size">1</property>
+
+ <!-- SQL dialect -->
+ <property
name="dialect">org.hibernate.dialect.HSQLDialect</property>
+
+ <!-- Enable Hibernate's automatic session context management -->
+ <property
name="current_session_context_class">thread</property>
+
+ <!-- Disable the second-level cache -->
+ <property
name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
+
+ <!-- Echo all executed SQL to stdout -->
+ <property name="show_sql">true</property>
+
+ <!-- Drop and re-create the database schema on startup -->
+ <property name="hbm2ddl.auto">create</property>
+
+ <mapping resource="events/Event.hbm.xml"/>
+
+ </session-factory>
+
+</hibernate-configuration>]]></programlisting>
+
+ <para>
+ Note que esta configuração XML usa um diferente DTD. Nós configuraremos
+ as <literal>SessionFactory</literal> do Hibernate – uma
factory global responsável
+ por uma base de dedados particular. Se você tiver diversas bases de
dados,
+ use diversas configurações
<literal><session-factory></literal>, geralmente
+ em diversos arquivos de configuração (para uma partida mais fácil).
+ </para>
+
+ <para>
+ As primeiras quatro <literal>propriedades</literal> do
elemento contém a configuração
+ necessária para a conexão ao JDBC. A propriedade
<literal>propriedade</literal> dialect
+ do elemento especifica a variante particular do SQL que o Hibernate gera.
+ O gerenciamento automático de sessão do Hibernate para contextos de
persistência
+ estará disponível em breve. A opção
<literal>hbm2ddl.auto</literal> habilita a geração
+ automática de schemas da base de dados – diretamente na base de dados.
+ Isto também pode ser naturalmente desligado (removendo a opção de
configuração) ou redirecionando
+ para um arquivo com ajuda do <literal>SchemaExport</literal>
nas tarefas do Ant.
+ Finalmente, iremos adicionar os arquivos das classes de persistência
mapeadas na configuração.
+ </para>
+
+ <para>
+ Copie este arquivo no diretório fonte, assim isto irá terminar na raiz
(root) do
+ classpath. O Hibernate automaticamente procura por um arquivo chamado
+ <literal>hibernate.cfg.xml</literal> na raiz do classpath, no
startup.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-ant" revision="1">
+ <title>Construindo com o Ant</title>
+
+ <para>
+ Nos iremos, agora, construir o tutorial com Ant. Você ira precisar o Ant
instalado –
+ se encontra disponível <ulink
url="http://ant.apache.org/bindownload.cgi">na página de download do
Ant</ulink>.
+ Como instalar o Ant, não será abordado aqui. Caso tenha alguma dúvida,
por favor,
+ vá ao <ulink
url="http://ant.apache.org/manual/index.html">Ant manual</ulink>.
+ Depois que tiver instalado o Ant, podemos começar a criar o arquivo de
construção <literal>build.xml</literal>.
+ Este arquivo será chamado de <literal>build.xml</literal> e
posto diretamente no diretório de desenvolvimento.
+ </para>
+
+ <para>
+ Um arquivo básico de build, se parece com isto:
+ </para>
+
+ <programlisting><![CDATA[<project
name="hibernate-tutorial" default="compile">
+
+ <property name="sourcedir" value="${basedir}/src"/>
+ <property name="targetdir" value="${basedir}/bin"/>
+ <property name="librarydir" value="${basedir}/lib"/>
+
+ <path id="libraries">
+ <fileset dir="${librarydir}">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <target name="clean">
+ <delete dir="${targetdir}"/>
+ <mkdir dir="${targetdir}"/>
+ </target>
+
+ <target name="compile" depends="clean, copy-resources">
+ <javac srcdir="${sourcedir}"
+ destdir="${targetdir}"
+ classpathref="libraries"/>
+ </target>
+
+ <target name="copy-resources">
+ <copy todir="${targetdir}">
+ <fileset dir="${sourcedir}">
+ <exclude name="**/*.java"/>
+ </fileset>
+ </copy>
+ </target>
+
+</project>]]></programlisting>
+
+ <para>
+ Isto irá avisar ao Ant para adicionar todos os arquivos no diretório lib
terminando com
+ <literal>.jar</literal>, para o classpath usado para
compilação. Irá também copiar todos os
+ arquivos não-java para o diretório alvo (arquivos de configuração,
mapeamento). Se você rodar
+ o ant agora, deverá ter esta saída.
+ </para>
+
+ <programlisting><![CDATA[C:\hibernateTutorial\>ant
+Buildfile: build.xml
+
+copy-resources:
+ [copy] Copying 2 files to C:\hibernateTutorial\bin
+
+compile:
+ [javac] Compiling 1 source file to C:\hibernateTutorial\bin
+
+BUILD SUCCESSFUL
+Total time: 1 second ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-helpers" revision="3">
+ <title>Startup and helpers</title>
+
+ <para>
+ É hora de carregar e arquivar alguns objetos
<literal>Event</literal>, mas primeiro
+ nós temos de completar o setup com algum código de infraestrutura. Este
startup
+ inclui a construção de um objeto
<literal>SessionFactory</literal> global e armazenar
+ isto em algum lugar de fácil acesso para o código da aplicação.
+ Uma <literal>SessionFactory</literal> pode abrir novas
<literal>Session</literal>'s.
+ Uma <literal>Session</literal> representa uma unidade
single-theaded do trabalho, a
+ <literal>SessionFactory</literal> é um objeto global
thread-safe, instanciado uma vez.
+ </para>
+
+ <para>
+ Nos iremos criar uma classe de ajuda
<literal>HibernateUtil</literal>, que toma
+ conta do startup e faz acesso a uma
<literal>SessionFactory</literal> conveniente.
+ Vamos dar uma olhada na implementação:
+ </para>
+
+ <programlisting><![CDATA[package util;
+
+import org.hibernate.*;
+import org.hibernate.cfg.*;
+
+public class HibernateUtil {
+
+ private static final SessionFactory sessionFactory;
+
+ static {
+ try {
+ // Create the SessionFactory from hibernate.cfg.xml
+ sessionFactory = new Configuration().configure().buildSessionFactory();
+ } catch (Throwable ex) {
+ // Make sure you log the exception, as it might be swallowed
+ System.err.println("Initial SessionFactory creation failed." +
ex);
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ public static SessionFactory getSessionFactory() {
+ return sessionFactory;
+ }
+
+}]]></programlisting>
+
+ <para>
+ Esta classe não só produz a global
<literal>SessionFactory</literal> no seu static initializer
+ (chamado uma vez pela JVM quando a classe é carregada), mas também
esconde o fato
+ de que isto usa um static singleton. Ela pode muito bem, enxergar a
+ <literal>SessionFactory</literal> do JNDI em um application
server.
+ </para>
+
+ <para>
+ Se você der à <literal>SessionFactory</literal> um nome, no
seu arquivo de configuração.
+ O Hibernate irá, de fato, tentar uni-lo ao JNDI depois que estiver
construído.
+ Para evitar este completamente este código, você também poderia usar JMX
deployment
+ e deixar o contêiner JMX capaz, instanciar e unir um
<literal>HibernateService</literal>
+ no JNDI. Essas opções avançadas são discutidas no documento de referência
do Hibernate.
+ </para>
+
+ <para>
+ Coloque o Place <literal>HibernateUtil.java</literal> no
diretório de arquivos
+ de desenvolvimento(source), em um pacote após o
<literal>events</literal>:
+ </para>
+
+ <programlisting><![CDATA[.
++lib
+ <Hibernate and third-party libraries>
++src
+ +events
+ Event.java
+ Event.hbm.xml
+ +util
+ HibernateUtil.java
+ hibernate.cfg.xml
++data
+build.xml]]></programlisting>
+
+ <para>
+ Novamente, isto deve compilar sem problemas. Finalmente, nós precisamos
configurar
+ um sistema de logging – o Hibernate usa commons logging e deixa você
escolher entre o
+ Log4j e o logging do JDK 1.4 . A maioria dos desenvolvedores preferem o
Log4j: copie
+ <literal>log4j.properties</literal> da distribuição do
Hibernate (está no diretório
+ <literal>etc/</literal>), para seu diretório
<literal>src</literal>,
+ depois vá em hibernate.cfg.xml. Dê uma olhada no exemplo de configuração
e mude as
+ configurações se você quizer ter uma saída mais detalhada. Por default,
apenas as
+ mensagems de startup e shwwn do Hibernate é mostrada no stdout.
+ </para>
+
+ <para>
+ O tutorial de infra-estrutura está completo - e nós já estamos preparados
para algum
+ trabalho de verdade com o Hibernate.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-firstapp-workingpersistence"
revision="4">
+ <title>Carregando e salvando objetos</title>
+
+ <para>
+ Finalmente, nós podemos usar o Hibernate para carregar e armazenar
objetos.
+ Nós escrevemos uma classe <literal>EventManager</literal> com
um método main():
+ </para>
+
+ <programlisting><![CDATA[package events;
+import org.hibernate.Session;
+
+import java.util.Date;
+
+import util.HibernateUtil;
+
+public class EventManager {
+
+ public static void main(String[] args) {
+ EventManager mgr = new EventManager();
+
+ if (args[0].equals("store")) {
+ mgr.createAndStoreEvent("My Event", new Date());
+ }
+
+ HibernateUtil.getSessionFactory().close();
+ }
+
+ private void createAndStoreEvent(String title, Date theDate) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+
+ session.beginTransaction();
+
+ Event theEvent = new Event();
+ theEvent.setTitle(title);
+ theEvent.setDate(theDate);
+
+ session.save(theEvent);
+
+ session.getTransaction().commit();
+ }
+
+}]]></programlisting>
+
+ <para>
+ We create a new <literal>Event</literal> object, and hand it
over to Hibernate.
+ Hibernate now takes care of the SQL and executes
<literal>INSERT</literal>s
+ on the database. Let's have a look at the
<literal>Session</literal> and
+ <literal>Transaction</literal>-handling code before we run
this.
+
+ Nós criamos um novo objeto <literal>Event</literal>, e
passamos para o Hibernate.
+ O Hibernate sabe como tomar conta do SQL e executa
<literal>INSERT</literal>s
+ no banco de dados. Vamos dar uma olhada na
<literal>Session</literal> e no
+ código <literal>Transaction</literal>-handling antes de
executarmos.
+ </para>
+
+ <para>
+ Um <literal>Session</literal> é uma unidade simples de trabalho. Por
agora nós
+ iremos pegar coisas simples e assumir uma granularidade de um-pra-um entre uma
+ <literal>Session</literal> do Hibernate e uma transação de banco de dados.
+ Para proteger nosso código de um atual sistema subjacente de transação (nesse
+ caso puro JDBC, mas também poderia rodar com JTA), nos usamos a API
+ <literal>Transaction</literal>, que está disponível na
<literal>Session</literal> do Hibernate.
+ </para>
+
+ <para>
+ O que a <literal>sessionFactory.getCurrentSession()</literal>
faz? Primeiro, você pode
+ chamar quantas vezes e de onde quiser, uma vez você recebe sua
<literal>SessionFactory</literal>
+ (fácil graças ao <literal>HibernateUtil</literal>). O método
<literal>getCurrentSession()</literal>
+ sempre retorna a unidade de trabalho "corrente". Lembra de que
nós mudamos a opção
+ de configuração desse mecanismo para thread no
<literal>hibernate.cfg.xml</literal>? Daqui em
+ diante, o escopo da unidade de trabalho corrente é a thread Java
+ corrente que executa nossa aplicação. Entretanto, esta não é toda a
verdade. Uma
+ <literal>Session</literal> começa quando é primeiramente
necessária, quando é feita a
+ primeira chamada à <literal>getCurrentSession()</literal>. É
então limitado pelo Hibernate
+ para thread corrente. Quando a transação termina, tanto com commit quanto
rollback,
+ o Hibernate também desune a <literal>Session</literal> da
thread e fecha isso pra você.
+ Se você chamar <literal>getCurrentSession()</literal>
novamente, você receberá uma nova
+ <literal>Session</literal> e pode começar uma nova unidade de
trabalho. Esse modelo de
+ programação de limite de thread
<emphasis>thread-bound</emphasis>, é o modo mais popular
+ de se usar o Hibernate.
+ </para>
+
+ <para>
+ Dê uma olhada no <xref linkend="transactions"/> para mais informações
a
+ respeito de manipulação de transação e demarcação. Nós também pulamos qualquer
+ manipulação de erro e rollback no exemplo anterior.
+ </para>
+
+ <para>
+ Para executar esta primeira rotina, nos teremos que adicionar um ponto de chamada
+ para o arquivo de build do Ant:
+ </para>
+
+ <programlisting><![CDATA[<target name="run"
depends="compile">
+ <java fork="true" classname="events.EventManager"
classpathref="libraries">
+ <classpath path="${targetdir}"/>
+ <arg value="${action}"/>
+ </java>
+</target>]]></programlisting>
+
+ <para>
+ O valor do argumento <literal>action</literal>, é setado na
linha de comando quando chamando esse ponto:
+ </para>
+
+ <programlisting><![CDATA[C:\hibernateTutorial\>ant run
-Daction=store]]></programlisting>
+
+ <para>
+ Você deverá ver, após a compilação, o startup do Hibernate e, dependendo
da sua
+ configuração, muito log de saída. No final você verá a seguinte linha:
+ </para>
+
+ <programlisting><![CDATA[[java] Hibernate: insert into EVENTS
(EVENT_DATE, title, EVENT_ID) values (?, ?, ?)]]></programlisting>
+
+ <para>
+ Este é o <literal>INSERT</literal> executado pelo Hibernate,
os pontos de interrogação
+ representam parêmetros de união do JDBC. Para ver os valores
substituídos, ou para diminuir a
+ verbalidade do log, check seu
l<literal>log4j.properties</literal>.
+ </para>
+
+ <para>
+ Agora nós gostaríamos de listar os eventos arquivados, então nós
adicionamos uma
+ opção para o método main:
+ </para>
+
+ <programlisting><![CDATA[if (args[0].equals("store")) {
+ mgr.createAndStoreEvent("My Event", new Date());
+}
+else if (args[0].equals("list")) {
+ List events = mgr.listEvents();
+ for (int i = 0; i < events.size(); i++) {
+ Event theEvent = (Event) events.get(i);
+ System.out.println("Event: " + theEvent.getTitle() +
+ " Time: " + theEvent.getDate());
+ }
+}]]></programlisting>
+
+ <para>
+ Nos também adicionamos um novo <literal>método
listEvents()</literal>:
+ </para>
+
+ <programlisting><![CDATA[private List listEvents() {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+
+ session.beginTransaction();
+
+ List result = session.createQuery("from Event").list();
+
+ session.getTransaction().commit();
+
+ return result;
+}]]></programlisting>
+
+ <para>
+ O que nós fazemos aqui, é usar uma query HQL (Hibernate Query Language),
+ para carregar todos os objetos <literal>Event</literal>
exitentes no banco de dados.
+ O Hibernate irá gerar o SQL apropriado, enviar para o banco de dados e
popular objetos
+ <literal>Event</literal> com os dados. Você pode criar
queries mais complexas com
+ HQL, claro.
+ </para>
+
+ <para>
+ Agora, para executar e testar tudo isso, siga os passos a seguir:
+ </para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ Execute <literal>ant run -Daction=store</literal>
para armazenar algo no banco de dados
+ e, claro, gerar o esquema do banco de dados antes pelo hbm2ddl.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Agora desabilite hbm2ddl comentando a propriedade no seu arquivo
<literal>hibernate.cfg.xml</literal>.
+ Normalmente só se deixa habilitado em teste unitários contínuos,
mas outra carga de hbm2ddl
+ pode <emphasis>remover</emphasis> tudo que você já
tenha arquivado. Sa configuração
+ <literal>create</literal>, atualmente são traduzidas
para "apague todas as tabelas do esquema,
+ então recrie todas quando a SessionFactory estiver pronta".
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Se você agora chamar o Ant com
<literal>-Daction=list</literal>, você deverá ver os
+ eventos que você acabou de criar. Você pode também chamar a ação
<literal>store</literal>
+ mais algumas vezes.
+ </para>
+
+ <para>
+ Nota: A maioria dos novos usuários do Hibernate falha nesse ponto e nós
regularmente, vemos
+ questões sobre mensagens de erro de <emphasis>tabela não encontrada
</emphasis> .
+ Entretanto, se você seguir os passos marcados acima, você não terá esse
problema,
+ com o hbm2ddl criando o esquema do banco de dados na primeira execução, e
restarts
+ subsequentes da aplicação irão usar este esquema. Se você mudar o
mapeamento e/ou
+ o esquema do banco de dados, terá de re-habilitar o hbm2ddl mais uma
vez.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="tutorial-associations">
+ <title>Part 2 - Mapeando associações</title>
+
+ <para>
+ Nós mapeamos uma classe de entidade de persistência para uma tabela. Agora vamos
continuar
+ e adicionar algumas associações de classe. Primeiro nos iremos adicionar pessoas a
nossa aplicação,
+ e armazenar os eventos de que elas participam.
+ </para>
+
+ <sect2 id="tutorial-associations-mappinguser"
revision="1">
+ <title>Mapeando a classe Person</title>
+
+ <para>
+ O primeiro código da classe <literal>Person</literal> é
simples:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+public class Person {
+
+ private Long id;
+ private int age;
+ private String firstname;
+ private String lastname;
+
+ public Person() {}
+
+ // Accessor methods for all properties, private setter for 'id'
+
+}]]></programlisting>
+
+ <para>
+ Crie um novo arquivo de mapeamento, chamado
<literal>Person.hbm.xml</literal> (não
+ esqueça a referencia ao DTD no topo)
+ </para>
+
+ <programlisting><![CDATA[<hibernate-mapping>
+
+ <class name="events.Person" table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="native"/>
+ </id>
+ <property name="age"/>
+ <property name="firstname"/>
+ <property name="lastname"/>
+ </class>
+
+</hibernate-mapping>]]></programlisting>
+
+ <para>
+ Finalmente, adicione o novo mapeamento a configuração do Hibernate:
+ </para>
+
+ <programlisting><![CDATA[<mapping
resource="events/Event.hbm.xml"/>
+<mapping resource="events/Person.hbm.xml"/>]]></programlisting>
+
+ <para>
+ Nos iremos agora criar uma associação entre estas duas entidades.
Obviamente,
+ pessoas (Person) podem participar de eventos, e eventos possuem
participantes.
+ As questões de design com que teremos de lidar são: direcionalidade,
multiplicidade e
+ comportamento de coleção.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-unidirset"
revision="3">
+ <title>Uma associação Set-based unidirectional</title>
+
+ <para>
+ Nos iremos adicionar uma coleção de eventos na classe
<literal>Person</literal>. Desse jeito
+ poderemos navegar pelos eventos de uma pessoa em particular, sem executar
uma query explicitamente –
+ apenas chamando <literal>aPerson.getEvents()</literal>. Nos
usaremos uma coleção Java, um
+ <literal>Set</literal>, porquê a coleção não conterá
elementos duplicados e a ordem não é
+ relevante para nós.
+ </para>
+
+ <para>
+ Vamos escrever o código para isto nas classes Java e então mapear:
+ </para>
+
+ <programlisting><![CDATA[public class Person {
+
+ private Set events = new HashSet();
+
+ public Set getEvents() {
+ return events;
+ }
+
+ public void setEvents(Set events) {
+ this.events = events;
+ }
+}]]></programlisting>
+
+ <para>
+ Antes de mapearmos esta associação, pense no outro lado. Claramente,
poderíamos apenas fazer isto de
+ forma unidirecional. Ou poderíamos criar outra coleção no
<literal>Event</literal>, se quisermos
+ ser capaz de navegar bidirecionalmente, i.e. um -
<literal>anEvent.getParticipants()</literal>.
+ Isto não é necessário, de perspectiva funcional. Você poderia sempre
executar uma query explicita
+ que retornasse os participantes de um evento em particular. Esta é uma
escolha de design que cabe
+ a você, mas o que é claro nessa discussão é a multiplicidade da
associação: "muitos" valores em ambos
+ os lados, nós chamamos isto uma associação
<emphasis>muitos-para-muitos</emphasis>. Daqui pra frente,
+ nos usaremos o mapeamento muitos-para-muitos do Hibernate:
+ </para>
+
+ <programlisting><![CDATA[<class name="events.Person"
table="PERSON">
+ <id name="id" column="PERSON_ID">
+ <generator class="native"/>
+ </id>
+ <property name="age"/>
+ <property name="firstname"/>
+ <property name="lastname"/>
+
+ <set name="events" table="PERSON_EVENT">
+ <key column="PERSON_ID"/>
+ <many-to-many column="EVENT_ID" class="events.Event"/>
+ </set>
+
+</class>]]></programlisting>
+
+ <para>
+ O Hibernate suporta todo tipo de mapeamento de coleção , sendo um
<literal><set></literal> mais comum.
+ Para uma associação muitos-para-muitos (ou relacionamento de entidade
<emphasis>n:m</emphasis> ),
+ uma tabela de associação é necessária. Cada linha nessa tabela representa
um link entre uma pessoa e um
+ evento. O nome da tabela é configurado com o atributo
<literal>table</literal> do elemento
+ <literal>set</literal>. O nome da coluna identificadora na
associção, peloo lado da pessoa,
+ é definido com o elemento
<literal><key></literal> , o nome da coluna pelo lado dos
eventos,
+ e definido com o atributo <literal>column</literal> do
<literal><many-to-many></literal>.
+ Você também precisa dizer para o Hibernate a classe dos objetos na sua
coleção (a classe do outro
+ lado das coleções de referência).
+ </para>
+
+ <para>
+ O esquema de mapeamento para o banco de dados está a seguir:
+ </para>
+
+ <programlisting><![CDATA[
+ _____________ __________________
+ | | | | _____________
+ | EVENTS | | PERSON_EVENT | | |
+ |_____________| |__________________| | PERSON |
+ | | | | |_____________|
+ | *EVENT_ID | <--> | *EVENT_ID | | |
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID |
+ | TITLE | |__________________| | AGE |
+ |_____________| | FIRSTNAME |
+ | LASTNAME |
+ |_____________|
+ ]]></programlisting>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-working"
revision="1">
+ <title>Trabalhando a associação</title>
+
+ <para>
+ Vamos trazer juntos algumas pessoas e eventos em um novo método na classe
<literal>EventManager</literal>::
+ </para>
+
+ <programlisting><![CDATA[private void addPersonToEvent(Long
personId, Long eventId) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session.load(Person.class, personId);
+ Event anEvent = (Event) session.load(Event.class, eventId);
+
+ aPerson.getEvents().add(anEvent);
+
+ session.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ Após carregar um <literal>Person</literal> e um
<literal>Event</literal>, simplesmente
+ modifique a coleção usando os métodos normais de uma coleção. Como você
pode ver, não há chamada explícita
+ para <literal>update()</literal> ou
<literal>save()</literal>, o Hibernate detecta automaticamente
+ que a coleção foi modificada e necessita ser atualizada. Isso é chamado
de <emphasis>checagem
+ suja automática</emphasis>, e você também pode usá-la modificando o
nome ou a data de qualquer um dos
+ seus objetos. Assim que eles estiverem no estado
<emphasis>persistent</emphasis>, ou seja,
+ limitado por uma <literal>Session</literal> do Hibernate em
particular (i.e. eles foram carregados ou
+ salvos dentro de uma unidade de trabalho), o Hibernate monitora qualquer
alteração e executa o SQL
+ em modo de escrita em segundo plano. O processo de sincronização do
estado da memória com o banco de
+ dados, geralmente apenas no final de uma unidade de trabalho, é chamado
de <emphasis>flushing</emphasis>.
+ No nosso código, a unidade de trabalho termina com o commit da transação
do banco de dados –
+ como definido pela opção de configuração da
<literal>thread</literal> da classe
<literal>CurrentSessionContext</literal>.
+ </para>
+
+ <para>
+ Você pode também querer carregar pessoas e eventos em diferentes unidades
de trabalho.
+ Ou você modifica um objeto fora de uma
<literal>Session</literal>, quando não se encontra no
+ estado persistent (se já esteve neste estado anteriormente, chamamos esse
estado de
+ <emphasis>detached</emphasis>). Você pode até mesmo modificar
uma coleção quando esta
+ se encontrar no estado detached.
+ </para>
+
+ <programlisting><![CDATA[private void addPersonToEvent(Long
personId, Long eventId) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session
+ .createQuery("select p from Person p left join fetch p.events where p.id
= :pid")
+ .setParameter("pid", personId)
+ .uniqueResult(); // Eager fetch the collection so we can use it detached
+
+ Event anEvent = (Event) session.load(Event.class, eventId);
+
+ session.getTransaction().commit();
+
+ // End of first unit of work
+
+ aPerson.getEvents().add(anEvent); // aPerson (and its collection) is detached
+
+ // Begin second unit of work
+
+ Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
+ session2.beginTransaction();
+
+ session2.update(aPerson); // Reattachment of aPerson
+
+ session2.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ A chamada <literal>update</literal> cria um objeto persistent
novamente, você poderia
+ dizer que ele liga o objeto a uma nova unidade de trabalho, assim
qualquer modificação
+ que você faça neste objeto enquanto estiver no estado detached pode ser
salvo no banco de dados.
+ Isso inclui qualquer modificação (adição/exclusão) que você faça em uma
coleção da entidade deste objeto.
+ </para>
+
+ <para>
+ Bom, isso não foi muito usado na nossa situação, porém, é um importante conceito que
você
+ pode aplicar em seus aplicativos. Agora, complete este exercício adicionando uma nova
ação
+ ao método main( ) da classe <literal>EventManager</literal> e chame-o pela
linha de comando.
+ Se você precisar dos identificadores de uma pessoa ou evento – o método
<literal>save()</literal>
+ retorna estes identificadores (você poderá modificar alguns dos métodos anteriores para
retornar aquele
+ identificador):
+ </para>
+
+ <programlisting><![CDATA[else if
(args[0].equals("addpersontoevent")) {
+ Long eventId = mgr.createAndStoreEvent("My Event", new Date());
+ Long personId = mgr.createAndStorePerson("Foo", "Bar");
+ mgr.addPersonToEvent(personId, eventId);
+ System.out.println("Added person " + personId + " to event " +
eventId);]]></programlisting>
+
+ <para>
+ Este foi um exemplo de uma associação entre duas classes igualmente
importantes, duas entidades.
+ Como mencionado anteriormente, há outras classes e tipos dentro de um
modelo típico,
+ geralmente "menos importante". Alguns você já viu, como um
<literal>int</literal> ou uma <literal>String</literal>.
+ Nós chamamos essas classes de <emphasis>value
types</emphasis>, e suas instâncias <emphasis>depend</emphasis>
+ de uma entidade particular. As instâncias desses tipos não possuem sua
própria identidade, nem são
+ compartilhados entre entidades (duas pessoas não referenciam o mesmo
objeto <literal>firstname</literal>
+ mesmo se elas tiverem o mesmo objeto firstname). Naturalmente, os value
types não são apenas encontrados
+ dentro da JDK (de fato, em um aplicativo Hibernate todas as classes JDK
são consideradas como value types),
+ mas você pode também criar suas classes como, por exemplo,
<literal>Address</literal> ou <literal>MonetaryAmount</literal>.
+
+ </para>
+
+ <para>
+ Você também pode criar uma coleção de value types. Isso é conceitualmente
muito diferente
+ de uma coleção de referências para outras entidades, mas em Java parece
ser quase a mesma coisa.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-valuecollections">
+ <title>Coleção de valores</title>
+
+ <para>
+ Nós adicionamos uma coleção de objetos de tipo de valores à entidade
<literal>Person</literal.
+ Nós querermos armazenar endereços de e-mail, para isso utilizamos o tipo
<literal>String</literal>,
+ e a coleção novamente será um <literal>Set</literal>:
+ </para>
+ <programlisting><![CDATA[private Set emailAddresses = new
HashSet();
+
+public Set getEmailAddresses() {
+ return emailAddresses;
+}
+
+public void setEmailAddresses(Set emailAddresses) {
+ this.emailAddresses = emailAddresses;
+}]]></programlisting>
+
+ <para>
+ O mapeamento deste <literal>Set</literal>:
+ </para>
+
+ <programlisting><![CDATA[<set name="emailAddresses"
table="PERSON_EMAIL_ADDR">
+ <key column="PERSON_ID"/>
+ <element type="string" column="EMAIL_ADDR"/>
+</set>]]></programlisting>
+
+ <para>
+ The difference compared with the earlier mapping is the
<literal>element</literal> part, which tells Hibernate that the collection
+ does not contain references to another entity, but a collection of
elements of type
+ <literal>String</literal> (the lowercase name tells you
it's a Hibernate mapping type/converter).
+ Once again, the <literal>table</literal> attribute of the
<literal>set</literal> element determines
+ the table name for the collection. The <literal>key</literal>
element defines the foreign-key column
+ name in the collection table. The <literal>column</literal>
attribute in the <literal>element</literal>
+ element defines the column name where the
<literal>String</literal> values will actually be stored.
+
+ A diferença comparada com o mapeamento anterior se encontra na parte
<literal>element</literal>,
+ que indica ao Hibernate que a coleção não contém referências à outra
entidade, mas uma coleção de
+ elementos do tipo <literal>String</literal> (a tag name em
miniscula indica que se trata de um
+ mapeamento do Hibernate para conversão de tipos). Mais uma vez, o
atributo <literal>table</literal>
+ do elemento <literal>set</literal> determina o nome da tabela
para a coleção. O elemento
+ <literal>key</literal> define o nome da coluna de chave
estrangeira na tabela de coleção.
+ O atributo <literal>column</literal> dentro do elemento
<literal>element</literal> define o
+ nome da coluna onde os valores da <literal>String</literal>
serão armazenados.
+ </para>
+
+ <para>
+ Dê uma olhada no esquema atualizado:
+ </para>
+
+ <programlisting><![CDATA[
+ _____________ __________________
+ | | | | _____________
+ | EVENTS | | PERSON_EVENT | | |
___________________
+ |_____________| |__________________| | PERSON | |
|
+ | | | | |_____________| | PERSON_EMAIL_ADDR
|
+ | *EVENT_ID | <--> | *EVENT_ID | | |
|___________________|
+ | EVENT_DATE | | *PERSON_ID | <--> | *PERSON_ID | <--> |
*PERSON_ID |
+ | TITLE | |__________________| | AGE | | *EMAIL_ADDR
|
+ |_____________| | FIRSTNAME |
|___________________|
+ | LASTNAME |
+ |_____________|
+ ]]></programlisting>
+
+ <para>
+ Você pode observar que a chave primária da tabela da coleção é de na
verdade uma chave composta,
+ usando ambas colunas. Isso também implica que cada pessoa não pode ter
endereços de e-mail
+ duplicados, o que é exatamente a semântica que precisamos para um set em
Java.
+ </para>
+
+ <para>
+ Você pode agora tentar adicionar elementos a essa coleção, do mesmo modo
que fizemos
+ anteriormente ligando pessoas e eventos. È o mesmo código em Java:
+ </para>
+
+ <programlisting><![CDATA[private void addEmailToPerson(Long
personId, String emailAddress) {
+
+ Session session = HibernateUtil.getSessionFactory().getCurrentSession();
+ session.beginTransaction();
+
+ Person aPerson = (Person) session.load(Person.class, personId);
+
+ // The getEmailAddresses() might trigger a lazy load of the collection
+ aPerson.getEmailAddresses().add(emailAddress);
+
+ session.getTransaction().commit();
+}]]></programlisting>
+
+ <para>
+ This time we didnt' use a <emphasis>fetch</emphasis>
query to initialize the collection.
+ Hence, the call to its getter method will trigger an additional select to
initialize
+ it, so we can add an element to it. Monitor the SQL log and try to
optimize this with
+ an eager fetch.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-bidirectional"
revision="1">
+ <title>Associações bidirecionais</title>
+
+ <para>
+ Agora iremos mapear uma associação bidirecional – fazendo a associação
entre pessoas e
+ eventos, de ambos os lados, em Java. Logicamente, o esquema do banco de
dados não muda,
+ nós continuamos tendo multiplicidades muitos-para-muitos. Um banco de
dados é mais flexível do que
+ uma linguagem de programação para redes, ele não precisa de nenhuma
direção de navegação – os
+ dados podem ser acessados em qualquer caminho possível.
+ </para>
+
+ <para>
+ Primeiramente, adicione uma coleção de participantes à classe
<literal>Event</literal>:
+ </para>
+
+ <programlisting><![CDATA[private Set participants = new HashSet();
+
+public Set getParticipants() {
+ return participants;
+}
+
+public void setParticipants(Set participants) {
+ this.participants = participants;
+}]]></programlisting>
+
+ <para>
+ Agora mapeie este lado da associação em
<literal>Event.hbm.xml</literal>.
+ </para>
+
+ <programlisting><![CDATA[<set name="participants"
table="PERSON_EVENT" inverse="true">
+ <key column="EVENT_ID"/>
+ <many-to-many column="PERSON_ID" class="events.Person"/>
+</set>]]></programlisting>
+
+ <para>
+ Como você pode ver, esses é uma mapeamento normal usando
<literal>set</literal> em ambos documenentos
+ de mapeamento. Observe que o nome das colunas em
<literal>key</literal> e <literal>many-to-many</literal>
+ estão trocados em ambos os documentos de mapeamento. A adição mais
importante feita está no atributo
+ <literal>inverse="true"</literal> no elemento set
do mapeamento da coleção da classe <literal>Event</literal>.
+ </para>
+
+ <para>
+ Isso significa que o Hibernate deve pegar o outro lado – a classe
<literal>Person</literal> –
+ quando necessitar encontrar informação sobre a relação entre as duas
entidades. Isso será muito
+ mais facilmente compreendido quando você analisar como a relação
bidirecional entre as entidades é criada.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-associations-usingbidir">
+ <title>Trabalhando com links bidirecionais</title>
+
+ <para>
+ Primeiro tenha em mente que o Hibernate não afeta a semântica normal do
Java. Como nós criamos
+ um link entre uma <literal>Person</literal> e um
<literal>Event</literal> no exemplo unidirecional?
+ Nós adicionamos uma instância de <literal>Event</literal>, da
coleção de referências de eventos,
+ a uma instância de <literal>Person</literal>. Então,
obviamente, se nós queremos que este link funcione
+ bidirecionalmente, nós devemos fazer a mesma coisa para o outro lado –
adicionando uma referência de
+ <literal>Person</literal> na coleção de um
<literal>Event</literal>. Esse acerto de link de ambos
+ os lados é absolutamente necessário e você nunca deve esquecer de
faze-lo.
+ </para>
+
+ <para>
+ Muitos desenvolvedores programam de maneira defensiva e criam métodos
+ gerenciador de links que ajusta corretamente ambos os lados:
+ </para>
+
+ <programlisting><![CDATA[protected Set getEvents() {
+ return events;
+}
+
+protected void setEvents(Set events) {
+ this.events = events;
+}
+
+public void addToEvent(Event event) {
+ this.getEvents().add(event);
+ event.getParticipants().add(this);
+}
+
+public void removeFromEvent(Event event) {
+ this.getEvents().remove(event);
+ event.getParticipants().remove(this);
+}]]></programlisting>
+
+ <para>
+ Notice that the get and set methods for the collection are now protected
- this allows classes in the
+ same package and subclasses to still access the methods, but prevents
everybody else from messing
+ with the collections directly (well, almost). You should probably do the
same with the collection
+ on the other side.
+ </para>
+
+ <para>
+ What about the <literal>inverse</literal> mapping attribute?
For you, and for Java, a bi-directional
+ link is simply a matter of setting the references on both sides
correctly. Hibernate however doesn't
+ have enough information to correctly arrange SQL
<literal>INSERT</literal> and <literal>UPDATE</literal>
+ statements (to avoid constraint violations), and needs some help to
handle bi-directional associations
+ properly. Making one side of the association
<literal>inverse</literal> tells Hibernate to basically
+ ignore it, to consider it a <emphasis>mirror</emphasis> of
the other side. That's all that is necessary
+ for Hibernate to work out all of the issues when transformation a
directional navigation model to
+ a SQL database schema. The rules you have to remember are
straightforward: All bi-directional associations
+ need one side as <literal>inverse</literal>. In a one-to-many
association it has to be the many-side,
+ in many-to-many association you can pick either side, there is no
difference.
+ </para>
+
+ </sect2>
+
+ <para>
+ Let's turn this into a small web application.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-webapp">
+ <title>Part 3 - The EventManager web application</title>
+
+ <para>
+ A Hibernate web application uses <literal>Session</literal> and
<literal>Transaction</literal>
+ almost like a standalone application. However, some common patterns are
useful. We now write
+ an <literal>EventManagerServlet</literal>. This servlet can list
all events stored in the
+ database, and it provides an HTML form to enter new events.
+ </para>
+
+ <sect2 id="tutorial-webapp-servlet" revision="1">
+ <title>Writing the basic servlet</title>
+
+ <para>
+ Create a new class in your source directory, in the
<literal>events</literal>
+ package:
+ </para>
+
+ <programlisting><![CDATA[package events;
+
+// Imports
+
+public class EventManagerServlet extends HttpServlet {
+
+ // Servlet code
+}]]></programlisting>
+
+ <para>
+ The servlet handles HTTP <literal>GET</literal> requests
only, hence, the method
+ we implement is <literal>doGet()</literal>:
+ </para>
+
+ <programlisting><![CDATA[protected void doGet(HttpServletRequest
request,
+ HttpServletResponse response)
+ throws ServletException, IOException {
+
+ SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy");
+
+ try {
+ // Begin unit of work
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().beginTransaction();
+
+ // Process request and render page...
+
+ // End unit of work
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().getTransaction().commit();
+
+ } catch (Exception ex) {
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().getTransaction().rollback();
+ throw new ServletException(ex);
+ }
+
+}]]></programlisting>
+
+ <para>
+ The pattern we are applying here is called
<emphasis>session-per-request</emphasis>.
+ When a request hits the servlet, a new Hibernate
<literal>Session</literal> is
+ opened through the first call to
<literal>getCurrentSession()</literal> on the
+ <literal>SessionFactory</literal>. Then a database
transaction is started—all
+ data access as to occur inside a transaction, no matter if data is read
or written
+ (we don't use the auto-commit mode in applications).
+ </para>
+
+ <para>
+ Next, the possible actions of the request are processed and the response
HTML
+ is rendered. We'll get to that part soon.
+ </para>
+
+ <para>
+ Finally, the unit of work ends when processing and rendering is complete.
If any
+ problem occured during processing or rendering, an exception will be
thrown
+ and the database transaction rolled back. This completes the
+ <literal>session-per-request</literal> pattern. Instead of
the transaction
+ demarcation code in every servlet you could also write a servlet filter.
+ See the Hibernate website and Wiki for more information about this
pattern,
+ called <emphasis>Open Session in
View</emphasis>—you'll need it as soon
+ as you consider rendering your view in JSP, not in a servlet.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-webapp-processing" revision="1">
+ <title>Processing and rendering</title>
+
+ <para>
+ Let's implement the processing of the request and rendering of the
page.
+ </para>
+
+<programlisting><![CDATA[// Write HTML header
+PrintWriter out = response.getWriter();
+out.println("<html><head><title>Event
Manager</title></head><body>");
+
+// Handle actions
+if ( "store".equals(request.getParameter("action")) ) {
+
+ String eventTitle = request.getParameter("eventTitle");
+ String eventDate = request.getParameter("eventDate");
+
+ if ( "".equals(eventTitle) || "".equals(eventDate) ) {
+ out.println("<b><i>Please enter event title and
date.</i></b>");
+ } else {
+ createAndStoreEvent(eventTitle, dateFormatter.parse(eventDate));
+ out.println("<b><i>Added event.</i></b>");
+ }
+}
+
+// Print page
+printEventForm(out);
+listEvents(out, dateFormatter);
+
+// Write HTML footer
+out.println("</body></html>");
+out.flush();
+out.close();]]></programlisting>
+
+ <para>
+ Granted, this coding style with a mix of Java and HTML would not scale
+ in a more complex application—keep in mind that we are only
illustrating
+ basic Hibernate concepts in this tutorial. The code prints an HTML
+ header and a footer. Inside this page, an HTML form for event entry and
+ a list of all events in the database are printed. The first method is
+ trivial and only outputs HTML:
+ </para>
+
+ <programlisting><![CDATA[private void printEventForm(PrintWriter
out) {
+ out.println("<h2>Add new event:</h2>");
+ out.println("<form>");
+ out.println("Title: <input name='eventTitle'
length='50'/><br/>");
+ out.println("Date (e.g. 24.12.2009): <input name='eventDate'
length='10'/><br/>");
+ out.println("<input type='submit' name='action'
value='store'/>");
+ out.println("</form>");
+}]]></programlisting>
+
+ <para>
+ The <literal>listEvents()</literal> method uses the
Hibernate
+ <literal>Session</literal> bound to the current thread to
execute
+ a query:
+ </para>
+
+ <programlisting><![CDATA[private void listEvents(PrintWriter out,
SimpleDateFormat dateFormatter) {
+
+ List result = HibernateUtil.getSessionFactory()
+ .getCurrentSession().createCriteria(Event.class).list();
+ if (result.size() > 0) {
+ out.println("<h2>Events in database:</h2>");
+ out.println("<table border='1'>");
+ out.println("<tr>");
+ out.println("<th>Event title</th>");
+ out.println("<th>Event date</th>");
+ out.println("</tr>");
+ for (Iterator it = result.iterator(); it.hasNext();) {
+ Event event = (Event) it.next();
+ out.println("<tr>");
+ out.println("<td>" + event.getTitle() +
"</td>");
+ out.println("<td>" + dateFormatter.format(event.getDate()) +
"</td>");
+ out.println("</tr>");
+ }
+ out.println("</table>");
+ }
+}]]></programlisting>
+
+ <para>
+ Finally, the <literal>store</literal> action is dispatched to
the
+ <literal>createAndStoreEvent()</literal> method, which also
uses
+ the <literal>Session</literal> of the current thread:
+ </para>
+
+ <programlisting><![CDATA[protected void createAndStoreEvent(String
title, Date theDate) {
+ Event theEvent = new Event();
+ theEvent.setTitle(title);
+ theEvent.setDate(theDate);
+
+ HibernateUtil.getSessionFactory()
+ .getCurrentSession().save(theEvent);
+}]]></programlisting>
+
+ <para>
+ That's it, the servlet is complete. A request to the servlet will be
processed
+ in a single <literal>Session</literal> and
<literal>Transaction</literal>. As
+ earlier in the standalone application, Hibernate can automatically bind
these
+ ojects to the current thread of execution. This gives you the freedom to
layer
+ your code and access the <literal>SessionFactory</literal> in
any way you like.
+ Usually you'd use a more sophisticated design and move the data
access code
+ into data access objects (the DAO pattern). See the Hibernate Wiki for
more
+ examples.
+ </para>
+
+ </sect2>
+
+ <sect2 id="tutorial-webapp-deploy">
+ <title>Deploying and testing</title>
+
+ <para>
+ To deploy this application you have to create a web archive, a WAR. Add
the
+ following Ant target to your <literal>build.xml</literal>:
+ </para>
+
+<programlisting><![CDATA[<target name="war"
depends="compile">
+ <war destfile="hibernate-tutorial.war" webxml="web.xml">
+ <lib dir="${librarydir}">
+ <exclude name="jsdk*.jar"/>
+ </lib>
+
+ <classes dir="${targetdir}"/>
+ </war>
+</target>]]></programlisting>
+
+ <para>
+ This target creates a file called
<literal>hibernate-tutorial.war</literal>
+ in your project directory. It packages all libraries and the
<literal>web.xml</literal>
+ descriptor, which is expected in the base directory of your project:
+ </para>
+
+ <programlisting><![CDATA[<?xml version="1.0"
encoding="UTF-8"?>
+<web-app version="2.4"
+
xmlns="http://java.sun.com/xml/ns/j2ee"
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+
+ <servlet>
+ <servlet-name>Event Manager</servlet-name>
+ <servlet-class>events.EventManagerServlet</servlet-class>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Event Manager</servlet-name>
+ <url-pattern>/eventmanager</url-pattern>
+ </servlet-mapping>
+</web-app>]]></programlisting>
+
+ <para>
+ Before you compile and deploy the web application, note that an
additional library
+ is required: <literal>jsdk.jar</literal>. This is the Java
servlet development kit,
+ if you don't have this library already, get it from the Sun website
and copy it to
+ your library directory. However, it will be only used for compliation and
excluded
+ from the WAR package.
+ </para>
+
+ <para>
+ To build and deploy call <literal>ant war</literal> in your
project directory
+ and copy the <literal>hibernate-tutorial.war</literal> file
into your Tomcat
+ <literal>webapp</literal> directory. If you don't have
Tomcat installed, download
+ it and follow the installation instructions. You don't have to change
any Tomcat
+ configuration to deploy this application though.
+ </para>
+
+ <para>
+ Once deployed and Tomcat is running, access the application at
+
<literal>http://localhost:8080/hibernate-tutorial/eventmanager</literal>.
Make
+ sure you watch the Tomcat log to see Hibernate initialize when the first
+ request hits your servlet (the static initializer in
<literal>HibernateUtil</literal>
+ is called) and to get the detailed output if any exceptions occurs.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="tutorial-summary" revision="1">
+ <title>Summary</title>
+
+ <para>
+ This tutorial covered the basics of writing a simple standalone Hibernate
application
+ and a small web application.
+ </para>
+
+ <para>
+ If you already feel confident with Hibernate, continue browsing through the
reference
+ documentation table of contents for topics you find interesting - most asked
are
+ transactional processing (<xref linkend="transactions"/>),
fetch
+ performance (<xref linkend="performance"/>), or the usage of
the API (<xref linkend="objectstate"/>)
+ and the query features (<xref
linkend="objectstate-querying"/>).
+ </para>
+
+ <para>
+ Don't forget to check the Hibernate website for more (specialized)
tutorials.
+ </para>
+
+ </sect1>
+
+</chapter>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/tutorial1.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/modules/xml.xml
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/modules/xml.xml 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/modules/xml.xml 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,289 @@
+<chapter id="xml">
+ <title>Mapeamento XML</title>
+
+ <para><emphasis>
+ Note that this is an experimental feature in Hibernate 3.0 and is under
+ extremely active development.
+ Veja que essa é uma feature experimental no Hibernate 3.0 e o
+ desenvolvimento esta bastante ativo.
+
+ </emphasis></para>
+
+ <sect1 id="xml-intro" revision="1">
+ <title>Trabalhando com dados em XML</title>
+
+ <para>
+ O Hibernate permite que se trabalhe com dados persistentes em XML quase
+ da mesma maneira como você trabalhar com POJOs persistentes. Uma árvore XML
+ parseada, pode ser imaginada como apenas uma maneira de representar os
+ dados relacionais como objetos, ao invés dos POJOs.
+ </para>
+
+ <para>
+ O Hibernate suporta a API dom4j para manipular árvores XML. Você pode
escrever
+ queries que retornem árvores dom4j do banco de dados e automaticamente
+ sincronizar com o banco de dados qualquer modificação feita nessas árvores.
+ Você pode até mesmo pegar um documento XML, parsear usando o dom4j, e
escrever
+ as alterações no banco de dados usando quaisquer operações básicas do
Hibernate:
+ <literal>persist(), saveOrUpdate(),merge(), delete(),
replicate()</literal>
+ (merging ainda não é suportado)
+ </para>
+
+ <para>
+ Essa funcionalidade tem várias aplicações incluindo importação/exportação de
dados,
+ externalização de dados de entidade via JMS or SOAP e relatórios usando
XSLT.
+ </para>
+
+ <para>
+ Um mapeamento simples pode ser usado para simultaneamente mapear propriedades
+ da classe e nós de um documento XML para um banco de dados ou, se não houver
+ classe para mapear, pode ser usado simplesmente para mapear o XML.
+ </para>
+
+ <sect2 id="xml-intro-mapping">
+ <title>Especificando o mapeamento de uma classe e de um arquivo XML
simultaneamente</title>
+
+ <para>
+ Segue um exemplo de como mapear um POJO e um XML ao mesmo tempo:
+ </para>
+
+ <programlisting><![CDATA[<class name="Account"
+ table="ACCOUNTS"
+ node="account">
+
+ <id name="accountId"
+ column="ACCOUNT_ID"
+ node="@id"/>
+
+ <many-to-one name="customer"
+ column="CUSTOMER_ID"
+ node="customer/@id"
+ embed-xml="false"/>
+
+ <property name="balance"
+ column="BALANCE"
+ node="balance"/>
+
+ ...
+
+</class>]]></programlisting>
+ </sect2>
+
+ <sect2 id="xml-onlyxml">
+ <title>Especificando somente um mapeamento XML</title>
+
+ <para>
+ Segue um exemplo que não contém uma classe POJO:
+ </para>
+
+ <programlisting><![CDATA[<class entity-name="Account"
+ table="ACCOUNTS"
+ node="account">
+
+ <id name="id"
+ column="ACCOUNT_ID"
+ node="@id"
+ type="string"/>
+
+ <many-to-one name="customerId"
+ column="CUSTOMER_ID"
+ node="customer/@id"
+ embed-xml="false"
+ entity-name="Customer"/>
+
+ <property name="balance"
+ column="BALANCE"
+ node="balance"
+ type="big_decimal"/>
+
+ ...
+
+</class>]]></programlisting>
+
+ <para>
+ Esse mapeamento permite que você acesse os dados como uma árvore dom4j ou
um
+ grafo de de pares nome de propriedade/valor
(<literal>Map</literal>s do Java).
+ Os nomes de propriedades são somente construções lógicas que podem ser
+ referenciadas em consultas HQL.
+ </para>
+
+ </sect2>
+
+ </sect1>
+
+ <sect1 id="xml-mapping" revision="1">
+ <title>Mapeando metadados com XML</title>
+
+ <para>
+ Muitos elementos do mapeamento do Hibernate aceitam o atributo
<literal>node</literal>.
+ Por meio dele, você pode especificar o nome de um atributo ou elemento XML
que contém
+ a propriedade ou os dados da entidade. O formato do atributo
<literal>node</literal>
+ deve ser o seguinte:
+ </para>
+
+ <itemizedlist spacing="compact">
+ <listitem>
+ <para><literal>"element-name"</literal> - mapeia
para o elemento XML com determinado nome</para>
+ </listitem>
+ <listitem>
+ <para><literal>"@attribute-name"</literal> -
mapeia para o atributo XML com determinado nome</para>
+ </listitem>
+ <listitem>
+ <para><literal>"."</literal> - mapeia para o
elemento pai</para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>"element-name/@attribute-name"</literal> -
+ mapeia para para o atributo com determinado nome do elemento com
determinado nome
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Para coleções e associações simples, existe o atributo adicional
<literal>embed-xml</literal>.
+ Se o atributo <literal>embed-xml="true"</literal>, que
é o valor padrão, a árvore XML para a
+ entidade associada (ou coleção de determinado tipo de valor) será embutida
diretamente na
+ árvore XML que contém a associação. Por outro lado, se
<literal>embed-xml="false"</literal>,
+ então apenas o valor do identificador referenciado irá aparecer no XML para
associações
+ simples e coleções simplesmentenão irão aparecer.
+ </para>
+
+ <para>
+ Você precisa tomar cuidado em não deixar
o<literal>embed-xml="true"</literal>
+ para muitas associações, pois o XML não suporta bem referências circulares.
+ </para>
+
+ <programlisting><![CDATA[<class name="Customer"
+ table="CUSTOMER"
+ node="customer">
+
+ <id name="id"
+ column="CUST_ID"
+ node="@id"/>
+
+ <map name="accounts"
+ node="."
+ embed-xml="true">
+ <key column="CUSTOMER_ID"
+ not-null="true"/>
+ <map-key column="SHORT_DESC"
+ node="@short-desc"
+ type="string"/>
+ <one-to-many entity-name="Account"
+ embed-xml="false"
+ node="account"/>
+ </map>
+
+ <component name="name"
+ node="name">
+ <property name="firstName"
+ node="first-name"/>
+ <property name="initial"
+ node="initial"/>
+ <property name="lastName"
+ node="last-name"/>
+ </component>
+
+ ...
+
+</class>]]></programlisting>
+
+ <para>
+ Nesse caso, decidimos embutir a colenção de account ids, e não os dados de
accounts.
+ A query HQL a seguir:
+ </para>
+
+ <programlisting><![CDATA[from Customer c left join fetch c.accounts
where c.lastName like :lastName]]></programlisting>
+
+ <para>
+ Retornaria um conjunto de dados como esse:
+ </para>
+
+ <programlisting><![CDATA[<customer id="123456789">
+ <account short-desc="Savings">987632567</account>
+ <account short-desc="Credit Card">985612323</account>
+ <name>
+ <first-name>Gavin</first-name>
+ <initial>A</initial>
+ <last-name>King</last-name>
+ </name>
+ ...
+</customer>]]></programlisting>
+
+ <para>
+ Se você setar <literal>embed-xml="true"</literal> em um
mapeamento
+ <literal><one-to-many></literal>, os dados se
pareceriam com o seguinte:
+ </para>
+
+ <programlisting><![CDATA[<customer id="123456789">
+ <account id="987632567" short-desc="Savings">
+ <customer id="123456789"/>
+ <balance>100.29</balance>
+ </account>
+ <account id="985612323" short-desc="Credit Card">
+ <customer id="123456789"/>
+ <balance>-2370.34</balance>
+ </account>
+ <name>
+ <first-name>Gavin</first-name>
+ <initial>A</initial>
+ <last-name>King</last-name>
+ </name>
+ ...
+</customer>]]></programlisting>
+
+ </sect1>
+
+
+ <sect1 id="xml-manipulation" revision="1">
+ <title>Manipulando dados em XML</title>
+
+ <para>
+ Vamos reler e atualizar documentos em XML em nossa aplicação. Nós fazemos
isso
+ obtendo uma session do dom4j:
+ </para>
+
+ <programlisting><![CDATA[Document doc = ....;
+
+Session session = factory.openSession();
+Session dom4jSession = session.getSession(EntityMode.DOM4J);
+Transaction tx = session.beginTransaction();
+
+List results = dom4jSession
+ .createQuery("from Customer c left join fetch c.accounts where c.lastName like
:lastName")
+ .list();
+for ( int i=0; i<results.size(); i++ ) {
+ //add the customer data to the XML document
+ Element customer = (Element) results.get(i);
+ doc.add(customer);
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ <programlisting><![CDATA[Session session = factory.openSession();
+Session dom4jSession = session.getSession(EntityMode.DOM4J);
+Transaction tx = session.beginTransaction();
+
+Element cust = (Element) dom4jSession.get("Customer", customerId);
+for ( int i=0; i<results.size(); i++ ) {
+ Element customer = (Element) results.get(i);
+ //change the customer name in the XML and database
+ Element name = customer.element("name");
+ name.element("first-name").setText(firstName);
+ name.element("initial").setText(initial);
+ name.element("last-name").setText(lastName);
+}
+
+tx.commit();
+session.close();]]></programlisting>
+
+ <para>
+ É extremamente útil combinar essa funcionalidade com a operação
<literal>replicate()</literal>
+ do Hibernate para implementar importação/exportação baseadas em XML.
+ </para>
+
+ </sect1>
+
+</chapter>
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/modules/xml.xml
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/styles/fopdf.xsl
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/styles/fopdf.xsl 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/styles/fopdf.xsl 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,516 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL FO configuration file for the Hibernate
+ Reference Documentation. It defines a custom titlepage and
+ the parameters for the A4 sized PDF printable output.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian(a)hibernate.org
+
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../support/docbook-xsl/">
+]>
+
+<xsl:stylesheet
+ version="1.0"
+
xmlns="http://www.w3.org/TR/xhtml1/transitional"
+
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+
xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ exclude-result-prefixes="#default">
+
+ <xsl:import href="&db_xsl_path;/fo/docbook.xsl"/>
+
+ <!--###################################################
+ Custom Title Page
+ ################################################### -->
+
+ <xsl:template name="book.titlepage.recto">
+ <fo:block>
+ <fo:table table-layout="fixed" width="175mm">
+ <fo:table-column column-width="175mm"/>
+ <fo:table-body>
+ <fo:table-row>
+ <fo:table-cell text-align="center">
+ <fo:block>
+ <fo:external-graphic
src="file:images/hibernate_logo_a.png"/>
+ </fo:block>
+ <fo:block font-family="Helvetica"
font-size="18pt" padding-before="10mm">
+ <xsl:value-of
select="bookinfo/subtitle"/>
+ </fo:block>
+ <fo:block font-family="Helvetica"
font-size="12pt" padding="10mm">
+ Version:
+ <xsl:value-of
select="bookinfo/releaseinfo"/>
+ </fo:block>
+ </fo:table-cell>
+ </fo:table-row>
+ </fo:table-body>
+ </fo:table>
+ </fo:block>
+ </xsl:template>
+
+ <!-- Prevent blank pages in output -->
+ <xsl:template name="book.titlepage.before.verso">
+ </xsl:template>
+ <xsl:template name="book.titlepage.verso">
+ </xsl:template>
+ <xsl:template name="book.titlepage.separator">
+ </xsl:template>
+
+ <!--###################################################
+ Header
+ ################################################### -->
+
+ <!-- More space in the center header for long text -->
+ <xsl:attribute-set name="header.content.properties">
+ <xsl:attribute name="font-family">
+ <xsl:value-of select="$body.font.family"/>
+ </xsl:attribute>
+ <xsl:attribute name="margin-left">-5em</xsl:attribute>
+ <xsl:attribute name="margin-right">-5em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Custom Footer
+ ################################################### -->
+
+ <!-- This footer prints the Hibernate version number on the left side -->
+ <xsl:template name="footer.content">
+ <xsl:param name="pageclass" select="''"/>
+ <xsl:param name="sequence" select="''"/>
+ <xsl:param name="position" select="''"/>
+ <xsl:param name="gentext-key" select="''"/>
+
+ <xsl:variable name="Version">
+ <xsl:choose>
+ <xsl:when test="//releaseinfo">
+ <xsl:text>Hibernate </xsl:text>
+ <xsl:value-of select="//releaseinfo"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- nop -->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="$sequence='blank'">
+ <xsl:choose>
+ <xsl:when test="$double.sided != 0 and $position =
'left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and $position =
'center'">
+ <!-- nop -->
+ </xsl:when>
+
+ <xsl:otherwise>
+ <fo:page-number/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+
+ <xsl:when test="$pageclass='titlepage'">
+ <!-- nop: other titlepage sequences have no footer -->
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'even' and
$position='left'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'odd' and
$position='right'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and
$position='right'">
+ <fo:page-number/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'odd' and
$position='left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided != 0 and $sequence = 'even' and
$position='right'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:when test="$double.sided = 0 and
$position='left'">
+ <xsl:value-of select="$Version"/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <!-- nop -->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--###################################################
+ Custom Toc Line
+ ################################################### -->
+
+ <!-- Improve the TOC. -->
+ <xsl:template name="toc.line">
+ <xsl:variable name="id">
+ <xsl:call-template name="object.id"/>
+ </xsl:variable>
+
+ <xsl:variable name="label">
+ <xsl:apply-templates select="."
mode="label.markup"/>
+ </xsl:variable>
+
+ <fo:block text-align-last="justify"
+ end-indent="{$toc.indent.width}pt"
+ last-line-end-indent="-{$toc.indent.width}pt">
+ <fo:inline keep-with-next.within-line="always">
+ <fo:basic-link internal-destination="{$id}">
+
+ <!-- Chapter titles should be bold. -->
+ <xsl:choose>
+ <xsl:when test="local-name(.) =
'chapter'">
+ <xsl:attribute
name="font-weight">bold</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+
+ <xsl:if test="$label != ''">
+ <xsl:copy-of select="$label"/>
+ <xsl:value-of
select="$autotoc.label.separator"/>
+ </xsl:if>
+ <xsl:apply-templates select="."
mode="titleabbrev.markup"/>
+ </fo:basic-link>
+ </fo:inline>
+ <fo:inline keep-together.within-line="always">
+ <xsl:text> </xsl:text>
+ <fo:leader leader-pattern="dots"
+ leader-pattern-width="3pt"
+ leader-alignment="reference-area"
+ keep-with-next.within-line="always"/>
+ <xsl:text> </xsl:text>
+ <fo:basic-link internal-destination="{$id}">
+ <fo:page-number-citation ref-id="{$id}"/>
+ </fo:basic-link>
+ </fo:inline>
+ </fo:block>
+ </xsl:template>
+
+ <!--###################################################
+ Extensions
+ ################################################### -->
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <!-- FOP provide only PDF Bookmarks at the moment -->
+ <xsl:param name="fop.extensions">1</xsl:param>
+
+ <!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+ <!-- Dot and Whitespace as separator in TOC between Label and Title-->
+ <xsl:param name="autotoc.label.separator" select="'.
'"/>
+
+
+ <!--###################################################
+ Paper & Page Size
+ ################################################### -->
+
+ <!-- Paper type, no headers on blank pages, no double sided printing -->
+ <xsl:param name="paper.type" select="'A4'"/>
+ <xsl:param name="double.sided">0</xsl:param>
+ <xsl:param name="headers.on.blank.pages">0</xsl:param>
+ <xsl:param name="footers.on.blank.pages">0</xsl:param>
+
+ <!-- Space between paper border and content (chaotic stuff, don't touch)
-->
+ <xsl:param name="page.margin.top">5mm</xsl:param>
+ <xsl:param name="region.before.extent">10mm</xsl:param>
+ <xsl:param name="body.margin.top">10mm</xsl:param>
+
+ <xsl:param name="body.margin.bottom">15mm</xsl:param>
+ <xsl:param name="region.after.extent">10mm</xsl:param>
+ <xsl:param name="page.margin.bottom">0mm</xsl:param>
+
+ <xsl:param name="page.margin.outer">18mm</xsl:param>
+ <xsl:param name="page.margin.inner">18mm</xsl:param>
+
+ <!-- No intendation of Titles -->
+ <xsl:param name="title.margin.left">0pc</xsl:param>
+
+ <!--###################################################
+ Fonts & Styles
+ ################################################### -->
+
+ <!-- Default Font size -->
+ <xsl:param name="body.font.master">11</xsl:param>
+
+ <!-- Line height in body text -->
+ <xsl:param name="line-height">1.4</xsl:param>
+
+ <!-- Monospaced fonts are smaller than regular text -->
+ <xsl:attribute-set name="monospace.properties">
+ <xsl:attribute name="font-family">
+ <xsl:value-of select="$monospace.font.family"/>
+ </xsl:attribute>
+ <xsl:attribute name="font-size">0.8em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Tables
+ ################################################### -->
+
+ <!-- The table width should be adapted to the paper size -->
+ <xsl:param name="default.table.width">17.4cm</xsl:param>
+
+ <!-- Some padding inside tables -->
+ <xsl:attribute-set name="table.cell.padding">
+ <xsl:attribute name="padding-left">4pt</xsl:attribute>
+ <xsl:attribute name="padding-right">4pt</xsl:attribute>
+ <xsl:attribute name="padding-top">4pt</xsl:attribute>
+ <xsl:attribute name="padding-bottom">4pt</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Only hairlines as frame and cell borders in tables -->
+ <xsl:param
name="table.frame.border.thickness">0.1pt</xsl:param>
+ <xsl:param
name="table.cell.border.thickness">0.1pt</xsl:param>
+
+ <!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label"
select="1"/>
+
+ <!-- Label only Sections up to level 2 -->
+ <xsl:param name="local.l10n.xml"
select="document('')"/>
+ <l:i18n
xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
+ <l:l10n language="en">
+ <l:context name="title-numbered">
+ <l:template name="sect3" text="%t"/>
+ <l:template name="sect4" text="%t"/>
+ <l:template name="sect5" text="%t"/>
+ </l:context>
+ <l:context name="section-xref-numbered">
+ <l:template name="sect3" text="the section called
%t"/>
+ <l:template name="sect4" text="the section called
%t"/>
+ <l:template name="sect5" text="the section called
%t"/>
+ </l:context>
+ </l:l10n>
+ </l:i18n>
+
+ <!--###################################################
+ Titles
+ ################################################### -->
+
+ <!-- Chapter title size -->
+ <xsl:attribute-set name="chapter.titlepage.recto.style">
+ <xsl:attribute name="text-align">left</xsl:attribute>
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.8"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
+ Let's remove it, so this sucker can use our attribute-set only... -->
+ <xsl:template match="title"
mode="chapter.titlepage.recto.auto.mode">
+ <fo:block
xmlns:fo="http://www.w3.org/1999/XSL/Format"
+ xsl:use-attribute-sets="chapter.titlepage.recto.style">
+ <xsl:call-template name="component.title">
+ <xsl:with-param name="node"
select="ancestor-or-self::chapter[1]"/>
+ </xsl:call-template>
+ </fo:block>
+ </xsl:template>
+
+ <!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
+ <xsl:attribute-set name="section.title.level1.properties">
+ <xsl:attribute
name="space-before.optimum">0.8em</xsl:attribute>
+ <xsl:attribute
name="space-before.minimum">0.8em</xsl:attribute>
+ <xsl:attribute
name="space-before.maximum">0.8em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.5"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+ <xsl:attribute-set name="section.title.level2.properties">
+ <xsl:attribute
name="space-before.optimum">0.6em</xsl:attribute>
+ <xsl:attribute
name="space-before.minimum">0.6em</xsl:attribute>
+ <xsl:attribute
name="space-before.maximum">0.6em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.25"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+ <xsl:attribute-set name="section.title.level3.properties">
+ <xsl:attribute
name="space-before.optimum">0.4em</xsl:attribute>
+ <xsl:attribute
name="space-before.minimum">0.4em</xsl:attribute>
+ <xsl:attribute
name="space-before.maximum">0.4em</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master * 1.0"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Titles of formal objects (tables, examples, ...) -->
+ <xsl:attribute-set name="formal.title.properties"
use-attribute-sets="normal.para.spacing">
+ <xsl:attribute name="font-weight">bold</xsl:attribute>
+ <xsl:attribute name="font-size">
+ <xsl:value-of select="$body.font.master"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="hyphenate">false</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.4em</xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.6em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.8em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Programlistings
+ ################################################### -->
+
+ <!-- Verbatim text formatting (programlistings) -->
+ <xsl:attribute-set name="verbatim.properties">
+ <xsl:attribute
name="space-before.minimum">1em</xsl:attribute>
+ <xsl:attribute
name="space-before.optimum">1em</xsl:attribute>
+ <xsl:attribute
name="space-before.maximum">1em</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.1em</xsl:attribute>
+ <xsl:attribute name="border-color">#444444</xsl:attribute>
+ <xsl:attribute name="border-style">solid</xsl:attribute>
+ <xsl:attribute name="border-width">0.1pt</xsl:attribute>
+ <xsl:attribute name="padding-top">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-left">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-right">0.5em</xsl:attribute>
+ <xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
+ <xsl:attribute name="margin-left">0.5em</xsl:attribute>
+ <xsl:attribute name="margin-right">0.5em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Shade (background) programlistings -->
+ <xsl:param name="shade.verbatim">1</xsl:param>
+ <xsl:attribute-set name="shade.verbatim.style">
+ <xsl:attribute
name="background-color">#F0F0F0</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- We want to use callouts... -->
+ <xsl:param name="callout.extensions">1</xsl:param>
+
+ <!-- Place callout bullets at this column in programmlisting.-->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+ <!--
+ No, don't use crappy graphics for the callout bullets. This setting
+ enables some weird Unicode rendering for some fancy bullet points
+ in callouts. By default, this can only count to 10 and produces
+ strange results if you ever have more than 10 callouts for one
+ programlisting. We will fix that next.
+ -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!--
+ Again, fun with DocBook XSL: The callout bullets are rendered in
+ two places: In the programlisting itself and in the list below
+ the listing, with the actual callout text. The rendering in the
+ programlisting is some XSL transformer extension (e.g. a Saxon
+ extension), so we can't change that without messing with the
+ extensions. We only can turn it off by setting this limit to
+ zero, then, a simple bracket style like "(3)" and "(4)" will
+ be used in the programlisting.
+ -->
+ <xsl:param name="callout.unicode.number.limit"
select="'0'"></xsl:param>
+
+ <!--
+ The callout bullets in the actual callout list will be rendered
+ with an XSL FO template. The default template is broken: limited to 10
+ nice looking Unicode bullet points and then it doesn't print anything,
+ the fallback doesn't work. We implement our own template, which is not
+ as complicated, more ugly, but works. As always, function is more
+ important than form.
+ -->
+ <xsl:template name="callout-bug">
+ <xsl:param name="conum" select='1'/>
+ <fo:inline
+ color="black"
+ padding-top="0.1em"
+ padding-bottom="0.1em"
+ padding-start="0.2em"
+ padding-end="0.2em"
+ baseline-shift="0.1em"
+ font-family="{$monospace.font.family}"
+ font-weight="bold"
+ font-size="75%">
+ <xsl:text>(</xsl:text>
+ <xsl:value-of select="$conum"/>
+ <xsl:text>)</xsl:text>
+ </fo:inline>
+
+ </xsl:template>
+
+ <!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Correct placement of titles for figures and examples. -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+ <!-- Format Variable Lists as Blocks (prevents horizontal overflow). -->
+ <xsl:param name="variablelist.as.blocks">1</xsl:param>
+
+ <!-- The horrible list spacing problems, this is much better. -->
+ <xsl:attribute-set name="list.block.spacing">
+ <xsl:attribute
name="space-before.optimum">0.8em</xsl:attribute>
+ <xsl:attribute
name="space-before.minimum">0.8em</xsl:attribute>
+ <xsl:attribute
name="space-before.maximum">0.8em</xsl:attribute>
+ <xsl:attribute
name="space-after.optimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.minimum">0.1em</xsl:attribute>
+ <xsl:attribute
name="space-after.maximum">0.1em</xsl:attribute>
+ </xsl:attribute-set>
+
+ <!-- Newer DocBook XSL apparently thinks that some sections are by
+ default "draft" status, and this idiotic thing is by default
+ also set to "maybe", so it spits out a lot of errors with the
+ latest FOP as the XSL/FO styles have references to some draft
+ watermarks, which you actually don't want in the first place.
+ Turn this crap off. If you have to work with the "status"
+ attribute, don't.
+ -->
+ <xsl:param name="draft.mode" select="'no'"/>
+
+</xsl:stylesheet>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/styles/fopdf.xsl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/styles/html.css
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/styles/html.css 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/styles/html.css 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,97 @@
+A {
+ color: #003399;
+}
+
+A:active {
+ color: #003399;
+}
+
+A:visited {
+ color: #888888;
+}
+
+P, OL, UL, LI, DL, DT, DD, BLOCKQUOTE {
+ color: #000000;
+}
+
+TD, TH, SPAN {
+ color: #000000;
+}
+
+BLOCKQUOTE {
+ margin-right: 0px;
+}
+
+
+H1, H2, H3, H4, H5, H6 {
+ color: #000000;
+ font-weight:500;
+ margin-top:10px;
+ padding-top:15px;
+}
+
+TABLE {
+ border-collapse: collapse;
+ border-spacing:0;
+ border: 1px thin black;
+ empty-cells: hide;
+}
+
+TD {
+ padding: 4pt;
+}
+
+H1 { font-size: 150%; }
+H2 { font-size: 140%; }
+H3 { font-size: 110%; font-weight: bold; }
+H4 { font-size: 110%; font-weight: bold;}
+H5 { font-size: 100%; font-style: italic; }
+H6 { font-size: 100%; font-style: italic; }
+
+TT {
+font-size: 90%;
+ font-family: "Courier New", Courier, monospace;
+ color: #000000;
+}
+
+PRE {
+font-size: 100%;
+ padding: 5px;
+ border-style: solid;
+ border-width: 1px;
+ border-color: #CCCCCC;
+ background-color: #F4F4F4;
+}
+
+UL, OL, LI {
+ list-style: disc;
+}
+
+HR {
+ width: 100%;
+ height: 1px;
+ background-color: #CCCCCC;
+ border-width: 0px;
+ padding: 0px;
+ color: #CCCCCC;
+}
+
+.variablelist {
+ padding-top: 10;
+ padding-bottom:10;
+ margin:0;
+}
+
+.itemizedlist, UL {
+ padding-top: 0;
+ padding-bottom:0;
+ margin:0;
+}
+
+.term {
+ font-weight:bold;
+}
+
+
+
+
Property changes on: trunk/Hibernate3/doc/reference/pt-br/styles/html.css
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/styles/html.xsl
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/styles/html.xsl 2006-08-14 14:43:45 UTC (rev
10261)
+++ trunk/Hibernate3/doc/reference/pt-br/styles/html.xsl 2006-08-14 14:55:10 UTC (rev
10262)
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL HTML configuration file for the Hibernate
+ Reference Documentation.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian(a)hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../support/docbook-xsl/">
+]>
+
+<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0"
+
xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="&db_xsl_path;/html/docbook.xsl"/>
+
+<!--###################################################
+ HTML Settings
+ ################################################### -->
+
+ <xsl:param
name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <xsl:param name="callout.extensions">1</xsl:param>
+ <xsl:param name="graphicsize.extension">0</xsl:param>
+
+<!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+<!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label"
select="1"/>
+
+<!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- Don't use graphics, use a simple number style -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!-- Place callout marks at this column in annotated areas -->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Placement of titles -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+</xsl:stylesheet>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/styles/html.xsl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/Hibernate3/doc/reference/pt-br/styles/html_chunk.xsl
===================================================================
--- trunk/Hibernate3/doc/reference/pt-br/styles/html_chunk.xsl 2006-08-14 14:43:45 UTC
(rev 10261)
+++ trunk/Hibernate3/doc/reference/pt-br/styles/html_chunk.xsl 2006-08-14 14:55:10 UTC
(rev 10262)
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+
+<!--
+
+ This is the XSL HTML configuration file for the Hibernate
+ Reference Documentation.
+
+ It took me days to figure out this stuff and fix most of
+ the obvious bugs in the DocBook XSL distribution. Some of
+ the workarounds might not be appropriate with a newer version
+ of DocBook XSL. This file is released as part of Hibernate,
+ hence LGPL licensed.
+
+ christian(a)hibernate.org
+-->
+
+<!DOCTYPE xsl:stylesheet [
+ <!ENTITY db_xsl_path "../../support/docbook-xsl/">
+]>
+
+<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0"
+
xmlns="http://www.w3.org/TR/xhtml1/transitional"
+ exclude-result-prefixes="#default">
+
+<xsl:import href="&db_xsl_path;/html/chunk.xsl"/>
+
+<!--###################################################
+ HTML Settings
+ ################################################### -->
+
+ <xsl:param name="chunk.section.depth">'5'</xsl:param>
+ <xsl:param name="use.id.as.filename">'1'</xsl:param>
+ <xsl:param
name="html.stylesheet">../shared/css/html.css</xsl:param>
+
+ <!-- These extensions are required for table printing and other stuff -->
+ <xsl:param name="use.extensions">1</xsl:param>
+ <xsl:param name="tablecolumns.extension">0</xsl:param>
+ <xsl:param name="callout.extensions">1</xsl:param>
+ <xsl:param name="graphicsize.extension">0</xsl:param>
+
+<!--###################################################
+ Table Of Contents
+ ################################################### -->
+
+ <!-- Generate the TOCs for named components only -->
+ <xsl:param name="generate.toc">
+ book toc
+ </xsl:param>
+
+ <!-- Show only Sections up to level 3 in the TOCs -->
+ <xsl:param name="toc.section.depth">3</xsl:param>
+
+<!--###################################################
+ Labels
+ ################################################### -->
+
+ <!-- Label Chapters and Sections (numbering) -->
+ <xsl:param name="chapter.autolabel">1</xsl:param>
+ <xsl:param name="section.autolabel" select="1"/>
+ <xsl:param name="section.label.includes.component.label"
select="1"/>
+
+<!--###################################################
+ Callouts
+ ################################################### -->
+
+ <!-- Don't use graphics, use a simple number style -->
+ <xsl:param name="callout.graphics">0</xsl:param>
+
+ <!-- Place callout marks at this column in annotated areas -->
+ <xsl:param name="callout.defaultcolumn">90</xsl:param>
+
+<!--###################################################
+ Misc
+ ################################################### -->
+
+ <!-- Placement of titles -->
+ <xsl:param name="formal.title.placement">
+ figure after
+ example before
+ equation before
+ table before
+ procedure before
+ </xsl:param>
+
+</xsl:stylesheet>
Property changes on: trunk/Hibernate3/doc/reference/pt-br/styles/html_chunk.xsl
___________________________________________________________________
Name: svn:executable
+ *