Spring-boot : รวมคำสั่ง Hibernate เบื้องต้น และนำไปใช้งานร่วมกับ Spring Boot

บทความนี้จะรวมคำสั่ง Hibernate เบื้อต้น ที่จำเป็นในการใช้งาน และนำไปประยุกต์ใช้งานกับ Spring Boot

โดยใช้ library spring-boot-starter-data-jpa และใช้ thymeleaf มาช่วยในการจัดการหน้า Web view

ก่อนอื่นเรามารู้จักกับ hinernate กันก่อนครับ ผมขอยืมคำพูดมาจากเว็บ programminghunter

Hibernate คืออะไร

Hibernate เป็น Framework Javaใช้ในการจัดการข้อมูลแบบ ORM (Object/Relation Mapping คือการ mapping Java Object กับ ข้อมูลจากฐานข้อมูลแบบอัตโนมัติกลับไปกลับมาได้)
เพื่อความสะดวกในการทำงานต่างๆ เช่น การเข้าถึงข้อมูล การเรียกค้นข้อมูล ซึ่งจะช่วยให้เราทำงานได้อย่างมีประสิทธิภาพ นอกจากนี้แล้ว Hibernate ยังเป็นโอเพ่นซอร์สอีกด้วย จึงสามารถดาวน์โหลดมาใช้งานกันได้ฟรีๆไม่มีค่าใช้จ่ายใดๆทั้งสิ้น

เรามาเริ่มกันเลยดีกว่า

โครงสร้าง Project มีดังนี้ image title

โครงสร้าง Database มีดังนี้

image title

โดย Scherma มีชื่อว่า springboot
และ Table มีชื่อว่า users

ก่อนอื่นให้มาทำการ เพิ่ม library ในไฟล์ pom.xml ก่อนครับ
pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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>com.SpringDataJPAandHibernate</groupId>
	<artifactId>SpringDataJPAandHibernate</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<name>SpringDataJPAandHibernate</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.3.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
	

</project>

application.properties

server.port=80

spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=toor

spring.datasource.test-while-idle=true
spring.datasource.validationQuery = SELECT 1

spring.jpa.show-sql = true

spring.jpa.hibernate.ddl-auto=update

spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy

spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5Dialect

โดยผมจะให้ server ทำงานใน port 80 และให้ทำการเชื่อมต่อกับ mysql ผ่าน jdbc โดยมี Schema ชื่อว่า springboot
บรรทัดที่ 4 username ของ database เรา
บรรทัดที่ 5 password ของ database เรา

ServletInitializer.java

package com.SpringDataJPAandHibernate;

import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

public class ServletInitializer extends SpringBootServletInitializer {

	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
		return application.sources(SpringDataJpAandHibernateApplication.class);
	}

}

SpringDataJpAandHibernateApplication.java

package com.SpringDataJPAandHibernate;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringDataJpAandHibernateApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringDataJpAandHibernateApplication.class, args);
	}
}

UserControllers.java

package com.SpringDataJPAandHibernate.Coontrollers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.SpringDataJPAandHibernate.Users.UserDao;
import com.SpringDataJPAandHibernate.Users.Users;

@Controller
public class UserControllers {
	@RequestMapping(value="/add",method=RequestMethod.GET)
	public String Agenda(Model model){
		model.addAttribute("Users", new Users());
		return "Users";
	}
		
	
	@Autowired
	private UserDao usersDao; 
	
	@RequestMapping("/create")
	@ResponseBody
	public String create(String email,String name){
		Users users = null;
		try {
			users = new Users(email, name);
			usersDao.save(users);
		} catch (Exception ex) {
			return "Error creating the user: "+ex.toString();
		}
		return "User successfully created! (id =" +users.getId()+")";
	}
	
	
	  @RequestMapping("/delete")
	  @ResponseBody
	  public String delete(long id) {
	    try {
	    	Users user = new Users(id);
	    	usersDao.delete(user);
	    }
	    catch (Exception ex) {
	      return "Error deleting the user:" + ex.toString();
	    }
	    return "User succesfully deleted!";
	  }
	  
	  @RequestMapping("/get-by-email")
	  @ResponseBody
	  public String getByEmail(String email) {
	    String userId;
	    try {
	    	Users user = usersDao.findByEmail(email);
	      userId = String.valueOf(user.getId())+"<br /> Email:"+user.getEmail()+"<br/> toString:"+user.toString();
	    }
	    catch (Exception ex) {
	      return "User not found";
	    }
	    return "The user id is: " + userId;
	  }
	  
	  @RequestMapping("/update")
	  @ResponseBody
	  public String updateUser(long id, String email, String name) {
	    try {
	      Users user = usersDao.findOne(id);
	      user.setEmail(email);
	      user.setName(name);
	      usersDao.save(user);
	    }
	    catch (Exception ex) {
	      return "Error updating the user: " + ex.toString();
	    }
	    return "User succesfully updated!";
	  }

	  @RequestMapping("/")
	  @ResponseBody
		private Iterable<Users> add(){
			return usersDao.findAll();
		}
}

คำสั่ง
บรรทัดที่ 31 .save(users); ใช้แทนคำสั่ง sql -> INSERT INTO table_name VALUES (value1,value2,value3,...);
บรรทัดที่ 44 .delete(user); ใช้แทนคำสั่ง sql -> DELETE FROM table_name WHERE some_column=some_value;
บรรทัดที่ 57 Users user = usersDao.findByEmail(email); ใช้แทนคำสั่ง sql -> SELECT * FROM users WHERE email=?;
บรรทัดที่ 58 userId = String.valueOf(user.getId())+"
Email:"+user.getEmail()+"
toString:"+user.toString(); //โดยจะให้แสดงข้อมูลอะไรบ้างจาก Columnsนั้น
บรรทัดที่ 70-73 ใช้แทนคำสั่ง sql -> UPDATE table_name SET column1=value1,column2=value2,... WHERE some_column=some_value;
บรรทัดที่ 84 .findAll(); ใช้แทนคำสั่ง sql -> SELECT * FROM users

UserDao.java

package com.SpringDataJPAandHibernate.Users;

import javax.transaction.Transactional;

import org.springframework.data.repository.CrudRepository;



@Transactional
public interface UserDao extends CrudRepository<Users, Long> {
	public Users findByEmail(String email);
}

Users.java

package com.SpringDataJPAandHibernate.Users;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;

@Entity
@Table(name="users")
public class Users {
	@Id @GeneratedValue(strategy = GenerationType.AUTO)
	private long id;
	
	@NotNull
	private String email;
	
	@NotNull
	private String name;

	public long getId() {
		return id;
	}

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

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Users [id=" + id + ", email=" + email + ", name=" + name + "]";
	}

	public Users(long id) {
		super();
		this.id = id;
	}

	public Users(String email, String name) {
		super();
		this.email = email;
		this.name = name;
	}

	public Users() {
		super();
	}
}

@Table(name="users") คือ บอกว่าเราใช้ table ชื่อว่า users
@Id คือ บอกว่าจะใช้ ตัวแปรด้านล่างนี้เป็น PK
@GeneratedValue(strategy = GenerationType.AUTO) คือให้เป็น Auto Increment โดยจะรันเองแบบ Auto ไม่ต้องให้เรากรอก
ควรตั้งให้สอดคล้องกับ Database เรานะครับ และควรเป็นคุณสมบัติตัวเลข
private long id; คือ ตัวแปรชนิด long โดยมีชื่อว่า id และรับคุณสมบัติจากด้านบน

ส่วนที่ 2 จะเป็นส่วนของ templates ครับ เป็นส่วนของ view ที่จะรับข้อมูลจาก user

image title

Users.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Getting Started: Handling Form Submission</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
	<h1>Register</h1>
    <form action="/create" th:action="@{/create}" th:object="${Users}" method="post">
    	<p>Email : <input type="email" th:field="*{email}" /></p>
        <p>Name: <input type="text" th:field="*{name}" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>
</body>
</html>

แค่นี้ก็เสร็จเรียบร้อยแล้วนะครับ

ทดสอบด้วยการรัน และเข้าหน้าเว็บ http://127.0.0.1/add

image title

จากนนั้นกด Submit image title จะสังเกตุว่า id จะถูก รันขึ้นมา Auto โดยที่ user ไม่ต้องกรอกเอง เพื่อป้องกันการซ้ำของข้อมูล

Database image title


### การใช้งานต่าง ๆ
http://127.0.0.1/
/create?email=[email]&name=[name] //สร้าง user
/delete?id=[id] // ลบuser โดยผ่าน id
/get-by-email?email=[email] // เรียกดู user โดยผ่าน email
/update?id=[id]&email=[email]&name=[name] //แก้ไข user โดยผ่าน id และ email หรือ name ที่ต้องการแก้ไข
![image title](https://s3-ap-southeast-1.amazonaws.com/codesanook-static/uploaded/2016/4/9/1460174663757-7.jpg?t=1460174667259)

หวังว่าเพื่อน ๆจะได้ความรู้ไม่มากก็น้อยนะครับสำหรับบทความนี้ ถ้าสงสัยตรงไหน คอมเมนท์ถามกันได้นะครับ ทาง codesanook.com ยินดีให้คำปรึกษาครับ

ผิดพลาดประการใดขออภัยด้วยนะครับ ยินดีรับคำติชม