Spring 三: 数据持久化
情景带入
假设你是一个话费公司, 负责充值话费, 那么你需要的一个 Domain 就是话费订单, 定义如下:
Order.java
package edu.ouc.wch.learn.demo;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.PrePersist;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@Entity
@Data
@NoArgsConstructor
@Table(name="orders")
public class Order {
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
private int id;
private String phoneNumber;
private int amount;
private Date date;
@PrePersist
void date() {
this.date = new Date();
}
}
其中 @Entity 注解表明该类将对应数据库中的一个表, 表名由 @Table注解确定.
@GeneratedValue 注解可以起到 mysql 中 autu_increment 的作用
而 @PrePersist 注解则表示该函数会在存入数据库之前调用
Repository
过去在用 java 写数据库逻辑时, 往往是由 DAO 对象来对数据库进行交互, 而 Spring 中该工作交给了 Repository, 个人感觉只是换了个名字而已.
Spring 中我最喜欢的一个功能就是它高度抽象了数据库相关的操作, 将你需要写的代码量几乎缩减到了零. ( 在过去我常常苦于写这些千篇一律的数据库交互代码, 没想到 Spring 竟然完全将其抽象了 )
OrderRepository.java
package edu.ouc.wch.learn.demo;
import org.springframework.data.repository.CrudRepository;
public interface OrderRepository extends CrudRepository<Order, Integer>{}
由上可见, 毫不夸张地说你完全不用写一行代码即可完成对数据库交互的逻辑. 其中 CrudRepositry 中 Crud 表示的是英文的"增删查改", 继承该接口后将会拥有一些最基础的如 findAll() 等方法.
如果你想增加其他数据库的交互逻辑, 你只需要添加一个方法名即可.
CrudRepository基于你的方法名来自动实现你所想要的功能, 比如你想通过电话号码来删除记录, 你只需要添加如下方法声明:
public void deleteAllByPhoneNumber(String phoneNumber);
这就是Spring给你带来的实实在在的便利.
Controller
Controller 的逻辑十分简单, 不再赘述
HomeController.java
package edu.ouc.wch.learn.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.ui.Model;
import edu.ouc.wch.learn.demo.Order;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import edu.ouc.wch.learn.demo.OrderRepository;
@Controller
@RequestMapping("/")
public class HomeController {
private final OrderRepository orderRepo;
@Autowired
public HomeController(OrderRepository orderRepo) {
this.orderRepo = orderRepo;
}
@GetMapping
public String home(Model model) {
Iterable<Order> orders = orderRepo.findAll();
Order order = new Order();
model.addAttribute("orders", orders);
model.addAttribute("newOrder", order);
return "home";
}
@PostMapping
public String process(Model model, Order order) {
orderRepo.save(order);
return "redirect:/";
}
}
View
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
<h1>This is home!</h1>
<form method="post" th:object="${newOrder}">
<input type="text" th:field="*{phoneNumber}" />
<input type="number" th:field="*{amount}" />
<input type="submit" value="submit">
</form>
<ul>
<li th:each="o : ${orders}"><span th:text="${o.id}+' - '"/><span th:text="${o.phoneNumber}+' : '"/><span th:text="'$'+${o.amount}"/></li>
</ul>
</body>
</html>