Hibernate
- What is it?
- Access Hibernate using Spring
- Advantages of hibernate
- Core interfaces of Hibernate framework
- Criteria API
- Hibernate communication with RDBMS
- Hibernate Query Language HQL
- ways to express joins in HQL
- HibernateTemplate
- Hibernate xml mapping file
- map Java Objects with Database tables / component mapping
- merge() vs update()
- sequence generated primary key in hibernate
- cascade
- orphan
- Many-to-many associations
- One-to-many associations
- Bidirectional associations
- Named – SQL query
- invoke Stored Procedures
- switch between relational databases without code changes
- show_sql
- sorted collection vs ordered collection in hibernate
- advantage of Hibernate over jdbc
- Collection types in Hibernate
- Hibernate proxy
- How can Hibernate be configured to access an instance variable directly and not through a setter method ?
- How can a whole class be mapped as immutable?
- what is the use of dynamic-insert and dynamic-update attributes in a class mapping?
- fetching strategy
- automatic dirty checking
- transactional write-behind
- Callback interfaces
- Types of Hibernate instance states
- differences between EJB 3.0 & Hibernate
- types of inheritance models in Hibernate
- hibernate vs iBatis
- Tags
TODO
https://www.bezkoder.com/jpa-one-to-one/
What is it?
Hibernate is a pure Java object-relational mapping (ORM) and persistence framework that allows you to map plain old Java objects to relational database tables using (XML) configuration files.Its purpose is to relieve the developer from a significant amount of relational data persistence-related programming tasks.
TODO
https://vladmihalcea.com/hibernate-types-hypersistence-utils/
https://github.com/vladmihalcea/hypersistence-utils
TODO Clean up this document
Access Hibernate using Spring
There are two approaches to Spring’s Hibernate integration:
- Inversion of Control with a HibernateTemplate and Callback
- Extending HibernateDaoSupport and Applying an AOP Interceptor:
- Spring and Hibernate can integrate using Spring’s SessionFactory called LocalSessionFactory. The integration
- process is of 3 steps.
- – Configure the Hibernate SessionFactory
- – Extend your DAO Implementation from HibernateDaoSupport
- – Wire in Transaction Support with AOP
Advantages of hibernate
Hibernate simplifies:
- Saving and retrieving your domain objects
- Making database column and table name changes
- Centralizing pre save and post retrieve logic
- Complex joins for retrieving related items
- Schema creation from object model
Core interfaces of Hibernate framework
The five core interfaces are used in just about every Hibernate application. Using these interfaces, you can store and retrieve persistent objects and control transactions.
-
Session interface
- The Session interface is the primary interface used by Hibernate applications. It is a single-threaded, short-lived
- object representing a conversation between the application and the persistent store. It allows you to create query
- objects to retrieve persistent objects.
Session session = sessionFactory.openSession();
Session interface role: Wraps a JDBC connection Factory for Transaction Holds a mandatory (first-level) cache of persistent objects, used when navigating the object graph or looking up objects by identifier
-
SessionFactory interface
- The application obtains Session instances from a SessionFactory. There is typically a single SessionFactory for the
- whole application related during application initialization. The SessionFactory caches generate SQL statements
- and other mapping metadata that Hibernate uses at runtime. It also holds cached data that has been read in one
- unit of work and may be reused in a future unit of work.
SessionFactory sessionFactory = configuration.buildSessionFactory();
-
Configuration interface
-
Transaction interface
-
Query and Criteria interfaces
Criteria API
Criteria is a simplified API for retrieving entities by composing Criterion objects. This is a very convenient approach for functionality like “search” screens where there is a variable number of conditions to be placed upon the result set. Example : List employees = session.createCriteria(Employee.class) .add(Restrictions.like(“name”, “a%”) ) .add(Restrictions.like(“address”, “Boston”)) .addOrder(Order.asc(“name”) ) .list();
Hibernate communication with RDBMS
The general flow of Hibernate communication with RDBMS is :
- Load the Hibernate configuration file and create configuration object. It will automatically load all hbm mapping files
- Create session factory from configuration object
- Get one session from this session factory
- Create HQL Query
- Execute query to get list containing Java objects
Hibernate Query Language HQL
Hibernate offers a query language that embodies a very powerful and flexible mechanism to query, store, update, and retrieve objects from a database. This language, the Hibernate query Language (HQL), is an object-oriented extension to SQL.
ways to express joins in HQL
HQL provides four ways of expressing (inner and outer) joins:-
- An implicit association join
- An ordinary join in the FROM clause
- A fetch join in the FROM clause.
- A theta-style join in the WHERE clause.
HibernateTemplate
org.springframework.orm.hibernate.HibernateTemplate is a helper class which provides different methods for querying/retrieving data from the database. It also converts checked HibernateExceptions into unchecked DataAccessExceptions. The benefits of HibernateTemplate are :
- HibernateTemplate, a Spring Template class simplifies interactions with Hibernate Session.
- Common functions are simplified to single method calls.
- Sessions are automatically closed.
- Exceptions are automatically caught and converted to runtime exceptions.
Hibernate xml mapping file
Hibernate mapping file tells Hibernate which tables and columns to use to load and store objects. Typical mapping file look as follows:
map Java Objects with Database tables / component mapping
- First we need to write Java domain objects (beans with setter and getter).
- Write hbm.xml, where we map java class to table and database columns to Java class variables.
Example :
<hibernate-mapping>
<class name="com.test.User" table="user">
<property column="USER_NAME" length="255"
name="userName" not-null="true" type="java.lang.String"/>
<property column="USER_PASSWORD" length="255"
name="userPassword" not-null="true" type="java.lang.String"/>
</class>
</hibernate-mapping>
- A component is an object saved as a value, not as a reference
- A component can be saved directly without needing to declare interfaces or identifier properties
- Required to define an empty constructor
- Shared references not supported
merge() vs update()
Use update() if you are sure that the session does not contain an already persistent instance with the same identifier, and merge() if you want to merge your modifications at any time without consideration of the state of the session.
sequence generated primary key in hibernate
Using <generator> tag.
Example:-
<id column="USER_ID" name="id" type="java.lang.Long">
<generator class="sequence">
<param name="table">SEQUENCE_NAME</param>
<generator>
</id>
cascade
cascade - enable operations to cascade to child entities. cascade=“all | none | save-update | delete|all-delete-orphan” In cascade, after one operation (save, update and delete) is done, it decide whether it need to call other operations (save, update and delete) on another entities which has relationship with each other. Cascade is a convenient feature to save the lines of code needed to manage the state of the other side manually. The “Cascade” keyword is often appear on the collection mapping to manage the state of the collection automatically.
- cascade=“none”, the default, tells Hibernate to ignore the association.
- cascade=“save-update” tells Hibernate to navigate the association when the
transaction is committed and when an object is passed to save() or update() and save newly instantiated transient instances and persist changes to detached instances.
- cascade=“delete” tells Hibernate to navigate the association and delete persistent
instances when an object is passed to delete().
- cascade=“all” means to cascade both save-update and delete, as well as
calls to evict and lock.
- cascade=“all-delete-orphan” means the same as cascade=“all” but, in addition,
Hibernate deletes any persistent entity instance that has been removed (dereferenced) from the association (for example, from a collection).
- cascade=“delete-orphan” Hibernate will delete any persistent entity
instance that has been removed (dereferenced) from the association (for example, from a collection).
orphan
I have a one-to-one relationship between two entities, say user and address. I am using a unique foreign key mapping like this: In User: <many-to-one name=“address” class=“Address” column=“AddressId” unique=“true” cascade=“all-deleteorphan” /> In Address: <one-to-one name=“user” class=“User” property-ref=“address” /> When I set user.Address to null and save the user, I would have thought that the address would be deleted from the system, but the generated sql just updates User setting its AddressId column to null. In Hibernate In Action page 133 it says: “all-delete-orphan […] deletes any persistent entity instance that has been removed (derefenced) from the association …” I solved the problem by directly deleting the address as well as setting user.address to null but …
- Why do I need to directly delete the address?
- Is there a mapping setting I’m missing? or
- Is this a bug (as I think that it’s not the expected behavior)?
The ref docs section 5.1.10 says “Note that single valued associations (many-to-one and one-to-one associations) do not support orphan delete.” This is the expected behaviour. inverse inverse - mark this collection as the “inverse” end of a bidirectional association. inverse=“true|false” Essentially “inverse” indicates which end of a relationship should be ignored. This is used to decide which side is the relationship owner to manage the relationship (insert or update of the foreign key column). In short, the “inverse” decides which side will update the foreign key, while “cascade” decides what the follow by operation should execute. Both are look quite similar in relationship, but totally two different things. It’s much simpler: If you map the same foreign key column twice, you need to “disable” one side by making it inverse. Which side varies. If I have a one-to-many with a persistent List or Map, I’d make that side inverse=“false” and the many-to-one should be disabled for updating/insertion with insert=“false” and update=“false”. If I have one-to-many with a persistent Set, I’d make that side inverse=“true” and let the many-to-one update/insert the foreign key column. If I have a many-to-many with a persistent Set on both sides, I can pick which side is “disabled”, no difference. If I have a many-to-many with a persistent List or Map on one of the sides, I need to enable that side and disable the other side (otherwise the index/map key of that list or map isn’t stored.) That’s it. Any collection of values or many-to-many associations requires a dedicated collection table with a foreign key column or columns, collection element column or columns, and possibly an index column or columns. For a collection of values use the <element> tag. For example:
<element
column="column_name"
formula="any SQL expression"
type="typename"
length="L"
precision="P"
scale="S"
not-null="true|false"
unique="true|false"
node="element-name"
/>
Many-to-many associations
A many-to-many association is specified using the <many-to-many> element.
<many-to-many
column="column_name"
formula="any SQL expression"
class="ClassName"
fetch="select|join"
unique="true|false"
not-found="ignore|exception"
entity-name="EntityName"
property-ref="propertyNameFromAssociatedClass"
node="element-name"
embed-xml="true|false"
/>
column (optional): the name of the element foreign key column. formula (optional): an SQL formula used to evaluate the element foreign key value. class (required): the name of the associated class. fetch (optional - defaults to join): enables outer-join or sequential select fetching for this association. This is a special case; for full eager fetching in a single SELECT of an entity and its many-to-many relationships to other entities, you would enable join fetching,not only of the collection itself, but also with this attribute on the <many-to-many> nested element. unique (optional): enables the DDL generation of a unique constraint for the foreign-key column. This makes the association multiplicity efectively one-to-many. not-found (optional - defaults to exception): specifies how foreign keys that reference missing rows will be handled: ignore will treat a missing row as a null association. entity-name (optional): the entity name of the associated class, as an alternative to class. property-ref (optional): the name of a property of the associated class that is joined to this foreign key. If not specified, the primary key of the associated class is used. Here are some examples. A set of strings:
<set name="names" table="person_names">
<key column="person_id"/>
<element column="person_name" type="string"/>
</set>
A bag containing integers with an iteration order determined by the order-by attribute:
<bag name="sizes"
table="item_sizes"
order-by="size asc">
<key column="item_id"/>
<element column="size" type="integer"/>
</bag>
An array of entities, in this case, a many-to-many association:
<array name="addresses"
table="PersonAddress"
cascade="persist">
<key column="personId"/>
<list-index column="sortOrder"/>
<many-to-many column="addressId" class="Address"/>
</array>
A map from string indices to dates:
<map name="holidays"
table="holidays"
schema="dbo"
order-by="hol_name asc">
<key column="id"/>
<map-key column="hol_name" type="string"/>
<element column="hol_date" type="date"/>
</map>
One-to-many associations
A one-to-many association links the tables of two classes via a foreign key with no intervening collection table. This mapping loses certain semantics of normal Java collections: ◦ An instance of the contained entity class cannot belong to more than one instance of the collection. ◦ An instance of the contained entity class cannot appear at more than one value of the collection index. An association from Product to Part requires the existence of a foreign key column and possibly an index column to the Part table. A <one-to-many> tag indicates that this is a one-to-many association.
<one-to-many
class="ClassName"
not-found="ignore|exception"
entity-name="EntityName"
node="element-name"
embed-xml="true|false"
/>
class (required): the name of the associated class. not-found (optional - defaults to exception): specifies how cached identifiers that reference missing rows will be handled. ignore will treat a missing row as a null association. entity-name (optional): the entity name of the associated class, as an alternative to class. The <one-to-many> element does not need to declare any columns. Nor is it necessary to specify the table name anywhere. The following example shows a map of Part entities by name, where partName is a persistent property of Part. Notice the use of a formula-based index:
<map name="parts"
cascade="all">
<key column="productId" not-null="true"/>
<map-key formula="partName"/>
<one-to-many class="Part"/>
</map>
Bidirectional associations
A bidirectional association allows navigation from both “ends” of the association. Two kinds of bidirectional association are supported: one-to-many set or bag valued at one end and single-valued at the other many-to-many set or bag valued at both ends You can specify a bidirectional many-to-many association by mapping two many-to-many associations to the same database table and declaring one end as inverse. You cannot select an indexed collection. Here is an example of a bidirectional many-to-many association that illustrates how each category can have many items and each item can be in many categories:
<class name="Category">
<id name="id" column="CATEGORY_ID"/>
...
<bag name="items" table="CATEGORY_ITEM">
<key column="CATEGORY_ID"/>
<many-to-many class="Item" column="ITEM_ID"/>
</bag>
</class>
<class name="Item">
<id name="id" column="ITEM_ID"/>
...
<!-- inverse end -->
<bag name="categories" table="CATEGORY_ITEM" inverse="true">
<key column="ITEM_ID"/>
<many-to-many class="Category" column="CATEGORY_ID"/>
</bag>
</class>
Changes made only to the inverse end of the association are not persisted. This means that Hibernate has two representations in memory for every bidirectional association: one link from A to B and another link from B to A. This is easier to understand if you think about the Java object model and how a many-to-many relationship in Javais created:
category.getItems().add(item); // The category now "knows" about the relationship
item.getCategories().add(category); // The item now "knows" about the relationship
session.persist(item); // The relationship won't be saved!
session.persist(category); // The relationship will be saved
The non-inverse side is used to save the in-memory representation to the database. You can define a bidirectional one-to-many association by mapping a one-to-many association to the same table column(s) as a many-to-one association and declaring the many-valued end inverse=“true”.
<class name="Parent">
<id name="id" column="parent_id"/>
....
<set name="children" inverse="true">
<key column="parent_id"/>
<one-to-many class="Child"/>
</set>
</class>
<class name="Child">
<id name="id" column="child_id"/>
....
<many-to-one name="parent"
class="Parent"
column="parent_id"
not-null="true"/>
</class>
Mapping one end of an association with inverse=“true” does not afect the operation of cascades as these are orthogonal concepts.
Named – SQL query
Named SQL queries are defined in the mapping xml document and called wherever required. Example:
<sql-query name = "empdetails">
<return alias="emp" class="com.test.Employee"/>
SELECT emp.EMP_ID AS {emp.empid},
emp.EMP_ADDRESS AS {emp.address},
emp.EMP_NAME AS {emp.name}
FROM Employee EMP WHERE emp.NAME LIKE :name
</sql-query>
Invoke Named Query :
List people = session.getNamedQuery("empdetails")
.setString("TomBrady", name)
.setMaxResults(50)
.list();
invoke Stored Procedures
<sql-query name="selectAllEmployees_SP" callable="true">
<return alias="emp" class="employee">
<return-property name="empid" column="EMP_ID"/>
<return-property name="name" column="EMP_NAME"/>
<return-property name="address" column="EMP_ADDRESS"/>
{ ? = call selectAllEmployees() }
</return>
</sql-query>
switch between relational databases without code changes
Using Hibernate SQL Dialects , we can switch databases. Hibernate will generate appropriate hql queries based on the dialect defined.
show_sql
If you want to see the Hibernate generated SQL statements on console, what should we do?
In Hibernate configuration file set as follows: <property name="show_sql">true</property>
sorted collection vs ordered collection in hibernate
advantage of Hibernate over jdbc
Collection types in Hibernate
- Bag
- Set
- List
- Array
- Map
Hibernate proxy
The proxy attribute enables lazy initialization of persistent instances of the class. Hibernate will initially return CGLIB proxies which implement the named interface. The actual persistent object will be loaded when a method of the proxy is invoked.
How can Hibernate be configured to access an instance variable directly and not through a setter method ?
By mapping the property with access=“field” in Hibernate metadata. This forces hibernate to bypass the setter method and access the instance variable directly while initializing a newly loaded object.
How can a whole class be mapped as immutable?
Mark the class as mutable=“false” (Default is true),. This specifies that instances of the class are (not) mutable. Immutable classes, may not be updated or deleted by the application.
what is the use of dynamic-insert and dynamic-update attributes in a class mapping?
fetching strategy
A fetching strategy is the strategy Hibernate will use for retrieving associated objects if the application needs to navigate the association. Fetch strategies may be declared in the O/R mapping metadata, or over-ridden by a particular HQL or Criteria query.
automatic dirty checking
Automatic dirty checking is a feature that saves us the effort of explicitly asking Hibernate to update the database when we modify the state of an object inside a transaction. Persistent Object Updates and Automatic Dirty Checking Hibernate monitors all Persistent objects (i.e. the persistent context). At the end of a unit of work, it knows which objects have been modified. It then calls update statements on all updated objects. This process of monitoring and updating only objects that have changed is called automatic dirty checking. As opposed to updating all Persistent objects at the end of each work, automatic dirty checking can offer significant performance savings. While a session remains open, if a Persistent object is modified, its data is kept synchronized with the database. The data will be synchronized (but not committed) when session.flush() is called. It will be synchronized and committed when the transaction is committed. It may be synchronized at other points. For example, before Hibernate performs some queries of the database. For example, in the code below a change to a BallPlayer object during a session does not require any special method call to persist the change. Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); BallPlayer p = (BallPlayer)session.get(BallPlayer.class, 1L); p.setNickname(“Bambino”); transaction.commit(); //new nickname is synch’ed and committed here session.close(); Hibernate knows and tracks the Persistent object and its state change. Merely committing the transaction will cause the new data to be synchronized to the database with an update statement. Update Player set name=?, nickname=?, date_of_birth=?, city_of_birth=?, uniform_number=? Where id=?
transactional write-behind
Hibernate uses a sophisticated algorithm to determine an efficient ordering that avoids database foreign key constraint violations but is still sufficiently predictable to the user. This feature is called transactional write-behind.
Callback interfaces
Callback interfaces allow the application to receive a notification when something interesting happens to an object—for example, when an object is loaded, saved, or deleted. Hibernate applications don’t need to implement these callbacks, but they’re useful for implementing certain kinds of generic functionality.
Types of Hibernate instance states
Three types of instance states:
- Transient -The instance is not associated with any persistence context
- Persistent -The instance is associated with a persistence context
- Detached -The instance was associated with a persistence context which has been closed – currently not associated
differences between EJB 3.0 & Hibernate
types of inheritance models in Hibernate
hibernate vs iBatis
Hibernate works well when you control the data model, iBATIS works well when you need to integrate with an existing database. Using iBATIS, there isn’t a whole lot of magic, and you get full control over the SQL - which would likely be easier to understand. if you design your application starting from an object model, the database platform is a moving target, you have a complex object model with lots of different queries to perform, Hibernate is your choice. On the contrary, if you think relational and the application is a by-product of the database design, then iBatis should be better. ibatis: -Simpler -faster development time -flixable -Much smaller in package size hibernate: -generate SQL for you which means you don’t spend time on SQL -provide much more advance cache -scalable consider a scenario where Hibernate work great for initial model. Now Suddenly if you are using stored procedures, well we can do it in Hibernate but its little difficult; ok we map those, all of sudden we got some reporting type of queries, those don’t have keys have group bys; with some difficulty here we can use name queries and stuff like that, but now starts getting more complicated, we have complex joins, yes you can do in hibernate, but we can’t do with average developer. We have sql that just doesn’t work. if am looking at an application that doesn’t work very well with an ORM, aside from these considerations of using stored procedures, already using SQL, complex joins. In other words, Hibernate works very well if your data model is well in sync with object model, because ORM solutions like Hibernate map object to tables. However, let’s suppose data model is not in sync with object model, in this case you have do lot of additional coding and complexities are entering into your application, start coming the beyond the benefits of ORM. So, again all of sudden you are noticing that the flow is gone; our application is becoming very very complex and developers can’t maintain the code. This is where the model starts breaking down. One size does not fit all. So this is where I like to use iBatis; as the alternative solution for these type of situations, iBatis maps results sets to objects, so no need to care about table structures. This works very well for stored procedures, works very well for reporting applications, etc,. Now the question is , does it work well for simple CRUD applications? Well, it works because what we have to write is sql. Then why not use Hibernate for that? You can start see Some of the decision criteria that comes into play. So one of the other follow on questions that typically get is , can I use both? That’s really interesting question! because the answer is sure. But,such a thing will never ever exists is java persistence world. However we can kind of use both to create this little hybrid. So think of this kind scenario, we have very large application where Hibernate is working very well for it, but we have a reporting piece that just is a real nag , its query only , so we can do is, we can use iBatis to pull up the queries for reporting piece and still use Hibernate for all the operational stuff and updates. This model actually works well, it doesn’t break the transactional model, and it doesn’t affect any of the primary & secondary caches with a Hibernate. It’s a good solution. • Use iBatis if ◦ You want to create your own SQL’s and are willing to maintain them ◦ your environment is driven by relational data model ◦ you have to work existing and complex schema’s • Use Hibernate if ◦ your environment is driven by object model and wants generates SQL automatically The message is, • One size does not fit all the java persistence and the important to know there are other solutions besides the traditional ORMs, and that would be iBatis. • Both the solutions work well, given their specific domain. • Look for the opportunity where you can use both. refer: Accessing Hibernate using Spring