iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 26
2
Modern Web

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

瑪麗亞女士 (MariaDB)

  • 分享至 

  • xImage
  •  
MariaDB Server is one of the most popular database servers in the world. It’s made by the original developers of MySQL and guaranteed to stay open source. Notable users include Wikipedia, WordPress.com and Google. (from https://mariadb.org/about/)
  • User.java
  • UserRepository.java
  • (UserMapper.java) -> 可以省略,直接寫在 UserService.java, 呼叫函數之內。
  • (UserService.java) -> 可以省略,直接由 UserController.java 呼叫資料庫(Dao)處理 。
  • UserController.java -> 路由控制。
  • SpringMariaDbApplication.java -> 主程式,自動生成,沒有改動。
  • @Autowired
  • Lambda expression

上一回中,我們介紹了資料庫的安裝與創建以及JDBC的連接。記得要啟動資料庫,在 MAC OS 是

mysql.server start

在 Windows 時,必須執行 services.msc (或是透過畫面點選,看服務是否被啟動)。
在這一回中,我們介紹其他的編碼,因為是資料庫的處理,影響所及,也是在相關的類別 UserRepository.java 變動比較大,類別成員 JdbcTemplate 提供連結資料庫及相關處理,在其宣告類別資料成員的上面一行的 @Autowired 表明其定義在其他地方,也可能不在我們的套件(package)之內 (若不在本套件之內,就必須透過 import 載入其他套件)。

    @Autowired
    private JdbcTemplate jdbcTemplate;

當然,SQL指令扮演重要的角色,SQL相關的內容可能值得一門課。在這裡我們用了 JdbcTemplate 中的 update() 及 query() 函式。

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class UserRepository {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	final private String USERS="users";
	public void userAdd(User user) {
		String sql_format=String.format("insert into %s(name,email) value(?,?)",USERS);
		jdbcTemplate.update(sql_format,user.getName(),user.getEmail());
	}	
	public List<User> findAll() {
		String sql=String.format("select id,name,email from %s", USERS);
		List<User> users = jdbcTemplate.query(sql, new UserRowMapper());
		return users;
		
	}
}

其中userAdd() 函數,sql_format 字串中的問號(?)對應jdbcTemplate.update()中的參數,update()函式中,第一個參數是 SQL指令,後面的參數逐一對應 SQL 指令中的問號。

sql_format=String.format("insert into %s(name,email) value(?,?)",USERS)
jdbcTemplate.update(sql_format,user.getName(),user.getEmail());
    sql_format -> SQL command
    user.getName() -> first question mark (?)
    user.getEmail() -> second question mark (?)

而在 query() 函式(用於 findAll() 內),必須提供欄位的對應,可以是一個欄位對應的類別。

package com.example.demo;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;

public class UserRowMapper implements RowMapper<User> {
	public User mapRow(ResultSet rs, int rowNum) throws SQLException {
		User user = new User();
		user.setId(new Integer(rs.getInt("id")));
		user.setName(rs.getString("name"));
		user.setEmail(rs.getString("email"));
		return user;
	}
}

query() 函式還有另外一個簡化的編程 (直接把 Mapper 放在 findAll 函數之內,用 Lambda 表示式...哇,又是一個新朋友,簡單地說,就是將函式當作參數,傳來傳去),其優缺點讀者可以省思,例如,相同的 Mapper 被一個以上的函數使用?當欄位很多時,程式的閱讀性?維護/修改的方便性?有的時候,也沒有標準答案,見仁見智,不過同一個應用,同一個團隊,建議是統一風格。完成之編碼如下:

public List<User> findAll() {
	String sql=String.format("select id,name,email from %s", USERS);
	return jdbcTemplate.query(sql, 
        (rs, rowNum) -> new User(rs.getString("name"),rs.getString("email")));	       
	}

在這裡我們多夾了層 service, Controller 呼叫 Service,再由 Service 呼叫 Repository,這是一個習慣,增加程式的靈活度,但也可以直接由 Controller 直接呼叫 Repository, 跳過 Service。

package com.example.demo;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {
	@Autowired
	UserRepository userDao;
	public void userAdd(User user) {
		userDao.userAdd(user);
	}
	public List<User> findAll() {
		return userDao.findAll();
	}
}

路由程式/控制器 UserController也配合作一些修改

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

	@Autowired
	private UserService userService;

	@GetMapping("/users")
	public String getUsers() {
		StringBuilder result = new StringBuilder("<h2>User List</h2>");
		List<User> users = userService.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) {
		User user = new User(name, email);
		userService.userAdd(user);
		return user.toString();
	}
}

執行結果如下:
https://ithelp.ithome.com.tw/upload/images/20191011/20120951UZ1UTvSWro.png

現在,資料是存在數據庫/資料庫,可以透過其他的工具(如 Tableplus)看到資料的內容,關機後,下回再使用,或是其他的電腦也可以讀取相同的資料。資料己經 "永久" 地被保存下來。


上一篇
心領神會 (JDBC)
下一篇
良善忠信的僕人 (JPA/Hibernate)
系列文
美麗的邂逅-與安室....伊春30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言