Friday, March 1, 2013

Hibernate

Section 1 & Section 2 Course Introduction & ORM and Hibernate V1-V10




in section 1 we installed MySQL and created the database

Video 7: Hibernate Overview
1- hibernate implements Java Persistence API.
2- in addition hibernate provides some extra annotations
3- in addition hibernate has HQL, a special query language.

in order to use hibernate, you need to have hibernate.properties (or hibernate.cfg.xml) to define your connection. Also you need to provide the mapping between your object and database, this can be done by annotation or xml. After that you just get a session from sessionFactory and start working, basically the sessionFactory hold all the connection and mapping information.

the most important thing in hibernate:
1- no SQL
2- reduce development time
3- sure hibernate abstract you from the database,

Video 8-9: Object Relational Mapping
we should know that we have data model, which is the table in the database and Object model which is a representation for this data as objects, normally you have a class for each table in the database


when you convert from a data model to object model you should be careful of the following differences:
1- Identity: in data model you identify a record by using primary key, in Object Model we use = operator or equals().
2- Association: in data model to associate table we use foreign key, in Object Model we use Object reference
3- Asoociation Navigation: in data model we use join, in Object Model we use get methods on the reference
4- Inheritance: there is no inheritance in data mode, but we have inheritance in Object model

with ORM you achieve:
1- less persistence code, which leads to less development time
2- no need to repeat yourself and build a persistence layer
3- it is less likely to make mistakes, like closing connections

Video 10: Hibernate Demo
it is just a demo, we will not talk about it, just one important thing, we said before that you should use hibernate.properties, however you can also set the configurations via code, nobody does that but you can




Section 3: V11- V16 Hibernate Basics 


V11: Setup the project
you should add the following maven dependencies


and we should add log4.properties file in src/main/resources


it is good practice to put your entities in specific packages like com.xxx.data.entities:


Video 12: Simple Entity Mapping
in the previous image we introduced the following annotations

1- @Entity: to define an entity
2- @Table: to set the table
3-@Id: to set the primary key
4- @GeneratedValue: to set the way you generate a new id
5- @Column: to set the column

Note: it is a good practice to always set the table and column names, even though Hibernate can do some magic to link them,

Video 13: prepare you application with hibernate.properties
in this lesson we will see how we can use hibernate.properties to setup our application

1- add hibernate.properties to the resources file:

2- now we will define a HibernateUtils class, in this class we will write the code responsible for creating a sessionFactory and other stuff


as you can see we are using singleton pattern, only one sessionFactory will be created

we define a Configuration object, which will automatically read the hibernate.properties file,
as you can see we have to add the Entity classes to configurations
configuration.addAnnotatedClass(User.class).

if you have other classes you should add all of them

then we call buildSessionFactory()

Video 15: setup the project with hibernate.cfg.xml
hibernate.cfg.xml is the preffered way to write configurations, it has more options to add than hibernate.properties


as you can see we added the connection information,
show_sql: will print the executed sql statement to the output

and the most important thing is mapping, here we define the Entity classes, we cannot do that in hibernate.properties, as you can see from the previous video you should add them by using configuration.addAnnotatedClass(User.class) if you are using hibernate.properties

now the HibernateUtil will look like this

as you can see no more configuration.addAnnotatedClass()

Video 16: Calling Persistence method
as you can see, we get a session factory and we open a session
then we begin a transaction
then we save
commit the transaction
then close the session.

Note: remember to commit the transaction before you close the session.


Section 4 Basic Mapping Annotation V17 - V26


Vide 16: Hibernate & JPA
we should know that JPA is just an interface, and hibernate implements this interface.
However, hibernate went beyond what we have in JPA by adding new annotation and new functionalities.
you should know that if you use the hibernate features you will be locked by hibernate.

all JPA annotations are under javax.persistence, the new hibernate annotations are under org.hibernate.annotations


Video 17: Field vs Property Access
when you annotate your class, you can do this:


as you can see here we are annotating the field

however, we can do another thing which is annotating the get method not the field like this

as you can see we removed the annotation from the field to the get methods,

you can also use @Access(value=AccessType.PROPERTY) on the class level, it is a good practice to alwayse use it.

the question is when to use property or field access?
so in field access, you are allowing Hibernate to access private fields, which violate the class encapsulation, sure hibernate uses reflection to access these values.
when you use property access, you can add some extra logic to your get methods.

choose what suits you best.

Video 19: @Column
some of the important attributes for @Column
1- updatable=false: it means that don't add this column to the update statement when we do an update, for example in this case we should not update the createdDate
2- insirtable=false: same as above but for insert
3- nullable=false: which means the field cannot be null.

let's see that birthdate field is defined in the database as cannot be null, and we don't set nullable = false in the User class. If we insert a record with birthdate = null, THE DATABASE will throw an exception, however if we set nullable = false then HIBERNATE will throw the exception. it is better to let Hibernate throws exceptions not database.

Video 20 & 21: Identifier
in this tutorial he talked about comparing records, you know that we can compare using == to compare instances and equals() to compare values.

and as you know we have to types of primary keys in the database
1-  surrogate key: which means an id column
2- natural key: a key that is a field or multiple field in the database

the preferred key for hibernate is surrogate key,

we saw that you define the surrogate key by
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)

the @GeneratedValue defines how we set the value of new records, when we set it as IDENTITY, it means let the underling database decide how to generate this value

in case of using ORACLE, we use sequences for generated values, in order to map that to oracle we write



 as you can see we use @SequenceGenerator

another way to generate this value is to use just
@GeneratedValue

without anything, this way Is called auto generator, the auto generator means let the persistence engine decides the best way to generate value based on the underling database

another way is called TableGenerator, which means using a specific table to generate the key value, we define a table with just two columns The Key Name and The Value
then we write


as you can see we use @TableGenerator tag

Video 22: @Transient
lets say you want to add a field to the User class,
private Boolean valid;

even if you don't add annotation to this field, hibernate will try to insert this field into the database, however the valid field is not part of the database we use it for different purposes,
we should tell hibernate to ignore this field when it does any database operations, that is why we use the @Transient

@Transient
private Boolean valid;

video 23: @Temporal
normally, databases provides you with 3 date types,
DateTime: to save date and time
Date: to save just the date
Time: to save the just the time

MySQL provides you with another type which is Timestamp, which is somehow similar to datetime.

in order to map these fields to java object, you can use java.util.Date

@Column(name = "DATETIME_COLUMN")
 private Date datetimeColumn;

 @Column(name = "TIMESTAMP_COLUMN")
 private Date timestampColumn;

 @Column(name = "DATE_COLUMN")
 private Date dateColumn;

 @Column(name = "TIME_COLUMN")
 private Date timeColumn;

however, if you check the value of these dates, you will find that java.util.Date will always have a date and time values even though the field could be of type Date (only Date) or time (only Time).

in order to fix this problem we use the @Temporal tag
@Temporal(TemporalType.TIMESTAMP)
 @Column(name = "DATETIME_COLUMN")
 private Date datetimeColumn;

 @Temporal(TemporalType.TIMESTAMP)
 @Column(name = "TIMESTAMP_COLUMN")
 private Date timestampColumn;

 @Temporal(TemporalType.DATE)
 @Column(name = "DATE_COLUMN")
 private Date dateColumn;

 @Temporal(TemporalType.TIME)
 @Column(name = "TIME_COLUMN")
 private Date timeColumn;

@Temporal will till java to store the correct value.

Note1: it is important to use @Temporal, otherwise you will have some casting issue when you store to datebase.
Note2: you should use @Temporal with java.util.date, or with Calender if you are using Calender
Note3: there are other types which solve the issue like:

Video 24: @Formula
@Formula is a Hibernate annotation

it is used like this
you write a formula to do the calculation of the field
@Formula works just when you select the record it has nothing to do with insert or update,

Lecture 25 & 26 Basic Data Types

IN hibernate we should distinguish between 2 data types:
1-Entity Type
2-Value Types

Entity Type is a record in the database, it has a life cycle, for example User is an entity type when you write
User x = new User()
the object x still not persistence, it is in the transient state,
when you do save(x), now x is in persistence state.

On the other hand Value types DONT HAVE LIFE CYCLE, for example String firstName, doesn't have life cycle its life cycle is owned by the User class.

we have different Value Types:
1- Basic Types: like String firstName:
2- Composite Types: like Address in the image, Address doesn't have a table in the database, it is just a way to organize the object, Address fields are simply columns in the User table.
3- Collection Value Types: like List<String>

you can check online how Hibernate maps the Basic types
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/types.html




 Section: 5 - Mapping Composite And Collection Types V27 - V31


Video 28: Mapping Composite Value Types
example, we have a bank Entity, this bank has address information, we want to set the address in a separate class, we don't have Address table in the database, address information are columns in the Bank table.

to do that you define the Address class

as you can see we annotated it with @Embeddable.

now in the Bank class

as you an see we use @Embedded here

there is another scenario where we use also the address in a different table, lets say in USER table, however the columns in the USER table have different names not similar to the names annotated in the Address class.

to solve this problem you can do this:


as you can see we use @AttributeOverrid to use different names.

NOTE: we use the term Composite or Embedded when we describe the Address class
NOTE: as we mentioned before Address doesn't have a lifecycle and doesn't have identity (you can query the address

Video 29: Mapping Collections of Basic Value Types
lets say the bank has list of contact names

private Collection<String> contacts = new ArrayList<String>();

In order to save that in the database, we should have a table to hold this information, we add this table to the database BANK_CONTACT(BANK_IDNAME).

NOTE: THIS IS NOT ONE TO MANY RELATIONSHIP, THIS IS ELEMENT COLLECTION, AS YOU CAN SEE THE TABLE DOESNT HAVE AN ID

now in order to do the mapping
@ElementCollection
@CollectionTable(name = "BANK_CONTACT", joinColumns = @JoinColumn(name = "BANK_ID"))
@Column(name = "NAME")
private Collection<String> contacts = new ArrayList<String>();

as you can see we use ElementCollection and CollectionTable.

Note: the field shouldn't be of type Collection it could be List or Set
NOTE: VERY IMPORTANT TO NOTICE THAT BANK_CONTACT DOESNT HAVE IDENTITY (DOESNT HAVE AN ID) WHICH MEANS IT IS PART OF THE BANK ENTITY WHICH MEANS IT DOESNT HAVE A LIFE CYCLE AS WELL

Video 30: Mapping a Map of Basic Value Types
lets say we have
private Map<String, String> contacts = new HashMap<String, String>();

in order to map this to the database, we should have another table with ID,Key and value fields.
we will add this table BANK_CONTACT(BANK_ID,POSITION_TYPE,NAME)

then to do the mapping we write

@ElementCollection
@CollectionTable(name="BANK_CONTACT", joinColumns=@JoinColumn(name="BANK_ID"))
@MapKeyColumn(name="POSITION_TYPE")
@Column(name="NAME")
private Map<String, String> contacts = new HashMap<String, String>();

NOTE: VERY IMPORTANT TO NOTICE THAT BANK_CONTACT DOESNT HAVE IDENTITY (DOESNT HAVE AN ID) WHICH MEANS IT IS PART OF THE BANK ENTITY WHICH MEANS IT DOESNT HAVE A LIFE CYCLE AS WELL


Video 31: Mapping a Collection of  Composite Values
lest say that the bank has multiple addresses
in order to handle this we will create a separate table for addresses and we should add this:

and of course we created USER_ADDRESS table,
as we mentioned the relation is not one to many, this is element collection, there is no primary key here.
same thing regarding the lifecycle.


Section: 6 - Entity Associations V32 - V40


lets take the follwoing example


as you can see we have one to many relationship between transaction and account.
Transaction has Account_ID as a foreign key.

we can have the following java classes to simulate this relationship

you see inside Transaction you define account (Each transaction has one Account).

here Account is the target for the transaction, the account is in the transaction, and the account is the foreign key so it is the target object and the  Transaction. is the source object

with the example above you can just reach one direction of the relation, which means you can know the account related to a Transaction, however you cannot know the Transactions that are associated with the account, to do that you need a biderictional relation


as you can see we defined a List of Transactions in the Account class.

Uni-directional One to One Association
lets have this example


the relation between CREDENTIAL and FINANCES_USER is one to one as we have a unique constraint on the USER_ID column in CREDENTIAL.

now to simulate this relation in JAVA.

1- add this to hibernate.cfg.xml

2- then you should define this in JAVA:

as you can see we have User object, which makes Credential the Source Object and User the Target Object.
OneToOne annotation with CascadeType.All means when we persist Credential we should persist User.
JoinColumn: which means the column that should be used to join the tables, sure this column is the foreign key column in Credential ( think about it like this, if you want to join 2 tables which column shold be in ON clause).
the name="USER_ID" is the name of the column in the Source Table (in this case it is the Credential) and as you can see the name is USER_ID which is similar to the name we have in the Target Table.
in case the names are not similar you should set
@JoinColumn(name="Column_NAME_IN_SOURCE_TABLE", referencedColumnName="COLUMN_NAME_IN_TARGET_TABLE").

you define the JOINCOLUMN in the class that has the foreign key

4- now example of using this relation:

Bidirectional One to One Association
now we will continue in the above example, we will define a relation now from User to Credential:

as you can see here we define Credential with mappedBy="user" where user is the instance variable name in the Credentail table
Private User user;

never define a JOIN COLUMN in the reverse relationtion 
never define cascade in the reverse relation (you will create a loop)
we call the entity that has the join column (i.e. has the foreign key) the "OWNING ENTITIY"
the entity that doesnt have the foreign key "THE NON OWNING ENTITY"

Uni Directional one to many
we have this relation


we have one to many between Account and Transaction, and we will build a relationship from account to transaction.

so each account could be associated with multiple transactions.


we said before that the join column should be in the owning entity, and the owning entity is the table with the foreign key constrain, which means we should put the JOINCOLUMN in TRANSACTION.

however in this case we have a uni directional one to many, we will not have an Account field in Transaction object, and we need a place to specify the JOINCOLUMN, that is why we put it in Account.

Very important here, if you try to add Account and Transaction, we didnt set an inverse relation, which means we are not assigning Account_id in Transaction, which is a foreign key, which should not be null. now if you try to insert a record you will get an exception that the Account_id is null.

in order to solve this issue you should either specify the other side of the relationship or you should write @JoinColumn(name="ACCOUNT_ID", nullable = false).

Bi directional One To Many
so the first thing we should know that we have @OneToMany, and @ManyToOne
how do you read that, from the relation between Account and Transaction you say
We have One Account Related to Many Transaction ==> in Account we have @OneToMany
and we say we have ManyTransaction To One Account ==> in Transaction we have @ManyToOne

the transaction will look like this


as you can see we have now the JoinColumn in the owning entity, we have to remove the Join Column from the target entity and set mapped by.


One to Many with Join Table.
lets say that we have a Budget table, each budget is related to multiple transactions and each transaction has one budget.
This is a one to many relationship between the transaction table and the budget table.
however, not all Transactions has Budget, which means you will find alot of records with null value for the Budget Id.
that is why in this case you build this one to many relationship using a JOIN TABLE


as you can see we have BUDGET_TRANSACTION as a join table, one to one relationship between Transaction and Budget_Transaction and one to many between Budget and Budget_Transaction.

this is simply a one to many relation with a join table.

you can build that by



you can see, we use the jointable and joincolumn and inversejoincolumns

Uni-Directional Many to Many

lets say we have this relation,



in a uni directional many to many, we write this


defining the Join table in Account means that Account is the owning entity, now to make a bi directional many to many you do this

Bi Directional Many to Many
just define ManyToMany with mapped by


Section: 7 - Hibernate API V41 - V50


in hibernate the life cycle is so simple
The object can be Transient,Persistent, Removed or detached.

if you are Persistent or Removed you are in the Persistence Context.

Transient: when you create a normal POJO from an Entity you are in transient mode, so for example 
Bank x = new Bank(); this is a Transient object, it is not associated with a database record, 

Persistent: it means the entity (the object) is associated with a database record, the object here is in the Persistence Context. if you do any manipulation on this entity, this manipulation will be reflected in the DB as well.

Removed: you are in the persistence context and scheduled for deletion.

Detached: if you are an object in the persitent state however we close the Persistence Context ==> you will be in the Detached state.

What is a persistence context
Persistence Context is an object that provides us with a place to put all the entities which are in the persistent state. All the changes that we do on these entities will be in the Persistence Context and will be sync with the DB later.
We get a Persistence Context by using a session
when you openSession() you are creating a new persistence context.

Hibernate API

if you get() or load() from the database you will be in the Persistent state.
you can save() or saveOrUpdate() to move from Transient to Persistent
you can call delete() on a persistent entity to make it removed.
if the persistence context is closed the entity will be detached, if you still have a reference to that entity, you can attach it again and make it persistent by calling update() or saveOrUpdate().

also you can detach an entity (without closing the Persistence Context) by calling the evict() method.

here is an example

as you can see here after the bank was detached we called
session2.delete(bank), YOU CANNOT DO THAT IN JPA THIS IS SOMETHING ONLY IN HIBERNATE

Saving Entities

as you can see, firstly we openSession() (i.e create a Persitence Context).
then we create account, trans1 and trans2 (those are Transient Entitiy now).

then we do a simple check session.contains(account) to check if these entities are in the PersistenceContxt, of course will return FALSE.

then we begin the transaction, 
session.save(account) // now account is in Persistence state.

then we commit() which flushes the data to the database.
then we close() the context


Retrieving Entities from DB

we use get(CLASS TYPE, ID), as you can see get() executes a select statement

another example:

as you can see 2 get() and one select statment, the first get runs a select statmnet, the net get() for the same ID will get the result from the cache of the session.

another method to retrieve is load()
as you can see, load() is lazy, the select statment will run not when you do session.load(), it will run when you do bank.getName().

Modifying entities

as you can see the update statement runs when we do commit().

Removing Entities:



as you can see we get() --> select statment
then we check session.contains()--> true, the object is in the session.
then we delete()--> as you can see the delete() will not generate a delete statment to the database, the record will be delete when we flush(i.e. when we commit).
then we check session.contains() again --> false because the object is detached.
then transaction.comit()--> delete statment, we can see 2 delete statment because there is a cascade.ALL.

VERY IMPORTANT: after the bank object is deleted it should not be used anymore and it should be garbage collected because it is now deleted from the DB.

Reattaching detached object.
 we do that with update() or saveOrUpdate() methods

Flushing
the flush will happen if you call flush() or transaction.commit() or sometimes when we do select, a flush may occur


Section:8 - Hibernate API V51 - V58



In the previous section we talked about Hibernate API, as we know Hibernate is the implentation of JPA APIs, Hibernate added some extra APIs.0


we have Session in Hibernate and EntityManager in JPA.
and you can see in the table above the methods mapping.


In this section we will talk about JPA APIs

JPA Configuration
add persistence.xml , this file should be inside META-INF
add orb.hibernate dependency.


as you can see, in persistence.xml, you set the provider, in our case it is hibernate, which means we will use hibernate implementation for JPA. (other possible provider is eclipse links).

we dont have to specify the Entities we have here like what we were doing with hibernate.xml, the application will go over the classes in the class path and detect all the classes that are annotated with @Entity.

JPA Saving Entities

as you can see we have EntityManagerFactory in JPA which is similar to SesssionFactory in Hibernate.
we have EntityManager which is similar to Hibernate Session
we have EntityTransaction which is similar to Hibernate Transaction.

as you can see we use persist() in JPA to save to database

another thing "infinite-finance" is the persistence-unit name that is defined in the xml file


JPA Retreiving Entities

find() is similar to get() in hibernate.


getRegerence() is similar to load() in Hibernate.

JPA Modifying Entity 

here we do find()
then change the object
then on commit() the record will be updated

JPA Removing Entity

we use remove() which is similar to delete() in Hibernate

JPA Reattache 

we use detach() to detach, and merge() to attach again.


Section: 9 - Advanced Mapping and Configuration v59 - v69



Compound Primary Key
it is always better to use surrogate keys (i.e ID field).
however sometimes we need a compound keys:

we have this example
Currency table has 3 columns (CurrencyName, CountryName, Symbol).
the key is CurrencyName & CountryName (e.g. Dollar,US or Dollar,Canada).

to represent that:

1-

you can see, we use @Id for both fields, and we use IdClass(CurrencyId.class).

2- we define the IdClass

as you can see we defined the CurrencyId class, which implements serializable
THE FIELDS (name, countryName) MUST MATCH THE FIELDS NAME IN Currency class.


that is it, now if you want to use this key your wirte


as you can see, we use the CurrencyId object to get an object from database.

Compound Join Column
so now we have the Currency class, lets say we want to have a one to many relationship with this class.

how can we do the Join with a table where the table has 2 columns as a primary key
as you can see we use @JoinColumns and inside it set both columns

Enumaration
lets say you have this enum:


and you want to save this information in the table



Simply use @Enumerated

Mapped Superclass Inheritance 
lets say you have this data model
Stock (Stock_id, Name, Issuer, Purchase_date, Share_price, Quantity)
Bond (Bond _id, Name, Issuer, Purchase_date, Interest_Rate, Maturity_date)

so as you can see we have (Name, Issuer, Purchase_date) in both table, so we will abstract them and use inheritance when we define the entities:

this is the base class, notice the use of @MappedSuperclass


and here is the bond entity extending this class


IMPORTANT: when you are @MappedSuperClass, you dont have persistence life cycle, which means you cant have something like one to many relation with the Investment because it is not an entity, it is just heirachal thing


Table per class inheritance
to solve the issue in the previous example, we should not use @MappedSuperClass, we should use @Inheritance:

@Inheritance has 3 different mode, the first one is table per class, which means we should have a table for each class Bond, Stock and Investment ( the abstract class ).


we will not continue in the example the main idea is @Inheritance and the strategy is TABLE_PER_CLASS

in this TABLE_PER_CLASS, hibernate will do a UNION query to union the tables, this is a big drawback

Single Table Inheritance
in a single table inheritance, we will have only one table INVESTMENT, it has all the shared and unshared fields, we will distinguish between BOND and STOCK by adding what we call a discriminator field.


as you can see we defined the DiscrminatorColumn

now in Bond we do this

as you can see we removed the @Table annotation because Bond is not a table anymore

Building a Persistence Layer
it is better to have a package for Data.

start by a general DAO interface


Here you have the general operations that can be run on any table, find save delete

then implement this interface in AbstractDAO
basically you will implement all the methods in the DAO interface and we will add another methods that are generic for all interfaces



now we will have an DAO for each entity, so lets say user DAO


as you can see UserDAO extends DAO, so it will provide all the methods in DAO plus extra methods related to User, which is findByFirstName.

now we should implement this interface


as you can see we extednd the AbstractDAO to get all the general functionalities, and we implement the UserDAO functions.

so now if you have BANK, you create a BANK DAO interface then you implement it.

Views for COmplex Queries
sometimes you may have a complex query which you cannot do it in hibernate, in this case it is better to create a View in the database then you can simply map it in Hibernate:

Schema Generation
you can generate the tables based on the entities you defined, however this is something not for production, it is better just to do it for testing


as you can see, we should add this to the hibernate.cfg.xml

create means: create the tables
we have other options
validate: means check that the defined entities follow the tables structure we have in the database
update: if there is any new field for example it will be added
create-drop: means create the tables do everything then after we finish it will drop everything (which means when the program exits you will have a clean schema)


Section: 10 - Hibernate Query Language and Java Persistence Query Language v70 - v77


Writing Queries
you can write a query in hibernate like this:



in hibernate you can create like this



Expressions and Operators
in hibernate


just one thing when you use "t" in the example, you are using an object from transaction so you can write t.amount or go to another level for example t.amount.SOMETHING

in JPA



Parameters


another example



Joins



as you can see we have a normal join here

we have another thing which is called implecit join


as you can see there is no join there, however when you say select t.account, hibernate knows that we should do this join.

ALWAYSE USE THE EXPLICIT JOIN

Functions
sure you can use functions in your query


Named Query
sometimes you find yourself writing the same query multiple times, thats why we have named query, you define the query one time and then use it


then you can use it

Lazy Loading
you know that for relations we have eager or lazy fetching, to set the value and say if it is lazy or eager



Section: 11- Criteria API  v78 - v81


simple criteria like ordering


and you can do the same in JPA


Less than or equal criteria 

and in JPA


Pagination in Hibernate

pagination in JPA would be