HIBERNATE/Java & ORACLE Overview of technology for Hibernate 3 as of 1/2006 By Joel A.
Download ReportTranscript HIBERNATE/Java & ORACLE Overview of technology for Hibernate 3 as of 1/2006 By Joel A.
HIBERNATE/Java & ORACLE Overview of technology for Hibernate 3 as of 1/2006 By Joel A. Thompson ([email protected]) Goal: Present Hibernate to first time users, and get you started with all the major concepts right away. copyright 2006, rhinosystemsinc.com all rights reserved What we'll Cover • Introduction of HibernateV3 Configuration & Setup of Hibernate/Java • Code • Pros and Cons • RESOURCES • Q & A. copyright 2006, rhinosystemsinc.com all rights reserved Intro:About Hibernate • www.hibernate.org - Open Source since, and now with JBoss (since late 2003) w/ commercial support & training. Founder: Gavin King • Provides a layer for java to interact with the database. – Is technically a set of java-class libraries that you use to gain access to your database • Hibernate caches database objects – & Hibernate services your Java program copyright 2006, rhinosystemsinc.com all rights reserved 1/3 Intro:About Hibernate • Hibernate layer resides in your JVM. • Improves performance – objects are cached in JVM and mapped to your object model. • Used in commercial applications – JBoss for one (yes, another open source…) – Many more opensource and commercial listed at: http://www.hibernate.org/27.html copyright 2006, rhinosystemsinc.com all rights reserved 2/3 Intro:About Hibernate • Hibernate is highly customizable – – – – – Caching (2nd level cache). Database dialects Transaction Connection pooling Custom Types • Or use out of box (recommend changing: connection pooling). copyright 2006, rhinosystemsinc.com all rights reserved 3/3 Intro:Importance of DAO • DAO: Data Access Objects – design/pattern • Purpose is to abstract your calls to the database. – Don't put SQL directly into your Java/JSP. • You can change our database with minimal affect on your code • Identify bottle necks and bugs easier. copyright 2006, rhinosystemsinc.com all rights reserved 1/2 Intro:Importance of DAO • Better design translates into easier to understand code. • Hibernate DAO - 3rd party technology – Benefits of common knowledge – Fixes to technology – Specialized for each database and optimized for database access (caveats). copyright 2006, rhinosystemsinc.com all rights reserved 2/2 Intro:Comparison to SQL • Problem with SQL – never lived up to promise of standardization amongst database vendors – Uses Jdbc to access database – (no forced design) – Is Relational • With Hibernate: – – – – Caching Easier to code Standard access Is Object Oriented and maps to Relational. copyright 2006, rhinosystemsinc.com all rights reserved 1/2 Intro:Comparison to SQL • Speed/performance – Prepared Statements and caching (hib) – Can batch process many DML statements. (hib) – Better performance from PL/SQL (sql/hib) • Maintenance/Updates (hib) • Legacy system (depends) – Using hibernate with legacy database systems & Legacy java code retrofit with Hibernate copyright 2006, rhinosystemsinc.com all rights reserved 2/2 Configuration Hibernate/Java • Download and install JDK 1.4 or 1.5 • Download version3 from www.hibernate.org • Setup Hibernate's Jars into your project's classpath. – The hibernate3.jar into your project's classpath; and if need be all the <hib>/lib (if you don't already have them). copyright 2006, rhinosystemsinc.com all rights reserved 1/5 Config:hibernate.properties • Make sure that Oracle's client jdbc lib is in your CLASSPATH • Hibernate.properties needs to be in your project's & runtime classpath. HIBERNATE.PROPERTIES #for OCI (local instance of Oracle, not using tnsnames.ora). hibernate.dialect=org.hibernate.dialect.OracleDialect hibernate.connection.driver_class=oracle.jdbc.driver.OracleDriver hibernate.connection.username=joel hibernate.connection.password=xyz hibernate.connection.pool_size=5 hibernate.connection.url=jdbc:oracle:oci:@ hibernate.show_sql=true copyright 2006, rhinosystemsinc.com all rights reserved 2/5 Config: Download & Config Xdoclet [OPTIONAL] • In order to run the "generation" of hibernate XML you need to setup your classpath to include Xdoclet libraries • Download latest (v1.2.3) from http://xdoclet.sourceforge.net/xdoclet/index.html (www.xdoclet.org?) – Download direct from http://sourceforge.net/project/showfiles.php?group_id=31602 – Tag References http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html copyright 2006, rhinosystemsinc.com all rights reserved 3/5 config: Download & Config ANT [OPTIONAL] • In order to use ANT you'll need to setup your PATH to include ANT. Check – run "ant" • Download latest (v1.6.5) from http://ant.apache.org/ (www.ant.org?) – Download direct from http://www.axint.net/apache/ant/binaries/apache-ant-1.6.5-bin.zip – Unzip and make sure "ant" is in your path. (right-click my computer -> properties ->Advanced->Environmental Variables -> update PATH with directory <ant_install>/bin) copyright 2006, rhinosystemsinc.com all rights reserved 4/5 config: Download & Config ANT • SUMMARY: – JDK [required]: PATH,CLASSPATH – HIBERNATE [required]: CLASSPATH • ORACLE or DBMS client [required]: CLASSPATH (connection/lib info w/ hibernate.properties) – XDOCLET [optional]:CLASSPATH – ANT [optional]:CLASSPATH copyright 2006, rhinosystemsinc.com all rights reserved 5/5 Code & Fragments • What we'll cover in the CODE section. For each of the items below you'll see the XML, the DDL SQL, Java code and an explanation. –Single Entity –Primary Keys –Many-to-One –Many-to-Many –DML (Query, Insert, Update, Delete) –Extra topics copyright 2006, rhinosystemsinc.com all rights reserved Code: Overview • Hibernate layer is independent of your code • Entities map via hibernate XML • Hibernate & you: DML, caching, isolation levels copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Java POJO Entity public class Person { Long PERSON_ID=null; //manufactured surrogate key String FIRST_NAME=null; String LAST_NAME=null; Standard get/set public Long getPERSON_ID(){…} need empty public void setPERSON_ID(String) {…} public String getFIRST_NAME(){…} constructor ~ public void setFIRST_NAME(String) {…} public String getLAST_NAME(){…} public void setLAST_NAME (String) {…} } & See SAMPLE 0 copyright 2006, rhinosystemsinc.com all rights reserved 1/4 Code[0]: XML for Entity <!--Must be named: Person.hbm.xml and reside in CLASSPATH--> <?xml <?xml version="1.0" version="1.0" encoding="UTF-8"?> encoding="UTF-8"?> <!DOCTYPE hibernate-mapping <!DOCTYPE hibernate-mapping PUBLIC PUBLIC "-//Hibernate/Hibernate "-//Hibernate/Hibernate Mapping MappingDTD DTD 3.0//EN" 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <hibernate-mapping> <class name="com.rhinosystemsinc.hibernate.samples_0.Person" table="SAMPLE0_Person" > <id name="PERSON_ID" column="PERSON_ID" type="java.lang.Long" unsaved-value="null"> <generator class="hilo"> class="hilo"> <generator <paramname="table">SAMPLE0_PERSON_SEQ</param> name="table">SAMPLE0_PERSON_SEQ</param> <param <paramname="column">NEXT</param> name="column">NEXT</param> <param </generator> </generator> </id> </id> <property <property name="FIRST_NAME" type="java.lang.String" update="true" insert="true" column="FIRST_NAME" not-null="true" unique="false" length="100" /> <property name="LAST_NAME"/> </class> </hibernate-mapping> Define the manufactured surrogate primary key, based on SEQUENCE. Also natural composite primary keys: <composite-id> <key-property name="name"/> <key-property name="ssn"/> copyright 2006, 2/4 </composite-id> rhinosystemsinc.com all rights reserved Code: Primary Keys • All hibernate persisted Entity mappings must have a primary key. • Suggestion: Use surrogate generated keys. – Hib supports natural keys ( & multi-column). – Reason: • Sometimes (rarely) keys will change values • Easier to manage copyright 2006, rhinosystemsinc.com all rights reserved 3/4 Code[0]: Java Main Class //SAVING A NEW OBJECT org.hibernate.Session sess = sessFact.openSession(); //more on SessionFactory in a minute. Person p = new Person(); p.setFIRST_NAME("John"); p.setLAST_NAME("Smith"); Transaction tx = sess.beginTransaction(); sess.saveOrUpdate(p); tx.commit(); At this point, what if we sess.close(); do an update, via SQLPLUS? See SAMPLE 0 copyright 2006, rhinosystemsinc.com all rights reserved 4/4 Code[0]: Java 1-to-Many public class Person { Long PERSON_ID=null; //manufactured surrogate key String FIRST_NAME=null; String LAST_NAME=null; Set ADDRESSES=null; public Set getADDRESSES() { return ADDRESSES; } public void setADDRESSES(Set ADDRESSES) { this.ADDRESSES = ADDRESSES; } …//rest of get/set methods } NEW copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Person XML 1-to-Many … <hibernate-mapping> <class name="com.rhinosystemsinc.hibernate.samples_0.Person" table="SAMPLE0_Person" > … <set name="ADDRESSES" lazy="false" inverse="true" all or save-update-delete cascade="save-update" sort="unsorted" Any records that don't have address will be shown too. outer-join="true"> <key column="PERSON_ID"/> Notice one-to-many ~ <one-to-many class="com.rhinosystemsinc.hibernate.samples_1.Address"/> </set> … </class> </hibernate-mapping> NEW copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: public class Address { Long ADDRESS_ID=null; String STREET=null; String APT_NO=null; String CITY=null; String STATE=null; String ZIP=null; Person person=null;// the person this address belongs to. public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } …//rest of get/set methods } Java 1-to-Many New Address class See Sample 1 Person reference ~ copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Address XML 1-to-Many Address class …usual header <class name="com.rhinosystemsinc.hibernate.samples_1.Address" table="SAMPLE1_Address" dynamic-update="true"> NOTICE different <id name="ADDRESS_ID" column="ADDRESS_ID" type="java.lang.Long" unsaved-value="null"> definition sample of <generator class="sequence"> the sequence <param name="sequence">SAMPLE1_ADDRESS_SEQ</param> <param name="parameters">INCREMENT BY 1 START WITH 1</param> </generator> Notice variable name in Address class </id> <many-to-one name="person" class="com.rhinosystemsinc.hibernate.samples_1.Person" For outer-join fetching or use 'select' cascade="save-update" fetch="join" sequential select fetching. N+1 select prob. will always be lazy="false" update="true" eagerly fetched. insert="true" ~ column="PERSON_ID" not-null="false"/> …rest of properties defined See Sample 1 copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: public static void main(String args[]) …. Address addr = new Address(); Person p = new Person(); p.setFIRST_NAME("John"); p.setLAST_NAME("Thompson"); p.setADDRESSES(new HashSet()); p.getADDRESSES().add(addr); p.setCreated(new Date()); addr.setSTREET("12345 Easy"); addr.setCITY("Sacramento"); addr.setSTATE("CA"); addr.setORDER_POS(new Long(1)); addr.setCreated(new Date()); addr.setPerson(p); … sess.save(p); tx.commit(); … … See Sample 1 main 1-to-Many Create an empty "set" and assign to Person Add the address to the "set" assign person reference to address ~ copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Java Many-to-Many public class Address { …same as before Set persons=null;// the person this address belongs to. public Set getPersons() { return persons; } public void setPersons(Set persons) { this.persons = persons; } …//rest of get/set methods } See Sample 2 copyright 2006, rhinosystemsinc.com all rights reserved NEW ~ Code[0]: XML Many-to-Many …usual header <class name=...Address> "Set persons=null" in java <set name="persons" Intermediate M-M table table="SAMPLE2_PERSON_ADDRESS"> <key column="ADDRESS_ID"/> M-M definition, <many-to-many class="com.rhinosystemsinc.hibernate.samples_2.Person" referencing the Person class by PERSON_ID column="PERSON_ID"/> ~ </set> …rest of properties defined </class> </hibernate-mapping> See Sample 1 copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Address addr = new Address(); Person p = new Person(); p.setFIRST_NAME("John"); p.setLAST_NAME("Thompson"); p.setADDRESSES(new HashSet()); p.getADDRESSES().add(addr); p.setCreated(new Date()); addr.setSTREET("12345 Easy"); … //revised! for many-to-many addr.setPersons(new HashSet()); addr.getPersons().add(p); //ADD NEW PERSON TO ADDRESS Person p2=new Person(); p2.setFIRST_NAME("Martha"); p2.setLAST_NAME("Thompson"); p2.setADDRESSES(new HashSet()); p2.getADDRESSES().add(addr); addr.getPersons().add(p2); See Sample 1 Main Many-to-Many Setup empty Address and Person object Create empty list of Addresses Martha also lives at the SAME address, here we add the address to the p2 object copyright 2006, rhinosystemsinc.com all rights reserved ~ Code[0]: Reference Data • Data that doesn't change usually loaded at system installation time. (Use 2nd level Cache). – Examples: STATES, CATEGORY, ZIP..etc. • Strategy – Setup XML class with element cache as read-only – Setup cache for relation as read-only – Call a method to load All read-only objects at initialization (actually even everytime). (for example…) copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Reference Data … <class name="com.rhinosystemsinc.sample.Event"> For the EVENT class … <many-to-one Variable name for java class name="CATEGORY" Category CATEGORY=null; class="com.rhinosystemsinc.sample.Category" cascade="none" which operations should be cascaded from update="false" the parent object to the associated object insert="false" We will not update or insert from this relationship. ~ column="CATEGORY_ID" not-null="true" /> </class> copyright 2006, rhinosystemsinc.com all rights reserved Code[0]: Reference Data For the CATEGORY class … <class name="com.rhinosystemsinc.sample.Category" mutable="false"> <cache usage="read-only" /> … </class> Set cache to be read-only Also - notice no need for a reference back to Event class ---------------------------------------------------------------------------------------------------------In your Java code, load the objects at least once… … org.hibernate.Query q = sess.createQuery("from Category"); q.setCacheMode(org.hibernate.CacheMode.NORMAL); q.setCacheable(true); java.util.List result = q.list(); Make sure your Query sets up the CACHING! (2nd level) ~ … copyright 2006, rhinosystemsinc.com all rights reserved Code: Components • Components "Fine-grained object Model" - more Classes than Tables – Value Type – not Entity reference • Meaning, you want separate Java class (from the main entity) for this property, and yet it is stored in DB with main entity • Lets Consider ZIP_CODE as example. • Address w/ ZipCode attribute • ZipCode defines ZIP_CODE and ZIP_4DIGIT_CODE as fields • Address Table has two fields in table (w/ same field names). copyright 2006, rhinosystemsinc.com all rights reserved Code: Component (example) //JAVA ADDRESS CLASS: public class Address { … ZipCode variable, name is same as ZipCode ZIP=null; mapping below. public ZipCode getZIP(){…} public void setZIP(ZipCode ZIP) } //Address.hbm.xml -----------------------------------------------------------------------------------------…usual header <class name="com.rhinosystemsinc.hibernate.samples_3.Address" Notice use of "component", with class table="SAMPLE3_Address" dynamic-update="true"> name ~ … <component name="ZIP" class="com.rhinosystemsinc.hibernate.samples_3.ZipCode"> … </class> copyright 2006, rhinosystemsinc.com all rights reserved Code: Component (example) //Java ZipCode Class public class ZipCode { NO ID // Components have NO ID...they are just entirely dependent on // containing Entity - in this case Address - in otherwords, // we want a Java Class representation of ZipCode, but want it // mapped into the Address table with ZIP_CODE and ZIP_4DIGIT_CODE // as attributes of Address table. String ZIP_CODE = ""; String ZIP_4DIGIT_CODE = ""; public String getZIP_4DIGIT_CODE(){…} public void setZIP_4DIGIT_CODE(String ZIP_4DIGIT_CODE){…} public String getZIP_CODE(){…} public void setZIP_CODE(String ZIP_CODE){…} } Two attributes w/ getters/setters In this example: Attribute names map directly to database column names ~ copyright 2006, rhinosystemsinc.com all rights reserved Code: //SQL for Address table: create table SAMPLE3_Address ( ADDRESS_ID number primary key, STREET varchar2(512), APT_NO varchar2(64), CITY varchar2(512), STATE varchar2(2), ZIP_CODE varchar2(5), ZIP_4DIGIT_CODE varchar2(4) ); Component (example) Notice same name as ZipCode variables. ~ copyright 2006, rhinosystemsinc.com all rights reserved Code: //Java Main Code Address addr = new Address(); Person p = new Person(); p.setFIRST_NAME("John"); p.setADDRESSES(new HashSet()); p.getADDRESSES().add(addr); addr.setSTREET("12345 Easy"); … ZipCode zip=new ZipCode(); zip.setZIP_CODE("95603"); zip.setZIP_4DIGIT_CODE("4456"); addr.setZIP(zip); addr.setPersons(new HashSet()); addr.getPersons().add(p); … sess.saveOrUpdate(p); Component (example) Usual initialization here. Create a ZipCode object, initialize it, and set to the Address Note: query returns an Address object w/ ZipCode filled in automatically. ~ copyright 2006, rhinosystemsinc.com all rights reserved Code: Querying • Hibernate offers a variety of ways to query the objects: – – – – SQL – straight SQL (parsed SQL 92 standard) HQL – hibernate's query language (SQL based) QBE – query by example Criteria Queries – Object oriented copyright 2006, rhinosystemsinc.com all rights reserved Code: • HQL simple example: Querying Use the session to create the Query object. Query q = sess.createQuery("from Person"); java.util.List result = q.list(); Can also use ? As positional param Then use: // ALSO First); Query q = sess.createQuery("from Person pq.setString(0, where " + q.setString(1, Last); "p.FIRST_NAME = :fname and " + "p.LAST_NAME =:lname"); q.setString("fname", First); //can also use positional parameters Returns a list, that you can iterate q.setString("lname", Last); through and cast the "objects" to java.util.List result = q.list(); Person. ~ See all examples for quering copyright 2006, rhinosystemsinc.com all rights reserved Code: Querying • HQL scalar example (from reference.pdf): Iterator results = sess.createQuery( "select cat.color, min(cat.birthdate), count(cat) from Cat cat " + "group by cat.color").list().iterator(); while ( results.hasNext() )Notice alias "cat" lowercase { Object[] column = (Object[]) results.next(); Notice cast – same as attribute Color type = (Color) column[0]; declared in Cat class ~ Date oldest = (Date) column[1]; Integer count = (Integer) column[2]; ..... } See all examples for quering copyright 2006, rhinosystemsinc.com all rights reserved Code: • SQL example: SQL Querying createSQLQuery org.hibernate.SQLQuery q = sess.createSQLQuery("select * " + " from SAMPLE0_PERSON" + " where " + " FIRST_NAME = :fname " + Tell hibernate about actual " and LAST_NAME = :lname"); class q.addEntity(Person.class); Bind parameters ~ q.setString("fname", First); //can also use positional parameters q.setString("lname", Last); See all examples for quering java.util.List copyright result2006, = q.list(); rhinosystemsinc.com all rights … reserved Code: SQL Querying • SQL example #2: With Alias org.hibernate.SQLQuery q = sess.createSQLQuery("select {Person.*} " + " from SAMPLE0_PERSON Person where " + " Person.FIRST_NAME = :fname " + " See also: and Person.LAST_NAME =:lname"); q.addScalar(String columnAlias, Type type). q.addEntity("Person",Person.class); q.addJoin(String alias, String path). Where path is the q.setString("fname", //can also path toFirst); the java collection member variable name ofuse the parent class. In our example it would be positional parameters "Person.ADDRESSES" ~ q.setString("lname", Last); java.util.List result = q.list(); … examples for quering See all copyright 2006, rhinosystemsinc.com all rights reserved Pros/Cons • Cons – Lots of idiosyncrasies. – caching, flushing, inverse…etc. (But can configure/disable them.) – Learning curve is fairly steep. (learn a way and stick with it). – Not good for bulk-inserts (batch processing) (forced to use PL/SQL within hibernate or jdbc) – Java-XML-table all defining entity (good and bad) – (xdoclet and other tools – setup system of generating base/core code elements – use patterns and conventions) copyright 2006, rhinosystemsinc.com all rights reserved Pros/Cons • Pros – Simple to understand concepts. – Stick with tools and frameworks, then can speed up development time. – Caching for you – so better performance. (if you don’t use cache, then similar to straight SQL w/ preparedstatement performance). – Highly extensible and customizable to suite your needs for new development and conversion. – Defacto standard, via OpenSource LGPL license, non proprietary, and known by developer community (cost, maintenance, bugs..etc.) copyright 2006, rhinosystemsinc.com all rights reserved Resources • Hibernate.org – is the best most up-to-date – FAQs : http://www.hibernate.org/5.html • Advanced Problems, Tips and Tricks, Performance and more… • Evaluation- http://www.hibernate.org/263.html – Doc link: http://www.hibernate.org/5.html – Migration (A MUST!) – http://www.hibernate.org/250.html • Package change: net.sf -> org.hibernate • SessionFactory • Criteria Query copyright 2006, rhinosystemsinc.com all rights reserved Resources • Hibernate installation – <installdir>/doc/{api,other,reference}/en/pdf/hibernate_reference. pdf (great for reference, yet not sufficient for beginners to "learn"). – <installdir>/eg – samples copyright 2006, rhinosystemsinc.com all rights reserved Resources • Miscellaneous – Book: Hibernate In Action http://www.manning.com/bauer – Performance #'s: http://www.sourcelabs.com/?sidemenu=3&page=software&sub=sash_hibernateperftest • Hibernate user FORUM - http://forum.hibernate.org/ (+200 msg/day) • CaveatEmptor Sample from Hibernate: http://caveatemptor.hibernate.org/ copyright 2006, rhinosystemsinc.com all rights reserved End 0f Presentation Thank you! • Extra topics session follow, if time. ~ Or ~ • Q&A • Future Questions: email: [email protected] copyright 2006, rhinosystemsinc.com all rights reserved XDoclet • XDoclet is used to generate hibernate XML files. – You specify annotation tags in your Java code – Run an xdoclet-ANT task on the java code – Make sure xml is in your classpath (the xdocletant will put in src directory) • Hibernate Annotations, next step. See all examples of Xdoclet in the java code copyright 2006, rhinosystemsinc.com all rights reserved XDoclet example •Person.java Long PERSON_ID=null; String FNAME=null; /** @hibernate.id @hibernate.id /** unsaved-value="null" ** unsavedvalue="null" * generatorclass="sequence"*/ * generatorpublic class="sequence"*/ Long get public Long getPERSON_ID(){} public void /** @hibernate.property */ setPERSON_ID(Long){} /** @hibernate.property */ • Person.hbm.xml Xdoclet Ant task <id name="PERSON_ID" column="PERSON_ID" type="java.lang.Long" unsaved-value="null"> <generator class="sequence"> <!– …some xdoclet commentary…--> commentary…--> </generator> </id> <property <property name="LAST_NAME" name="LAST_NAME" type="java.lang.String" type="java.lang.String" update="true" update="true" insert="true" insert="true" column="LAST_NAME" /> column="LAST_NAME" /> public String getFNAME(){} •Maintain tags in one location - Java public void setFNAME(String){} •On building (one click) create hbm.xml See all examples for xdoclet copyright 2006, rhinosystemsinc.com all rights reserved files Topics Not Covered • • • • • SessionFactory PLSQL Custom UserType Caching (1st & 2nd Level) Transactions and Isolation Levels – JDBC trx semantics – Concurrent Updates and versioning. • Session and Flushing – Session "unit of work" • Interceptors & Logging • Definitions: – Transient, Persistent, Detached • Subclass copyright 2006, rhinosystemsinc.com all rights reserved