0% found this document useful (0 votes)
3 views

Module 01 - Hibernate Entity Mapping-upd

ea lect1

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Module 01 - Hibernate Entity Mapping-upd

ea lect1

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

Module 01: Entity Mapping

CS544: Enterprise Architecture

© 2014 Time2Master 1
Entity Class Mapping
 Entity classes can be thought of as the distinct
business concepts in a domain driven design
 We will start with the basic Java class
requirements for persisting entity classes
 After which we will go into identity mapping,
mapping data types, and Hibernate access
 We will provide both XML and annotation
mapping examples for each subject we cover
Person
+name

© 2014 Time2Master 2
Class Requirements
 Hibernate requires that entity classes have:
 A field that can be used as identifier
 A default constructor
 Getter and Setter Methods for all properties

package intro; An identifier


public class Person {
private long id;
private String name; A default constructor
public Person() {}
public Person(String name) { this.name = name; }

public long getId() { return id; }


public void setId(long id) { this.id = id; } Getter and Setter Methods
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}

© 2014 Time2Master 3
About Annotations
 Most of the mapping annotations we will use
are part of the Java Persistence API (JPA)
@Entity(name="MY_PERSON") Person class with
public class Person { JPA Annotations
@Id
@Column(name="PERSON_ID")
private long id;
@Column(name="FULLNAME")
private String name;

...

 JPA is supported by many Java persistence


frameworks as a standard, portable API

© 2014 Time2Master 4
Hibernate Annotations
 Additional Hibernate specific functionality can
be exposed using Hibernate annotations
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity Full org.hibernate.annotations


public class Person { pacakge name to clearly
@Id distinguish from JPA
@GeneratedValue
private long id;
@org.hibernate.annotations.AccessType("property")
private String name;

...

 Best practice to use full package name for


hibernate annotations to clearly distinguish
from JPA
© 2014 Time2Master 5
Annotation based Mapping
@Entity Map class to ‘MY_PERSON’ table Table: MY_PERSON
@Table(name="MY_PERSON")
public class Person {
@Id Map to PERSON_ID column
@Column(name="PERSON_ID")
private long id;
@Column(name="FULLNAME")
Map to FULLNAME column
private String name;

public Person() {}
public Person(String name) { this.name = name; }

public long getId() { return id; }


private void setId(long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
Defaults to ‘Person’ table

@Entity Table: PERSON


public class Person {
@Id
Defaults to ‘id’ column
private long id; name (same as property)
private String name;

... No annotation needed, persisted


to the ‘name’ column by default
© 2014 Time2Master 6
Hibernate XML Mapping
 Person.hbm.xml
 Usually in the same package as Person.java
<?xml version="1.0" encoding="UTF-8"?> Table: MY_PERSON
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<class> tag to map Person>
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
to the `MY_PERSON’ table
<hibernate-mapping>
<class name="intro.Person" table="MY_PERSON">
<id name="id" column="PERSON_ID" />
<id> tag to map the primary key
<property name="name" column="FULLNAME" />
</class>
</hibernate-mapping> <property> tag to map
normal properties

<hibernate-mapping> Table: PERSON


<class name="intro.Person">
<id name="id" />
<property name="name" />
</class>
</hibernate-mapping> Unlike annotations, you have
to specify all properties!

© 2014 Time2Master 7
Entity Class Mapping:

MAPPING IDENTITY

© 2014 Time2Master 8
Primary key
 A primary key is
 Unique
 No duplicate values
 Constant
 Value never changes
 Required
 Value can never be null

 Primary key types:


 Natural key
 Has a meaning in the business domain
 Surrogate key
 Has no meaning in the business domain
 Best practice

© 2014 Time2Master 9
Mapping Primary Keys
 Object / Relational mismatch
 Hibernate requires you to specify the property
that will map to the primary key
 Prefer surrogate keys
 Natural keys often lead to a brittle schema

@Entity @Entity Instead use id as a


public class Person { public class Person {
surrogate key for Person
@Id @Id
private String name; private long id;
private String name;
...
Name as a natural ...
primary key for Person
can give problems

© 2014 Time2Master 10
Generating Identity
 Generated identity values
 Ensure identity uniqueness
 Private setId() methods
 Ensure identity immutability
@Entity
public class Person {
@Id
@GeneratedValue Id is generated
private long id;
private String name;

public Person() {}
public Person(String name) { this.name = name; }

public long getId() { return id; } Id can not be set by


private void setId(long id) { this.id = id; } the application
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}

© 2014 Time2Master 11
Generation Strategies
Hibernate JPA Description
native AUTO Selects the best strategy for your database
identity IDENTITY Use an identity column (MS SQL, MySQL, HSQL, …)
sequence SEQUENCE Use a sequence (Oracle, PostgreSQL, SAP DB, …)
- TABLE Uses a table to hold last generated values for PKs
hilo - Like table, uses efficient algorithm to generate values
seqhilo - Like regular hilo, but using a sequence
increment - Finds the current max value and increments by 1*
uuid.hex - Creates globally unique 128-bit UUIDs
guid - Uses MySQL and MS SQL server global uid generator
select - Have Hibernate select a value generated by a trigger
assigned (implicit) Specifies that the value is assigned by the application

© 2014 Time2Master 12
Specifying Identity Generation
 @GeneratedValue
@Entity @Entity Defaults to
public class Person { Specify the generation strategy public class Person { ‘AUTO’
@Id @Id when not
@GeneratedValue(strategy=GenerationType.AUTO) @GeneratedValue
private long id; private long id;
specified
private String name; private String name;

 <generator> tag
<hibernate-mapping>
<class name="identity.Person"> Always have to
<id name="id"> specify a strategy,
<generator class="native" /> cannot leave it off
</id>
<property name="name" />
</class>
</hibernate-mapping>

© 2014 Time2Master 13
Identity Column
 Identity columns are columns that can
automatically generate the next unique id
@Entity
public class Person { JPA identity strategy
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;

<hibernate-mapping>
<class name="identity.Person">
<id name="id">
<generator class="identity" />
</id>
<property name="name" />
</class>
XML identity strategy
</hibernate-mapping>

 If your database support identity columns the


native strategy will default to using them
© 2014 Time2Master 14
Sequence
 The SEQUENCE strategy will default to using
the ‘hibernate_sequence’ for all tables
 The AUTO strategy will do so too if sequence is the
default strategy (Oracle, PostgreSQL)
@Entity
public class Person { Both AUTO and SEQUENCE
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
private long id;
private String name;

<hibernate-mapping>
<class name="identity.Person">
<id name="id">
<generator class="sequence" />
</id> Both native and sequence
<property name="name" />
</class>
</hibernate-mapping>

© 2014 Time2Master 15
Sequences
 By default Hibernate only uses a single
sequence called ‘hibernate-sequence’
 You can specify additional custom sequences

 Tip: You can use the native strategy and still


also specify a custom sequence

© 2014 Time2Master 16
Using Custom Sequences
Create Custom Sequence
@Entity
@SequenceGenerator(name="personSeq", sequenceName="PERSON_SEQUENCE")
public class Person_annotated_sequence {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="personSeq")
private long id;
Use Custom Sequence
...

<hibernate-mapping>
<class name="identity.Person">
<id name="id" >
Use ‘sequence’ strategy
<generator class="sequence">
<param name="sequence">PERSON_SEQUENCE</param>
</generator>
</id> Specify the custom
<property name="name" /> sequence
</class>
</hibernate-mapping>

© 2014 Time2Master 17
Entity Class Mapping

MAPPING DATA TYPES

© 2014 Time2Master 18
Data Types
 So far we haven’t specified any data types
 Hibernate automatically mapped to SQL types

 You can be very specific


 Specify the data type, length, precision and more
@Entity
public class Person { Name will be stored as:
@Id FULLNAME VARCHAR(255) NOT NULL
@GeneratedValue
private long id;
@Column(name="FULLNAME", length=255, nullable=false)
private String name;

...

© 2014 Time2Master 19
Specify Date Type
 Sometimes you need to be specific
 Should a java.util.Date be stored as date, as a time
or as a timestamp in the database?
@Entity
public class Person {
@Id
@GeneratedValue
private long id;
private String name; Birthday will be
@Temporal(TemporalType.DATE) stored as a Date
private Date birthday;

...

 If left unspecified a java.util.Date will be


stored as a timestamp to preserve accuracy
© 2014 Time2Master 20
Annotation Types
 Reflection is used to find java type information
 Use @Column to specify more details
 Use @Temporal to specify how a Date should
be persisted (DATE, TIME or TIMESTAMP)
 Use @Lob to indicate Large values
 Use @Transient to indicate that a property
should not be persisted

© 2014 Time2Master 21
All in One Example

@Entity
public class Person { Name will be stored as:
@Id FULLNAME VARCHAR(255) NOT NULL
@GeneratedValue
private long id;
@Column(name="FULLNAME", length=255, nullable=false)
private String name;
@Temporal(TemporalType.DATE) Birthday will be
private Date birthday; stored as a Date
@Lob
private String biography;
@Transient
private String temp;
Biography will be stored as CLOB
instead of VARCHAR
...

Temp will not be stored in the database

© 2014 Time2Master 22
Basic Hibernate XML Types
Hibernate Type Java Type SQL Type
byte byte or java.lang.Byte TINYINT
short short or java.lang.Short SMALLINT
integer int or java.lang.Integer INTEGER
long long or java.lang.Long BIGINT
float float or java.lang.Float FLOAT
double double or java.lang.Double DOUBLE
big_decimal java.math.BigDecimal NUMERIC
boolean boolean BIT
yes_no boolean CHAR(1) – ‘Y’ or ‘N’
true_false boolean CHAR(1) – ‘T’ or ‘F’
string java.lang.String VARCHAR
character char, java.lang.Character or CHAR(1)
java.lang.String

© 2014 Time2Master 23
Date Time & Large Values
Hibernate Type Java Type SQL Type
date java.util.Date or java.sql.Date DATE
time java.util.Date or java.sql.Time TIME
timestamp java.util.Date or java.sql.Timestamp TIMESTAMP
calendar java.util.Calendar TIMESTAMP
calendar_date java.util.Calendar DATE

Hibernate Type Java Type SQL Type


binary byte[] or java.lang.Byte[] VARBINARY
text java.lang.String CLOB
clob java.sql.Clob CLOB
blob Java.sql.Blob BLOB
serializable java.io.serializable VARBINARY

© 2014 Time2Master 24
XML Type Example
Same class and properties as the
previous annotation example
public class Person {
private long id; Now without
private String name; annotations
private Date birthday;
private String biography;
private String temp;

...

Name will be stored as:


<hibernate-mapping> FULLNAME VARCHAR(255) NOT NULL
<class name="model.Person" table="MY_PERSON">
<id name="id" type="long" column="PERSON_ID">
<generator class="native" />
</id>
Birthday will be
<property name="name" column="FULLNAME"
type="string" length="255" not-null="true" /> stored as a Date
<property name="birthday" column="BIRTHDAY" type="date" />
<property name="biography" type="text" />
</class>
Biography will be stored as CLOB
</hibernate-mapping>
instead of VARCHAR
Temp is not listed and will not
be stored in the database
© 2014 Time2Master 25
Entity Class Mapping

SPECIFYING ACCESS TYPE

© 2014 Time2Master 26
Property or Field Access
 Hibernate can access objects in two ways
 property access gets and sets object values
through getter /setter methods
 field access gets and sets object values directly
from / to the fields
@Entity @Entity
public class Person { public class Person {
@Id private long id;
@GeneratedValue private String name;
private long id;
private String name; public Person() {}
public Person(String name) { this.name = name; }
...
JPA field access @Id
@GeneratedValue JPA property access
public long getId() { return id; }
private void setId(long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
© 2014 Time2Master 27
Specifying Access with Annotations
 The JPA specification lets you set the Access Type
with the location of @Id
 Placing @Id on a field specifies field access for the
entire object
 All other mapping annotations should be on the fields
 Placing @Id on a getter specifies property access for
the entire object
 All other mapping annotations should be on the getters

 Using additional annotations you can also change


access for individual fields

© 2014 Time2Master 28
Access Example
@Entity
public class Person {
private long id;
private String name;
private Date birthday;

All other public Person() {}


annotations public Person(String name) { this.name = name; }
have to be @Id on a getter sets property access for all attributes
on getter @Id
@GeneratedValue
methods as public long getId() { return id; }
well private void setId(long id) { this.id = id; }

@Access(AccessType.FIELD) Name will be accessed


public String getName() { return name; } through the field instead
public void setName(String name) { this.name = name; }

@Temporal(TemporalType.DATE)
public Date getBirthday() { return birthday; }
public void setBirthday(Date birthday) { this.birthday = birthday; }
}

Birthday is still accessed


through getters / setters

© 2014 Time2Master 29
Setting Access with XML
 Use the “default-access” attribute on the
<hibernate-mapping> tag to set the default
 Use the “access” attribute on the <property>
tag to change access for individual fields
Sets the default access
for Person to field
<hibernate-mapping default-access="field">
<class name="model.Person">
<id name="id">
<generator class="native" />
</id>
<property name="name" access="property" /> Changes the access for the name
<property name="birthday" type="date" /> attribute to property
</class>
</hibernate-mapping>
Birthday will be accessed through
its field (as set by the default)

© 2014 Time2Master 30
Access / Encapsulation
 Property access hides implementation details
 Maintains OO Principle of Encapsulation

 Hibernate dirty checking compares by value


 With property access your implementation can
differ from your relational mapping without
disturbing Hibernate

© 2014 Time2Master 31
Encapsulation Example XML
public class Person {
private long id;
Table: PERSON
3 field implementation
private String firstname; details are encapsulated
private String lastname;
Mapped to 2 column table
public Person() {}

public long getId() { return id; } Firstname and lastname are


public void setId(long id) { this.id = id; }
combined in getter
public String getName() { return firstname + " " + lastname; }
public void setName(String name) {
StringTokenizer st = new StringTokenizer(name);
firstname = st.nextToken();
lastname = st.nextToken(); Firstname and lastname are
} separated in setter
public String getFirstname() { return firstname; }
public void setFirstname(String firstname) { this.firstname = firstname; }

public String getLastname() { return lastname; }


public void setLastname(String lastname) { this.lastname = lastname; }
}
<hibernate-mapping default-access="property">
<class name="model.Person" >
<id name="id"> Property access
<generator class="native"/>
</id>
<property name="name" /> maps the 2 fields:
</class> id and name
</hibernate-mapping>© 2014 Time2Master 32
Annotations Encapsulation Example
@Entity
public class Person { Table: PERSON
private long id;
private String firstname; Three class properties get
private String lastname; mapped to two columns

public Person() {}

@Id Property access


@GeneratedValue
public long getId() { return id; }
public void setId(long id) { this.id = id; }

@Column
public String getName() { return firstname + " " + lastname; }
public void setName(String name) { /* see code prev slide */; }
@Transient firstname
@Transient and lastname
public String getFirstname() { return firstname; }
public void setFirstname(String firstname) { this.firstname = firstname; }

@Transient
public String getLastname() { return lastname; }
public void setLastname(String lastname) { this.lastname = lastname; }
}

© 2014 Time2Master 33
Entity Class Mapping

WRAPPING UP

© 2014 Time2Master 34
Mapping Tips
 You can specify a package attribute on the
<hibernate-mapping> XML element
 No longer need fully qualified class names
 Useful when mapping associations

Class name Order Pacakge specified for this mapping


instead of tips.Order
<hibernate-mapping package="cs544">
<class name="Order" table="`order`">
<id name="id" column="`id`"/>
<many-to-one name="customer" class="Person" />
</class>
</hibernate-mapping>
Person instead of cs544.Person

© 2014 Time2Master 35
Active Learning
 What do the following annotations do:
@Temporal @Transient

 How does property access work, how does


field access work?

© 2014 Time2Master 36
Module Summary
 In this module we covered entity class
mapping including:
 Mapping an entity classes to tables
 Mapping properties to columns
 Mapping Identity and setting Identity Generation
 Mapping Data types
 Property / Field Access
 These are the tools you use to map any class

© 2014 Time2Master 37

You might also like