Sử dụng Hibernate

Giới thiệu nội dung bài viết

Chào các em ,chủ để hôm nay chúng ta sẽ tìm hiểu về Hibernate .


1. Giới thiệu 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


2. Cấu hình Hibernate với Spring

Bước 1 : Nhúng thư viện hibernate vào dự án qua file pom

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>

Bước 2 : Tạo file khai báo kết nối database

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

Bước 3 :Chúng ta có thể cấu hình Hibernate qua Java

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");
         }
      };
   }
}

Bước 4. Tạo entity (ORM)

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;

Bước 5. Sử dụng truy vẫn dữ liệu

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();
	}

}


3. Kết luận

Để 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.

Xin vui lòng bình luận bài viết dưới đây có hữu ích hay không? Nếu có nhiều bài viết khác mà anh chưa kịp cập nhật các em có thể bình luận kèm link liên kết anh sẽ cập nhật bài viết của mình nhé.

Mọi người hãy subcribe kênh youtube dưới đây nhé. Videos về các kỹ năng mềm và lập trình sẽ được cập nhật hằng tuần


Comments