JDBC and Hibernate
JDBC and Hibernate
Agenda
1. JDBC architecture
2. JDBC components
3. JDBC application
4. Hibernate architecture
5. Hibernate interfaces
6. Hibernate types
7. Hibernate persistence context
8. Hibernate associations
9. HQL / JPQL
3
JDBC
4
JDBC
The JDBC library includes APIs for each of the tasks mentioned
below that are commonly associated with database usage.
• making a connection to a database
• creating SQL or MySQL statements
• executing SQL or MySQL queries in the database
• viewing and modifying the resulting records
5
JDBC
Fundamentally, JDBC is a specification that provides
a complete set of interfaces that allows for portable access to
an underlying database. Java can be used to write different types
of executables. All different executables are able to use a JDBC
driver to access a database and take advantage of the stored data.
6
Architecture
JDBC
7
JDBC Architecture
8
JDBC Architecture
The JDBC API uses a driver manager and database specific drivers
to provide transparent connectivity to heterogeneous databases.
The JDBC Driver Manager ensures that the correct driver is used
to access each data source. The driver manager is capable
of supporting multiple concurrent drivers connected
to multiple heterogeneous databases.
9
JDBC Architecture
Java Application
JDBC API
Driver Manager
11
JDBC Components
12
JDBC Components
13
JDBC Components
Connection
Interface with all methods for contacting a database. The
connection object represents communication context.
Statement
You use objects created from this interface to submit the SQL
statements to the database. Some derived interfaces accept
parameters in addition to executing stored procedures.
14
JDBC Components
ResultSet
These objects hold data retrieved from a database after you
execute an SQL query using Statement objects. It acts
as an iterator to allow you to move through its data.
SQLException
This class handles any errors that occur in a database application.
15
JDBC Component Interaction Diagram
JDBC
Application JDBC Driver Connection Statement ResultSet Database
Interfaces
Load driver
Open connection
Open connection
Return connection
Return connection
Create statement
Create statement
Return statement
Execute statement
Execute statement
Return result
Return ResultSet (cursor)
Traverse ResultSet
Traverse result
(cursor)
Return records
Return records
17
JDBC Application
There are following steps involved in building a JDBC application:
• import the packages
• register the JDBC driver (automatically since ver. 4)
• open a connection
• execute a query
• extract data from result set
• clean up the environment
18
Maven – MySQL Connector
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
try {
Connection conn = DriverManager.getConnection(url, user, pass);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, email, country FROM user");
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
String country = rs.getString("country");
System.out.println(id + ", " + name + ", " + email + ", " + country);
}
}catch (SQLException ex){
ex.printStackTrace();
}
}
private void updateOperation(int id, String name, String email, String country){
try{
if(stmt != null) {
//UPDATE
int ret = stmt.executeUpdate("UPDATE user SET name = '" + name + "', " +
"email = '" + email + "', country = '" + country + "' WHERE id = " + id);
System.out.println("Update return: " + (ret == 1 ? "OK" : "ERROR"));
}
}catch (SQLException ex){
ex.printStackTrace();
}
}
private void updateOperation(int id, String name, String email, String country){
try{
if(conn != null) {
//UPDATE
PreparedStatement pstmt = conn.prepareStatement(UPDATE);
pstmt.setString(1, name);
pstmt.setString(2, email);
pstmt.setString(3, country);
pstmt.setInt(4, id);
int ret = pstmt.executeUpdate();
System.out.println("Update return: " + (ret == 1 ? "OK" : "ERROR"));
}
}catch (SQLException ex){
ex.printStackTrace();
}
}
27
Transactions
28
Transactions
Start a transaction
conn.setAutoCommit(isAutoCommit);
30
JDBC - Exercises
1. Connect to database
2. CRUD operations
3. Use PreparedStatement – supply values for parameters
4. Use transactions
32
Hibernate
Working with both Object-Oriented software and
Relational Databases can be cumbersome and time consuming.
Hibernate is an Object/Relational Mapping (ORM) solution
for Java environments.
The term ORM refers to the technique of mapping data between
an object model representation to
a relational data model representation.
33
Hibernate
34
Hibernate
Hibernates design goal is to relieve the developer from 95%
of common data persistence-related programming tasks by
eliminating the need for manual, hand-crafted data processing
using SQL and JDBC.
Hibernate can certainly help you to remove or encapsulate
vendor-specific SQL code and streamlines the common task
of translating result sets from a tabular representation
to a graph of objects.
35
Architecture
Hibernate
36
Hibernate - Architecture
37
Hibernate - Architecture
39
Hibernate - Interfaces
40
Hibernate - Interfaces
41
Hibernate - Interfaces
42
Hibernate - Interfaces
43
Domain model
Hibernate
44
Hibernate – Domain model
Domain model is the central character in an ORM. Hibernate
works best if these classes follow the Plain Old Java Object /
JavaBean programming model.
Hibernate understands both the Java and JDBC representations
of application data.
The ability to read/write this data from/to the database
is the function of a Hibernate type.
45
Types
Hibernate
46
Hibernate types
47
Basic types
48
Entity requirements (by JPA 2.1 Specification)
• Both abstract and concrete classes can be entities. Entities may extend non-entity
classes as well as entity classes, and non-entity classes may extend entity classes.
• The persistent state of an entity is represented by instance variables, which may
correspond to JavaBean-style properties. An instance variable must be directly
accessed only from within the methods of the entity by the entity instance itself.
The state of the entity is available to clients only through the entity’s accessor
methods (getter/setter methods) or other business methods.
• The entity class must have a no-argument constructor, which may be public,
protected or package visibility. It may define additional constructors as well.
• The entity class need not be a top-level class
• Technically Hibernate can persist final classes or classes with final persistent state
accessor (getter/setter) methods. However, it is generally not a good idea as doing
so will stop Hibernate from being able to generate proxies for lazy-loading the
entity.
• Hibernate does not restrict the application developer from exposing instance
variables and reference them from outside the entity class itself. The validity of such
a paradigm, however, is debatable at best.
• A class that acts as an identifier must implement equals/hashCode
based on the id value(s).
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
@Column(name = "country")
private String country;
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.9.Final</version>
</dependency>
1. Configure dependencies
2. Prepare proper configurations
3. Create simple entities
4. Implement equals() and hashCode() methods
56
Persistence context
57
Persistence context
58
Persistence context
59
Persistence context
60
Persistence context
61
Entity – create
•byId() •flush()
•byMultilpeIds() •get()
•byNaturalId() •load()
•clear() •merge()
•contains() •persist()
•createNamedQuery() •refresh()
•createQuery() •save()
•delete() •saveOrUpdate()
•evict() •update()
•@Entity •@ElementCollection
•@Table, @SecondaryTable •@Embedded, @Embeddable
•@Column •@EmbeddedId, @IdClass
•@Id, @NaturalId •@Transient
•@GeneratedValue •@Temporal
•@Basic •@Lob
•@Type •@Enumerated
•@Formula
•@PrePersist
•@PostPersist
•@PostLoad
•@PreUpdate
•@PostUpdate
•@PreRemove
•@PostRemove
•@EntityListeners
71
Associations
72
Associations
• @OneToOne
▪ @PrimaryKeyJoinColumn
▪ @JoinColumn
▪ @JoinTable
• @OneToMany, @ManyToOne
▪ @JoinColumn
▪ @JoinTable
• @ManyToMany
▪ @JoinTable
• unidirectional and bidirectional
@Entity
@Table(schema = "users", name = "employee")
@Entity
public class Employee {
@Table(schema = "users", name = "account")
public class Account {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
@Column(name = "email")
private Long id;
private String email;
@Column(name = "acc_number")
@Column(name = "first_name")
private String accountNumber;
private String firstName;
@Column(name = "date_employment")
@Column(name = "last_name")
private LocalDate dateEmployment;
private String lastName;
@OneToOne(mappedBy = "account")
@OneToOne
private Employee employee;
@JoinColumn(name = "account_id")
private Account account;
@Entity
@Table(schema = "owner", name = "users")
public class Owner {
@Entity
@Table(schema = "users", name = "book")
@Id
public class Book {
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "name")
private Long id;
private String name;
@Column(name = "title")
@Column(name = "email")
private String title;
private String email;
@ManyToOne
@Column(name = "country")
@JoinColumn(name = "owner_id")
private String country;
private Owner owner;
@OneToMany(mappedBy = "owner")
private List<Book> books;
@Entity
@Table(schema = "users", name = "author")
public class Author { @Entity
@Table(schema = "users", name = "book")
@Id public class Book {
@GeneratedValue(strategy =
GenerationType.AUTO) @Id
private Long id; @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "name")
private String name; @Column(name = "title")
private String title;
@Column(name = "surname")
private String surname; @ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "book_to_authors")
@ManyToMany(mappedBy = "authors", private Set<Author> authors;
cascade = CascadeType.ALL)
private Set<Book> books;
78
HQL / JPQL
79
@NamedQuery – Example
@NamedQueries({
@NamedQuery(
name = "get_person_by_name",
query = "from Person where lastName like :name"
)
})
@NamedQuery(
name = "get_person_by_mobile",
query = "select pr from Person pr join pr.phones ph where ph.type = :phoneType"
)
@NamedQuery(
name = "get_person_by_land_line",
query = "select pr from Person pr left join pr.phones ph where ph is null or ph.type = :phoneType"
)