[Hibernate] Maven + (Spring + Hibernate) Annotation + MySql

Download – Spring-Hibernate-Annotation-Example.zip

Trong bài trước, chúng ta đã sử dụng Maven để tạo Java project đơn giản và sử dụng Hibernate trong Spring framework để thực hiện các thao tác (select, insert, update và delete) tại database MySQL. Trong bài này, ta sẽ biết thêm cách làm điều tương tự bằng annotation Spring và Hibernate.


Yêu cầu tiên quyết
– Cài đặt và cấu hình Maven, MySQL, Eclipse IDE.

Thư viện javaee.jar cần thiết hơn, có thể lấy nó từ j2ee SDK và include thủ công, đây không là phiên bản đầy đủ của javaee.jar đang có trong bất kỳ Maven repoitory nào.


Cấu trúc project sau cùng
Cấu trúc project cuối cùng như sau, nếu mất trong việc tạo cấu trúc thư mực, hãy xem bên dưới.
mavan-spring-hibernate-annotation-mysql.gif


1. Tạo table
Tạo table ‘stock’ trong database MySQL:

SQL:
CREATE TABLE  `mkyong`.`stock` (
  `STOCK_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `STOCK_CODE` varchar(10) NOT NULL,
  `STOCK_NAME` varchar(20) NOT NULL,
  PRIMARY KEY (`STOCK_ID`) USING BTREE,
  UNIQUE KEY `UNI_STOCK_NAME` (`STOCK_NAME`),
  UNIQUE KEY `UNI_STOCK_ID` (`STOCK_CODE`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;

2. Cấu trúc file trong project
Tạo nhanh cấu trúc file cho project bằng lệnh Maven ‘mvn archetype:generate‘, xem ví dụ tại đây. Convert project sang Eclipse project (mvn eclipse:eclipse) và import nó vào Eclipse IDE.

Code:
E:\workspace>mvn archetype:generate
[INFO] Scanning for projects...
...
Choose a number:
(1/2/3....) 15: : 15
...
Define value for groupId: : com.mkyong.common
Define value for artifactId: : HibernateExample
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.mkyong.common: : com.mkyong.common
[INFO] OldArchetype created in dir: E:\workspace\HibernateExample
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

3. Cấu hình trong file pom.xml
Thêm Spring, Hibernate, Annotation và MySQL và dependency của chúng trong file pom.xml của Maven.

XML:
<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mkyong.common</groupId>
  <artifactId>SpringExample</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>SpringExample</name>
  <url>http://maven.apache.org</url>

  <repositories>
    <repository>
      <id>JBoss repository</id>
      <url>http://repository.jboss.com/maven2/</url>
    </repository>
  </repositories>

  <dependencies>

        <!-- JUnit testing framework -->
        <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
        </dependency>

        <!-- Spring framework -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>2.5.6</version>
    </dependency>

        <!-- Spring AOP dependency -->
        <dependency>
                <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2</version>
    </dependency>

        <!-- MySQL database driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.9</version>
    </dependency>

    <!-- Hibernate framework -->
    <dependency>
        <groupId>hibernate</groupId>
        <artifactId>hibernate3</artifactId>
        <version>3.2.3.GA</version>
    </dependency>

    <!-- Hibernate annotation -->
    <dependency>
        <groupId>hibernate-annotations</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.3.0.GA</version>
    </dependency>

    <dependency>
        <groupId>hibernate-commons-annotations</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>3.0.0.GA</version>
    </dependency>

    <!-- Hibernate library dependecy start -->
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>

    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.1.1</version>
    </dependency>

    <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
    </dependency>

    <dependency>
        <groupId>antlr</groupId>
        <artifactId>antlr</artifactId>
        <version>2.7.7</version>
    </dependency>
    <!-- Hibernate library dependecy end -->

  </dependencies>
</project>
4. Model & BO & DAO
Model, Business Object (BO)Data Access Object (DAO) thường được sử dụng để xác định các tầng rõ ràng, tránh làm rối cấu trúc project.

Stock Model (Annotation)
Class model annatation Stock để lưu dữ liệu.

Java:
package com.mkyong.stock.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name = "stock", catalog = "mkyong", uniqueConstraints = {
        @UniqueConstraint(columnNames = "STOCK_NAME"),
        @UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {

    private Integer stockId;
    private String stockCode;
    private String stockName;

    public Stock() {
    }

    public Stock(String stockCode, String stockName) {
        this.stockCode = stockCode;
        this.stockName = stockName;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "STOCK_ID", unique = true, nullable = false)
    public Integer getStockId() {
        return this.stockId;
    }

    public void setStockId(Integer stockId) {
        this.stockId = stockId;
    }

    @Column(name = "STOCK_CODE", unique = true, nullable = false, length = 10)
    public String getStockCode() {
        return this.stockCode;
    }

    public void setStockCode(String stockCode) {
        this.stockCode = stockCode;
    }

    @Column(name = "STOCK_NAME", unique = true, nullable = false, length = 20)
    public String getStockName() {
        return this.stockName;
    }

    public void setStockName(String stockName) {
        this.stockName = stockName;
    }

    @Override
    public String toString() {
        return "Stock [stockCode=" + stockCode + ", stockId=" + stockId
                + ", stockName=" + stockName + "]";
    }
}
Stock Business Object (BO))
Interface và implement của business object (BO) Stock, sử dụng để khai báo hàm xử lý nghiệp vụ, các hoạt động tại database (CRUD) không được xử lý tại đây, thay vào đó, có class DAO (StockDao) để làm việc đó.

Java:
package com.mkyong.stock.bo;

import com.mkyong.stock.model.Stock;

public interface StockBo {

    void save(Stock stock);
    void update(Stock stock);
    void delete(Stock stock);
    Stock findByStockCode(String stockCode);
}
Cho class này làm bean “stockBo” trong Spring Ioc container và autowire class stock dao.

Java:
package com.mkyong.stock.bo.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mkyong.stock.bo.StockBo;
import com.mkyong.stock.dao.StockDao;
import com.mkyong.stock.model.Stock;

@Service("stockBo")
public class StockBoImpl implements StockBo{

    @Autowired
    StockDao stockDao;

    public void setStockDao(StockDao stockDao) {
        this.stockDao = stockDao;
    }

    public void save(Stock stock){
        stockDao.save(stock);
    }

    public void update(Stock stock){
        stockDao.update(stock);
    }

    public void delete(Stock stock){
        stockDao.delete(stock);
    }

    public Stock findByStockCode(String stockCode){
        return stockDao.findByStockCode(stockCode);
    }
}
Stock Data Access Object
Interface và implement của Stock DAO. Trong bài trước, class DAO implement được extends “HibernateDaoSupport”, nhưng không thể làm vậy khi sử dụng annotation vì không thể autowire bean seesion Factory cho class Dao. Cách giải quyết là tạo class custom (CustomHibernateDaoSupport) và extends “HibernateDaoSupport” và autowire session factory, và class DAO sẽ extends class này.

Java:
package com.mkyong.stock.dao;

import com.mkyong.stock.model.Stock;

public interface StockDao {

    void save(Stock stock);
    void update(Stock stock);
    void delete(Stock stock);
    Stock findByStockCode(String stockCode);

}
Java:
package com.mkyong.util;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class CustomHibernateDaoSupport extends HibernateDaoSupport
{
    @Autowired
    public void anyMethodName(SessionFactory sessionFactory)
    {
        setSessionFactory(sessionFactory);
    }
}
Java:
package com.mkyong.stock.dao.impl;

import java.util.List;

import org.springframework.stereotype.Repository;

import com.mkyong.stock.dao.StockDao;
import com.mkyong.stock.model.Stock;
import com.mkyong.util.CustomHibernateDaoSupport;

@Repository("stockDao")
public class StockDaoImpl extends CustomHibernateDaoSupport implements StockDao{

    public void save(Stock stock){
        getHibernateTemplate().save(stock);
    }

    public void update(Stock stock){
        getHibernateTemplate().update(stock);
    }

    public void delete(Stock stock){
        getHibernateTemplate().delete(stock);
    }

    public Stock findByStockCode(String stockCode){
        List list = getHibernateTemplate().find(
                     "from Stock where stockCode=?",stockCode
                );
        return (Stock)list.get(0);
    }

}

5. Cấu hình resource
Tạo thư mục 'resources' trong 'project_name/main/java', Maven sẽ xem tất cả file trong thư mục này là file resource. Nó sẽ được sử dụng để lưu trữ Spring, Hibernate và file cấu hình khác.

Cấu hình Spring
Liên quan đến Database...

Tạo file properties (database.properties) để cấu hình kết nối database, cho nó vào thư mục “resources/properties”. Việc này để tách biệt cấu hình kết nối database và cấu hình Spring Bean trong những file khác nhau.

database.properties
Code:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mkyong
jdbc.username=root
jdbc.password=password
Tạo bean “dataSource” (DataSource.xml) để cấu hình database và import properties trong database.properties, cho nó vào thư mục “resources/database”.

DataSource.xml
XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>properties/database.properties</value>
    </property>
</bean>

<bean id="dataSource"
         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

</beans>
Liên quan đến Hibernate….

Tạo file cấu hình bean session factory (Hibernate.xml), bỏ nó vào thư mục “resources/database”. Với annotation cần sử dụng AnnotationSessionFactoryBean và chỉ định các class model annotation trong property ‘annotatedClasses‘ nằm bên trong property ‘mappingResources'.

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

<!-- Hibernate session factory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

    <property name="dataSource">
      <ref bean="dataSource"/>
    </property>

    <property name="hibernateProperties">
       <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
         <prop key="hibernate.show_sql">true</prop>
       </props>
    </property>

    <property name="annotatedClasses">
    <list>
        <value>com.mkyong.stock.model.Stock</value>
    </list>
    </property>

    </bean>
</beans>
Import tất cả file cấu hình bean của Spring vào 1 file duy nhất (BeanLocations.xml) và cho nó vào thư mục “resources/config”.

BeanLocations.xml
Import cấu hình database Spring và enable tính năng scan tự động của Spring.

XML:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

    <!-- Database Configuration -->
    <import resource="../database/DataSource.xml"/>
    <import resource="../database/Hibernate.xml"/>

    <!-- Auto scan the components -->
    <context:component-scan
        base-package="com.mkyong.stock" />

</beans>
6. Chạy ứng dụng
Đã có tất cả các file và cấu hình, bây giờ hãy chạy nó.

Java:
package com.mkyong.common;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.mkyong.stock.bo.StockBo;
import com.mkyong.stock.model.Stock;

public class App
{
    public static void main( String[] args )
    {
        ApplicationContext appContext =
          new ClassPathXmlApplicationContext("spring/config/BeanLocations.xml");

        StockBo stockBo = (StockBo)appContext.getBean("stockBo");

        /** insert **/
        Stock stock = new Stock();
        stock.setStockCode("7668");
        stock.setStockName("HAIO");
        stockBo.save(stock);

        /** select **/
        Stock stock2 = stockBo.findByStockCode("7668");
        System.out.println(stock2);

        /** update **/
        stock2.setStockName("HAIO-1");
        stockBo.update(stock2);

        /** delete **/
        stockBo.delete(stock2);

        System.out.println("Done");
    }
}
Kết quả
Code:
Hibernate: insert into mkyong.stock (STOCK_CODE, STOCK_NAME) values (?, ?)
Hibernate: select stock0_.STOCK_ID as STOCK1_0_,
stock0_.STOCK_CODE as STOCK2_0_, stock0_.STOCK_NAME as STOCK3_0_
from mkyong.stock stock0_ where stock0_.STOCK_CODE=?
Stock [stockCode=7668, stockId=11, stockName=HAIO]
Hibernate: update mkyong.stock set STOCK_CODE=?, STOCK_NAME=? where STOCK_ID=?
Hibernate: delete from mkyong.stock where STOCK_ID=?
Done

Kết luận
Tất cả các class cấu hình và file liên quan đến Spring, Hibernate đều có thử sử dụng annotation, chỉ để lại cấu hình database trong file XML. Nếu biết cách sử dụng annotation cho cấu hình database, hãy cho tôi biết nhé. Cá nhân, tôi không sử dụng tính năng annotation nhiều, bởi vì bằng cách nào đó có thể cần một số cách giải quyết cho một số tình huống nhất định, như ‘CustomHibernateDaoSupport, extends HibernateDaoSupport, ở trên. File XML đã phát triển hoàn thiện trong Spring và Hibernate và nó là tốt hơn.


Cám ơn các bạn đã theo dõi. Hẹn gặp lại các bạn trong các bài viết sau :D

Bài viết tham khảo tại: https://mkyong.com/spring/maven-spring-hibernate-annotation-mysql-example/
 

Bình luận