Chào các em ,chủ để hôm nay chúng ta sẽ tìm hiểu về Hibernate .
Như các em biết để hiển thị được dữ liệu lưu trữ trong cơ sở dữ liệu (database) ra cho người dùng thì mình phải thao tác xuống database như kết nối vào database .Sau đó thực hiện các câu lệnh truy vấn như select , insert, update , join các bảng .Cuối cùng là lấy dữ liệu từ database về và xử lý. Trong lập trình java mình may mắn có một framework giúp mình làm được tất cả các việc đó. Nó chính là Hibernate.
Vì sao ta nên sử dụng framework , bởi vì nó đã có sẳn các thư viện như kết nối xuống database, thực hiện các câu truy vấn chúng ta chỉ sử dụng các thư việc có sẳn mà framework cung cấp và nhiệm vụ của chúng ta chỉ tập trung vào xử lý các nghiệp vụ của phần mềm.
Hibernate là một framework được sử dụng ở tầng Persistence. Tầng Persisten có nghĩa là lưu trử và sử lý dữ liệu trong một khoảng thời gian dài. Hibernate là mã nguồn mở , ta có thể nhúng vào dự án và dùng không phải trả tiền
Các chức năng được hỗ trợ khi ta sử dụng Hibernate
Auto DDL : DDL có nghĩa là các câu lệnh định nghĩa cấu trúc để lưu trữ dữ liệu như create table , columns , kiểu dữ liệu trong database. Hiberate có thể tự động tạo table, columns, kiểu dữ liệu thông qua các annotaion mà ta thêm trong Entity mà ta không cần phải vào database tạo các table , column bằng tay
Auto Primary Key : Trong database để đánh dấu một trường là khoá chính thì ta phải làm bằng tay hoặc viết câu lệnh SQL để đánh dấu một trường là khoá chính của table. Hibernate có thể làm việc này một cách tự động
HQL query : Để thực hiện các câu lệnh truy vấn và thao tác dữ liệu thì ta dùng cú pháp HQL (Hibernate Query Language) để lấy dữ liệu ra thay vì viết câu lệnh SQL như select * from table . Mà chúng ta có thể viết bằng ngôn ngữ HQL như select customer from customer customer . Khi sử dụng HQL thì ta không phụ thuộc vào database đang sử dụng là gì vì câu lệnh HQL nó tương thích với các database quan hệ khác nhau như mysql , postgress .Giúp chúng ta không phụ thuộc vào database.
Hibernate Cache : giúp chúng ta có thể cache (lưu lại câu query) lại câu truy vấn mà không phải thực hiện thao tác, truy xuất xuống database nhiều lần. A ví dụ như câu select * from customer trả về 1000 kết quả. những kết quả này sẽ được lưu lại trong bộ nhớ. Khi có câu lại có câu lệnh select * from customer lần nữa. Vì nó đã lưu kết quả trong bộ nhớ nên nó sẽ trả về 1000 kết quả giống lần đầu tiên vì câu query giống nhau. Như vậy các em thấy dù có 1000 câu truy vấn thì Hibernate chỉ kết nối xuống database lần đầu tiên thôi. Điều này giúp cho ứng dụng nhanh hơn vì không phải mất thời gian kết nối xuống database và thực hiện truy vấn thêm nữa.
Hibernate hỗ trợ ORM mapping. Các em có thể xem lại bài blog về ORM anh đã viết để nắm rõ thêm ORM là gì ?
Hầu hết các dự án Java ngày nay đều sử dụng Spring Data JPA kết hợp với Hibernate như một công cụ để thao tác giữa ứng dụng của mình và database
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.18.2-GA</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-dbcp</artifactId>
<version>7.0.55</version>
</dependency>
Chúng ta tạo file persistence-mysql.properties khai báo username , database trong file properties. Khi spring chạy nó sẽ vào đây dể biết được phải kết nối database ở đâu .
1
2
3
4
5
6
7
8
9
10
# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate_dev?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-mysql.properties" })
@ComponentScan({ "levunguyen.spring.persistence" })
public class PersistenceConfig {
@Autowired
private Environment env;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(
new String[] { "levunguyen.spring.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager txManager
= new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers",
"true");
}
};
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private long id;
@Column(name = "emp_name")
private String name;
@Column(name = "emp_salary")
private double salary;
@OneToOne(mappedBy = "employee")
@Cascade(value = org.hibernate.annotations.CascadeType.ALL)
private Address address;
Chúng ta sử dụng sessionFactory để mở kết nối và thực hiện các câu lệnh truy vấn xuống database.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
public abstract class HibernateDAO{
@Autowired
SessionFactory sessionFactory;
protected Session getCurrentSession(){
return sessionFactory.getCurrentSession();
}
public void query(String[] args) {
//Prep work
Session session = sessionFactory.getCurrentSession();
//HQL example - Get All Employees
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Employee");
List<Employee> empList = query.list();
for(Employee emp : empList){
System.out.println("List of Employees::"+emp.getId()+","+emp.getAddress().getCity());
}
//HQL example - Get Employee with id
query = session.createQuery("from Employee where id= :id");
query.setLong("id", 3);
Employee emp = (Employee) query.uniqueResult();
System.out.println("Employee Name="+emp.getName()+", City="+emp.getAddress().getCity());
//HQL pagination example
query = session.createQuery("from Employee");
query.setFirstResult(0); //starts with 0
query.setFetchSize(2);
empList = query.list();
for(Employee emp4 : empList){
System.out.println("Paginated Employees::"+emp4.getId()+","+emp4.getAddress().getCity());
}
//HQL Update Employee
query = session.createQuery("update Employee set name= :name where id= :id");
query.setParameter("name", "Pankaj Kumar");
query.setLong("id", 1);
int result = query.executeUpdate();
System.out.println("Employee Update Status="+result);
//HQL Delete Employee, we need to take care of foreign key constraints too
query = session.createQuery("delete from Address where id= :id");
query.setLong("id", 4);
result = query.executeUpdate();
System.out.println("Address Delete Status="+result);
query = session.createQuery("delete from Employee where id= :id");
query.setLong("id", 4);
result = query.executeUpdate();
System.out.println("Employee Delete Status="+result);
//HQL Aggregate function examples
query = session.createQuery("select sum(salary) from Employee");
double sumSalary = (Double) query.uniqueResult();
System.out.println("Sum of all Salaries= "+sumSalary);
//HQL join examples
query = session.createQuery("select e.name, a.city from Employee e "
+ "INNER JOIN e.address a");
List<Object[]> list = query.list();
for(Object[] arr : list){
System.out.println(Arrays.toString(arr));
}
//HQL group by and like example
query = session.createQuery("select e.name, sum(e.salary), count(e)"
+ " from Employee e where e.name like '%i%' group by e.name");
List<Object[]> groupList = query.list();
for(Object[] arr : groupList){
System.out.println(Arrays.toString(arr));
}
//HQL order by example
query = session.createQuery("from Employee e order by e.id desc");
empList = query.list();
for(Employee emp3 : empList){
System.out.println("ID Desc Order Employee::"+emp3.getId()+","+emp3.getAddress().getCity());
}
//rolling back to save the test data
tx.rollback();
//closing hibernate resources
sessionFactory.close();
}
}
Để kết nối và thao tác với database chúng ta có thể dùng Hibernate framework để mình truy xuất và thao tác các dữ liệu. Ngoài Hibernate thông thường các dự án Spring thì mình dùng Spring Data JPA (bài JPA là gì mọi người có thể tham khảo bài viết trước của anh).
Vậy Hibernate và Spring Data JPA thì khác biệt gì nhau. Trước tiên chúng ta phải hiểu các khái niệm sau
JPA : Java Persistence API, cung cấp các chuẩn để kết nối database , truy vấn dữ liệu, lưu trữ dữ liệu.
Hibernate là một trong số provider (nhà cung cấp dịch vụ trong việc thao tác với database) cài đặt và tuân thủ các chuẩn JPA để thao tác , lưu trữ và truy xuất dữ liệu
Spring JPA : là một tầng được xây dựng ở trên JPA. Nó abstract (trừa tượng hoá các thư viện). Chúng ta chỉ cần dùng và tập trung và nghiệp vụ giúp chúng ta dể dàng quản lý, maintain code.
Thông thường ở dự án Spring mình kết hợp cả 2. Mình sử dụng Hibernate là provider cho ORM , các validation và kết hợp với Spring Data JPA để thao tác với database.