Spring Hibernate – Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

Spring Hibernate – Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

1. Giới thiệu Spring ORM

Spring cung cấp API giúp lập trình viên dễ dàng tích hợp Spring với ORM Framework như JPA(Java Persistence API), JDO(Java Data Objects), Oracle Toplink and iBATIS.

Lợi ích của ORM Framework với Spring

Có khá nhiều lợi ích khi kết hợp Spring Framework với ORM framework:

  • Viết code ít hơn: Không cần phải viết code trước và sau khi truy vấn với database qua connection (ví dụ start connection, start transaction, commit transaction, close connection…)
  • Dễ test hơn:
  • Xử lý exception tốt hơn: Spring framewrok cung cấp các API để xử lý exception với ORM framework
  • Tích hợp quản lý transaction: Spring hỗ trợ khả năng quản lý transaction qua AOP (Xem lại ví dụ xử lý transaction với JDBC)

2. Tích hợp Spring Framework với Hibernate Framework

Hibernate là 1 framework thực hiện cài đặt lại JPA

Trong hibernate, chúng ta khai báo thông tin của database trong file hibernate.cfg.xml.

Nếu tích hợp Hibernate với Spring thì chúng ta không cần tạo file hibernate.cfg.xml, chúng ta có thể cung cấp tất cả thông tin trong file spring config.

Việc tích hợp Hibernate với Spring còn giúp chúng ta bớt được rất nhiều code, và không cần phải làm nhiều bước như tạo Configuration, BuildSessionfactory, Session, tạo và commit Transaction…

3. Code ví dụ Spring Hibernate

Ở ví dụ này mình sử dụng:

Tạo database:

CREATE SCHEMA `demo-spring-hibernate` ;
CREATE TABLE `demo-spring-hibernate`.`customer` (
  `id` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NULL,
  `address` VARCHAR(255) NULL,
  PRIMARY KEY (`id`));

Spring Hibernate - Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

Tạo maven project:

Spring Hibernate - Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

Thư viện sử dụng:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>stackjava.com</groupId>
  <artifactId>DemoJDBC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <dependencies>
    <!-- Spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>5.0.2.RELEASE</version>
    </dependency>

    <!-- Hibernate -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.2.12.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>5.2.12.Final</version>
    </dependency>
    <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
    </dependency>

    <!-- MySQL -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.45</version>
    </dependency>

  </dependencies>
</project>

File Spring config:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

  <context:annotation-config />
  <context:component-scan base-package="stackjava.com.springhibernate" />
  

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
      value="jdbc:mysql://localhost:3306/demo-spring-hibernate" />
    <property name="username" value="root" />
    <property name="password" value="admin1234" />
  </bean>
  
  <bean id="sessionFactory"
    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    
    <property name="packagesToScan" value="stackjava.com.springhibernate.entities" />
    <!-- <property name="annotatedClasses">
      <list>
        <value>stackjava.com.springhibernate.entities.Customer</value>
      </list>
    </property> -->
    
    
    <property name="hibernateProperties" value="classpath:hibernate.properties" />
    <!-- <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.current_session_context_class">thread</prop>
        <prop key="hibernate.show_sql">false</prop>
      </props>
    </property> -->
    
  </bean>

</beans>
  • org.apache.commons.dbcp.BasicDataSourcechứa các thông tin kết nối tới database
  • org.springframework.orm.hibernate5.LocalSessionFactoryBean: tạo đối tượng sessionFactory.
    • Thuộc tính packagesToScan sẽ chỉ định package chứa các file entity map với table trong database (hoặc bạn cũng có thể chỉ rõ các class entity mapping với table bằng thuộc tính annotatedClasses)
    • Thuộc tính hibernateProperties khai báo file chưa các thông tin config hibernate (hoặc bạn cũng có thể chỉ rõ các thông tin config trong file spring config luôn)

 File Hibernate config:

hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.hibernate.current_session_context_class=thread
hibernate.show_sql=true

File entity:

package stackjava.com.springhibernate.entities;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "customer")
public class Customer {
  @Id
  @Column(name = "id")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;

  @Column(name = "name")
  private String name;

  @Column(name = "address")
  private String address;

  public Customer() {
  }

  public Customer(int id, String name, String address) {
    this.id = id;
    this.name = name;
    this.address = address;
  }

  public Customer(String name, String address) {
    this.name = name;
    this.address = address;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

}

File DAO:

package stackjava.com.springhibernate.dao;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import stackjava.com.springhibernate.entities.Customer;

@Repository(value = "customerDAO")
public class CustomerDAO {
  
  @Autowired
  private SessionFactory sessionFactory;

  public void save(Customer customer) {
    Session session = this.sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    session.persist(customer);
    tx.commit();
    session.close();
  }
  
  public void update(Customer customer) {
    Session session = this.sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    session.update(customer);
    tx.commit();
    session.close();
  }
  
  public List<Customer> findAll() {
    Session session = this.sessionFactory.openSession();
    List<Customer> result = session.createQuery("FROM Customer", Customer.class).getResultList();
    return result;
  }
  
  public Customer findById(int id) {
    Session session = this.sessionFactory.openSession();
    return session.find(Customer.class, id);
  }

  public void delete(Customer customer) {
    Session session = this.sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    session.delete(customer);
    tx.commit();
    session.close();
  }

}

Demo:

package stackjava.com.springhibernate.main;

import java.util.List;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import stackjava.com.springhibernate.dao.CustomerDAO;
import stackjava.com.springhibernate.entities.Customer;

public class MainApp {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    CustomerDAO customerDAO = (CustomerDAO) context.getBean("customerDAO");
    
    customerDAO.save(new Customer("Rooney", "Manchester"));
    customerDAO.save(new Customer("Gerrard", "Liverpool"));
    
    List<Customer> listCustomer = customerDAO.findAll();
    for (Customer customer : listCustomer) {
      System.out.println(customer.getId() + " - " + customer.getName() + " - " + customer.getAddress());
    }
//		
//		Customer customer = new Customer(1, "Gerrard", "Liverpool");
//		customerDAO.update(customer);
    context.close();
  }
}

Kết quả:

Spring Hibernate - Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

Spring Hibernate - Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

Okay, Done!

Phần tiếp theo chúng ta sẽ tìm hiểu và áp dụng AOP vào quản lý transaction với Spring Hibernate.

Download code ví dụ trên tại đây

Thanks all!

 

Spring Hibernate – Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

References:

https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html

https://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch14s02.html

4 thoughts on “Spring Hibernate – Giới thiệu Spring ORM, Code ví dụ Spring Hibernate

  • anh cho em hỏi: em thấy người ta hay tạo một lớp Dao implements từ interface dao, một lớp service implement từ một interface service, sau đó lớp service lại gọi tới các phương thức của lớp dao, tại sao không dụng controller gọi thẳng tới lớp Dao luôn ạ ?

    • Đúng rồi bạn, thường thì sẽ tạo interface dao và interface service để thực injection, ví dụ bạn có 2 class UserDAO1 (kết nối tới mysql) và UserDAO2 (postgre SQL) rồi bạn tạo 1 interface UserDAO để 2 thằng đó implement, khi sử dụng thì bạn sử dụng UserDAO để dễ dàng chuyển đổi sang 1 trong 2 thằng kia. (các ví dụ của mình không làm cái đó vì nó hơi dài và không cần thiết trong những trường hợp code không cần mở rộng)

      Việc chia riêng DAO và Service giúp tách nhỏ các chức năng để dùng lại, dễ phân tích nếu có lỗi…
      Ví dụ controller insert user, thì user service sẽ thực hiện check user tồn tại chưa, dữ liệu hợp lệ không. còn user dao sẽ thực hiện lấy user theo id (để check tồn tại chưa) và save user.
      Nếu bạn có method update user, delete user thì tạo service riêng cho nó và có thể sử dụng lại các dao đã tạo

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

DMCA.com Protection Status stackjava.com