330 likes | 356 Views
Hibernate Introduction - 1. Present by Eric Yu. Content. Understanding object/relational persistence Introduction Architecture The core interfaces Configuration Persistent classes Basic O/R mapping Collection mapping Association mapping Component mapping. Understanding O/R persistence.
E N D
Hibernate Introduction - 1 Present by Eric Yu
Content • Understanding object/relational persistence • Introduction • Architecture • The core interfaces • Configuration • Persistent classes • Basic O/R mapping • Collection mapping • Association mapping • Component mapping
Understanding O/R persistence • What is persistence? • Object-oriented applications • Relational database system • The paradigm mismatch • Object/relational mapping • What is ORM? • Why ORM (solution)? • productivity, maintainability • performance, vendor independence
Understanding O/R persistence • What do RDBS do well? • Work with large amounts of data • searching, sorting • Work with sets of data • joining, aggregating • Share • concurrency, many applications • Integrity • constraint, transaction isolation • What do RDBS do badly? • Modeling • no polymorphism; fine-gained modeling is difficult • Biz logic in stored procedure
Introduction • Hibernate • Open Source (LGPL) • Mature and Popular (15,000 downloads/month) • Custom API • Will be referred by EJB 3.0 in its redesign of entity beans • Features • Persistence for POJOs (Plain Ordinary/Old Java Object) • Flexible and intuitive mapping • Support for fine-grained object models • Powerful, high performance queries • Two-level Caching Architecture • Toolset for roundtrip development • Support for detached persistent objects
Architecture Figure 1 Figure 2
The core interfaces • SessionFactory • A threadsafe (immutable) cache of compiled mappings for a single database. A factory for Session and a client of ConnectionProvider • Session • A single-threaded, short-lived object representing a conversation between the application and the persistent store. Wraps a JDBC connection. Factory for Transaction. • Persistent Objects and Collections • Short-lived, single threaded objects containing persistent state and business function. These might be ordinary JavaBeans/POJOs, • Transient and detached Objects and Collections • Instances of persistent classes that are not currently associated with a Session. • Transaction • A single-threaded, short-lived object used by the application to specify atomic units of work. Abstracts application from underlying JDBC, JTA or CORBA transaction. A Session might span several Transactions in some cases. • ConnectionProvider • (Optional) A factory for (and pool of) JDBC connections. Abstracts application from underlying Datasource or DriverManager. Not exposed to application, but can be extended/implemented by the developer. • TransactionFactory • (Optional) A factory for Transaction instances. Not exposed to the application, but can be extended/implemented by the developer.
Configuration • Objective • Used to build an SessionFactory. • Main items • JDBC connection / datasource • Classes mapping files • Diff for managed and non-managed environments • Two styles • Properties configure file • XML configure file (recommended)
Configuration • Sample • Properties file for Non-managed env • XML file for Managed env <hibernate-configuration> <session-factory> <property name="hibernate.connection.datasource"> synnex/jdbc/CISDB </property> <property name=" hibernate.dialect"> org.hibernate.dialect.SybaseDialect </property> <property name="hibernate.transaction.factory_class"> org.hibernate.transaction.JTATransactionFactory </property> <mapping resource="Customer.hbm.xml" /> <mapping resource="Address.hbm.xml" /> </session-factory> </hibernate-configuration> hibernate.connection.url = \ jdbc:sybase:Tds:192.168.200.11:4500/CIS hibernate.connection.driver_class = \ com.sybase.jdbc2.jdbc.SybDriver hibernate.connection.username = \ ericy hibernate.connection.password = \ synnex2k2 hibernate.transaction.factory_class = \ org.hibernate.transaction.JDBCTransactionFactory
Configuration • How to get SessionFactory • For properties file (hibernate.properties) • For XML file (hibernate.cfg.xml) Configuration cfg = new Configuration() .addResource(“Customer.hbm.xml") .addResource(“Address.hbm.xml"); // If not use the default configure file // cfg.setProperties(<an instance of java.util.Properties>); SessionFactory sessionFactory = cfg.buildSessionFactory(); SessionFactory sf = new Configuration().configure().buildSessionFactory(); // If not use the default configure file SessionFactory sf = new Configuration().configure(“cisdb.cfg.xml”).buildSessionFactory();
Persistent classes • Example
Persistent class Declare accessors and mutators for persistent fields Implement a no-argument constructor Provide an identifier property Prefer non-final classes Collection property is an interface Class sample Persistent classes public class AuctionItem { private Long _id; private Set _bids; private Bid _successfulBid private String _description; public AuctionItem () {}; public Long getId() { return _id; } private void setId(Long id) { _id = id; } public String getDescription() { return _description; } public void setDescription(String desc){ _description=desc; } … }
XML Mapping Readable metadata Column/table mappings Surrogate key generation strategy Collection metadata Fetching strategies XML Sample Persistent classes <hibernate-mapping> <class name=“AuctionItem” table=“AUCTION_ITEM”> <id name=“id” column=“ITEM_ID”> <generator class=“native”/> </id> <property name=“description” column=“DESC”/> <many-to-one name=“successfulBid” column=“SUCCESSFUL_BID_ID” class=“Bid” /> <set name=“bids” cascade=“all” lazy=“true”> <key column=“ITEM_ID”/> <one-to-many class=“Bid”/> </set> </class> </hibernate-mapping>
Persistent classes • Code sample • AuctionItem item = new AuctionItem(); • item.setItemName(“XXX”); • … • Session session = null; • Transaction tx = null; • try { • session = sessionFactory.openSession(); • tx = session.beginTransaction(); • // do your work • session.save(item); • tx.commit(); • } • catch (Exception e) { • if (tx != null) tx.rollback(); • throw e; • } • finally { • if (session != null) session.close(); • }
Basic O/R mapping • class • <class • name="ClassName" (1) • table="tableName" (2) • discriminator-value="discriminator_value" (3) • mutable="true|false" (4) • schema="owner" (5) • catalog="catalog“ (6) • dynamic-update="true|false" (8) • dynamic-insert="true|false" (9) • select-before-update="true|false" (10) • where="arbitrary sql where condition" (12) • batch-size="N" (14) • optimistic-lock="none|version|dirty|all" (15) • lazy="true|false" (16) • /> • name:The fully qualified Java class name of the persistent class (or interface). • table (optional - defaults to the unqualified class name): The name of its database table. • (15)optimistic-lock (optional, defaults to version): Determines the optimistic locking strategy.
Basic O/R mapping • id • <id • name="propertyName" (1) • type="typename" (2) • column="column_name" (3) • unsaved-value="null|any|none|undefined|id_value" (4) • access="field|property|ClassName"> (5) • <generator class="generatorClass"/> (6) • </id> • (1)name: The name of the identifier property. • (2) type: A name that indicates the Hibernate type. • (3) column (optional - defaults to the property name): The name of the primary key • column. • (4) unsaved-value (optional): An identifier property value that indicates that an instance is newly instantiated (unsaved), distinguishing it from detached instances that were saved or loaded in a previous session. • (6) The built-in generator: • assigned,hilo, seqhilo,increment, identity,sequence, native, • uuid (hibernate 3.0), foreign, select (hibernate 3.0)
Basic O/R mapping • composite-id • <composite-id • name="propertyName" • class="ClassName" • unsaved-value="undefined|any|none" • access="field|property|ClassName"> • <key-property name="propertyName" type="typename" column="column_name"/> • <key-many-to-one name="propertyName class="ClassName" column="column_name"/> • ...... • </composite-id> • For Example : • (1) • <composite-id> • <key-property name=“orderNo“ column=“order_no”/> • <key-property name=“orderType“ colunm=“order_type”/> • </composite-id> • (2) • <composite-id> • <key-many-to-one name=“customerNo“ column=“cust_no” class=“Customer”/> • <key-property name=“locationNo“ colunm=“loc_no”/> • </composite-id>
Basic O/R mapping • version • <version • column="version_column“ (1) • name="propertyName" (2) • type="typename" (3) • access="field|property|ClassName“ (4) • unsaved-value="null|negative|undefined" (5) • /> • (1)column (optional - defaults to the property name): The name of the column holding the version number. • (2) name: The name of a property of the persistent class. • (3) type (optional - defaults to integer): The type of the version number. Version numbers may be of Hibernate type long, integer, short, timestamp or calendar. • (4) access (optional - defaults to property): The strategy Hibernate should use for accessing the property value. • (5) unsaved-value (optional - defaults to undefined): A version property value that indicates that an instance is newly instantiated (unsaved), distinguishing it from detached instances that were saved or loaded in a previous session. (undefined specifies that the identifier property value should be used.) • Declaring a nullable version or timestamp property is an easy way to avoid any problems with transitive reattachment in Hibernate, especially useful for people using assigned identifiers or composite keys!
Basic O/R mapping • property • <property • name="propertyName" (1) • column="column_name" (2) • type="typename" (3) • update="true|false" (4) • insert="true|false" (4) • formula="arbitrary SQL expression" (5) • lazy="true|false" (7) • unique="true|false" (8) • not-null="true|false" (9) • optimistic-lock="true|false" (10) • /> • (4) update, insert (optional - defaults to true) : specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. • (5) formula (optional): an SQL expression that defines the value for a computed property. • (7) lazy (optional - defaults to false): Specifies that this property should be fetched lazily when the instance variable is first accessed. • (8) unique (optional): Enable the DDL generation of a unique constraint for the columns. • (9) not-null (optional): Enable the DDL generation of a nullability constraint for the columns. • (10) optimistic-lock (optional - defaults to true): Specifies that updates to this property do or do not require acquisition of the optimistic lock. In other words, determines if a version increment should occur when this property is dirty.
element class Collection mapping Collection (<set>, <list>, <map>, <bag>, <array>) Example - set • public class Product { • private String serialNumber; • private Set images = new HashSet(); • } • =========================== • <class name="Product"> • <id name="serialNumber" • column="productSerialNumber"/> • <set name="images" • table="ITEM_IMAGE"> • <key column="ITEM_ID"/> • <element type="string“ • column="FILENAME" /> • </set> • </class> • public class Product { • private String serialNumber; • private Set parts = new HashSet(); • } • ========================== • <class name="Product"> • <id name="serialNumber" • column="productSerialNumber"/> • <set name="parts"> • <key • column="productSerialNumber“/> • <one-to-many class="Part"/> • </set> • </class>
Example - list Example - map Collection mapping • public class Customer { • private String customerNo; • private List addresses • = new ArrayList(); • … … • } • ===================== • <class name=“Customer"> • … • <list name="addresses"> • <key column="cust_no"/> • <index column="addr_no"/> • <one-to-many class="Address"/> • </list> • … • </class> • public class Customer { • private String customerNo; • private Map addresses • = new HashMap(); • … … • } • ===================== • <class name=“Customer"> • … • <map name="addresses"> • <key column="cust_no"/> • <index column="addr_no“ • type=“integer”/> • <one-to-many class="Address"/> • </map> • … • </class>
Association mapping • many-to-one • <many-to-one • name="propertyName" (1) • column="column_name" (2) • class="ClassName" (3) • cascade="cascade_style" (4) • fetch="join|select" (5) • update="true|false" (6) • insert="true|false" (6) • property-ref="propertyNameFromAssociatedClass" (7) • access="field|property|ClassName" (8) • unique="true|false" (9) • not-null="true|false" (10) • optimistic-lock="true|false" (11) • lazy="true|false" (12) • /> • (1)name: The name of the property • (2)column (optional): The name of the foreign key column. This may also be specified by nested <column> element(s). • (3)class (optional): The name of the associated class. • (4)cascade (optional): Specifies which operations should be cascaded from the parent object to the associated object. • (5)fetch (optional - defaults to select): Chooses between outer-join fetching or sequential select fetching.
Association mapping • many to one (example) • <class name="Person"> • <id name="id" column="personId"> • <generator class="native"/> • </id> • <many-to-one name="address" • column="addressId" • not-null="true“ • class=“Address”/> • </class> • <class name="Address"> • <id name="id" column="addressId"> • <generator class="native"/> • </id> • </class> create table Person ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
Association mapping • one to one (example) • A one-to-one association on a foreign key • <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> create table Person ( personId bigint not null primary key, addressId bigint not null unique) create table Address ( addressId bigint not null primary key )
Association mapping • one to one (example) • A one-to-one association on a primary key • <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> create table Person ( personId bigint not null primary key ) create table Address ( personId bigint not null primary key )
Association mapping • one to many (example) • A one-to-many association on a foreign key • <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> create table Person ( personId bigint not null primary key ) create table Address ( addressId bigint not null primary key, personId bigint not null )
Association mapping • one to many (example) • A one-to-many association on a join table • <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> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId not null, addressId bigint not null) create table Address ( addressId bigint not null primary key )
Association mapping • many to many (example) • A many-to-many association on a join table • <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> create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId not null, addressId bigint not null) create table Address ( addressId bigint not null primary key )
Componentmapping • dependent objects • <class name="Person" table="person"> • <id name=“id" column=" personId" type="string"> • <generator class="uuid.hex"/> • </id> • <property name=“name" type=“string"/> • <component name=“address" class=“Address"> • <property name=“street"/> • <property name=“zipcode"/> • <property name=“city"/> • <property name=“state"/> • <property name=“country"/> • </component> • </class> create table Person ( personId bigint not null primary key,name varchar not null, street varchar null, zipcode varchar null, city varchar null, state varchar null, country varchar null )
Inheritance mapping • table per class-hierarchy • Suppose we have an interface Payment, with implementors CreditCardPayment, CashPayment, ChequePayment. The table per class-hierarchy mapping would look like: • <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>
Inheritance mapping • table per subclass • Four tables are required. The three subclass tableshave primary key associations to the superclass table. • <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>
Inheritance mapping • table per subclass, using a discriminator • <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"> • <join table="CASH_PAYMENT"> • ... • </join> • </subclass> • <subclass name="ChequePayment" discriminator-value="CHEQUE"> • <join table="CHEQUE_PAYMENT" fetch="select"> • ... • </join> • </subclass> • </class>
Inheritance mapping • table per concrete class • Three tables are involved – no table for the interface (super class). • <class name="Payment"> • <id name="id" type="long" column="PAYMENT_ID"> • <generator class="native"/> • </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>