良善又忠信的奴僕,你在不多的事上既是忠信的,我要把許多事派你管理;進來享受你主人的快樂。
在上面資料庫處理的程式編碼,如果我們仔細,會看到兩個重點
隱藏細節
,是物件導向的原則之一)。編程
(例如欄位對應),可共用
。上一個目的:像使用物件一樣操作資料庫,稱作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;