iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 27
1
Modern Web

美麗的邂逅-與安室....伊春系列 第 27

良善忠信的僕人 (JPA/Hibernate)

  • 分享至 

  • xImage
  •  
良善又忠信的奴僕,你在不多的事上既是忠信的,我要把許多事派你管理;進來享受你主人的快樂。
  • JPA = Java Persistence API
  • ORM = Object Relational Mapping
  • DAO = Data Access Object
  • ORM = Object Relational Mapping
  • CRUD = Create, Retrieve, Update, Delete
  • DDL=Data Definition Language
  • @Column
  • JpaRepository

在上面資料庫處理的程式編碼,如果我們仔細,會看到兩個重點

  1. 像使用物件一樣存取資料庫(而不是用SQL) (隱藏細節,是物件導向的原則之一)。
  2. 在CRUD 的應用中,有許多是雷同的編程(例如欄位對應),可共用

上一個目的:像使用物件一樣操作資料庫,稱作ORM(Object Relational Mapping),資料庫是為了長久保存資料(不是關機或停用程式就不見了),Java 實作ORM實際制定的界面稱作 JPA (Java Persistence API)。即然是界面,那就有一個界接的實體(界面就像一道門,打開門,進去該有一間屋子,或是,另外一個世界),在Java 中常用的是 Hibernate, 下一回中會介紹 MyBatis, 這是ORM的另一個解決方案。因此我們可以說,要達成ORM有許多技術方案,JPA,Batis是其中兩個,要提供JPA實作,也有許多技術方案,Hibernate是其中最著名的一個,還有其他很多的實作可以選用。原理都類似的。在IT的領域,解決同一個問題,都有不同的選擇,各人頂著一片天,各取所好。不管黑貓白貓,會抓老鼠的貓就是好貓。
首先在 Dependencies,有一些是衝突的,在 JDBC 時,我們選用(設定於 pom.xml - Maven)

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>

現在(JPA),我們改用

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

可以在創建時,DEPENDENCIES中前者(JDBC)選擇 data > jdbc, 而後者(JPA)選擇 data > jpa。同時在 application.properties 中還要增加兩行,設定Hibernate

spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update

其中 database-platform 與所使用的 MariaDB 或是 MySQL 版本有關,設錯了,也不是不能用,但可能什麼環節會怪怪的。ddl-auto 有none (預設)/ create / create-drop / update / validate / create-only / drop ,create 代表每次加載 hibernate 時會刪除舊表,(根據 model)創建新表, create-drop 則除了 create 外,在結束 (sessionFactory 關閉) 時會刪除表格,update 是第一次運行時會建立新表,若model 改變時,表格會重新建立,但資料保留;餘類推。
在這一回的範例中,我們將 Service 省略了,直接從 Controller 呼收 Repository,
IUserRepository.java

@Repository
public interface IUserRepository extends JpaRepository<User,Long>  {
	List<User> findAll();
}

(界面名稱,我們加個 "I",這是在C++中養成的習慣,JAVA同好,有許多並沒有這個習慣)。在Spring Boot 中,我們不必定義函式邏輯,只要定義界面,是不是簡單許多?只剩下三行,而且這只是 “界面”,裡面可以使用的函式,系統全部都自動完成,當然,函式的名稱是固定的。要查看有那些函式,網上有許多訊息,這裡就連結一個供參考
最後路由控制器(UserController)的編程列之如下供參考:

@RestController
public class UserController {

	@Autowired
	IUserRepository userDao;

	@GetMapping("/users")
	public String getUsers() {
		StringBuilder result = new StringBuilder("<h2>User List</h2>");
		List<User> users = userDao.findAll();
		if (users != null && !users.isEmpty()) {
			for (User user : users) {
				result.append("<p>" + user.toString() + "</p>");
			}
		} else {
			result.append("<p>There is no user.</p>");
		}

		return result.toString();
	}

	@GetMapping("/new/{name}/{email}")
	String addUser(@PathVariable String name, @PathVariable String email) {
		StringBuilder result = new StringBuilder("<h2>User Add</h2>");
		User user = new User(name, email);
		userDao.save(user);
		result.append("<p>" + user.toString() + "</p>");
		return result.toString();
	}
}

是不是又更簡單了,SQL指令沒有了,欄位對應Mapper也沒有了。其實欄位定義是定義在Model中(User.java), 透過 @Column 建立資料庫欄位(database field)與類別成員(class member)之間的對應關係。

	  @Id
      @GeneratedValue(strategy = IDENTITY)
	  @Column(name="ID")
      private long id;
    
      @Column(name="NAME")
	  private String name;
    
      @Column(name="EMAIL")
      private String email;

當資料庫欄位名稱與類別中的資料成員相同(如範例)時,亦可以省略成 @Column,或乾脆連 @Column 整行都省略也行。就這樣,成了,一切盡在不言中。

	@Id
    @GeneratedValue(strategy = IDENTITY)
    private long id;
	private String name;
    private String email;

上一篇
瑪麗亞女士 (MariaDB)
下一篇
管教 (MyBatis)
系列文
美麗的邂逅-與安室....伊春30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言