Spring Boot QuickStart (4) - Database

环境:Spring Boot 1.5.4

本文只是引子,后续会持续更新。

到了操作数据库的环节,以 MySQL 为基准,体验一下数据库的相关操作,先让我纠结一下,至少有以下四种姿势。

  • JDBC。原生的 JDBC 操作,原生的 SQL语句,写一大堆的初始化、代码、异常捕获。
  • JDBCTemplate。Spring 对 JDBC 的封装,基本上还是原生的 SQL 语句,操作方法要自己写,少了很多(他们叫样板式)代码。
  • JPA。内置了一些接口,封装了常规的 CURD、分页操作,借助 Spring Data Jpa,能帮你自动实现大部分的单表操作,你要做的仅仅是定义实体,按照规范定义接口即可。
  • MyBatis。一个 Java 当前很流行的 ORM 框架,如果你以前是写 PHP 的,我猜你不太敢相信它是 ORM 框架。

JPA、MyBatis 将是学习重点。尤其是 MyBatis,这也是现在号称流行的 SSM 组合。(Spring + Spring MVC + MyBatis)?幸亏 Structs、Hibernate 现在看起来不主流了。

体验的基线:

  • 单表。增、删、改、查(多条件组合查询、分页,排序等)
  • 多表关联。一对一,一对多,多对多

lombok

Java 是强类型的,所以经常要定义实体,或domain,或dao,或dto。

而每个类写上构造函数,Getter、Setter、toString,实在是蛋疼。虽然 PHPStorm 提供了快捷键可以快速生成(CTRL+N),但当你要修改属性、属性类型的时候,还是需要手动搞一下的。

所以我发现了 lombok 这个项目,通过一定的注解,配合 PHPStorm 插件,可以消除以上那些常规代码。

甚至,还可以通过 builder() 模式,消除重复的 .setXXX() 语句

官网地址:https://projectlombok.org/

数据库结构

先意淫几张表,通过这几张表,期望能够覆盖常规的需求,其包含了各种类型的的字段,以及多种表关系。

user (id, role_id, xx)
user_detail (id, user_id, xx)
role (id, xx)
order (id, user_id, xx)
product (id, xx)
order_product (order_id, product_id)

关系如下:
user<->user_detail 一对一
user->role 一对一(假设一个用户只有一个角色)
role->user 一对多
user->order 一对多
order->user 多对一
order<->product 多对多

同时在 application.properties 中配置 datasource 数据源相关配置,这里使用 MySQL

spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123123
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

字段映射

Java 与 MySQL 类型映射,可以参考

但,我目前还很困惑的是时间相关的几个类型,在 MySQL 中,有以下几个:

DATE
TIME
DATETIME
TIMESTAMP

其中,TIMESTAMP、TIME 貌似只能对应 java.sql.Timestamp 与 java.sql.Time

那么 DATE、DATETIME 呢?首先对应 java.sql.Date 与 java.sql.Timestamp 肯定是可以的。

能对应 java.util.Date 吗?

能对应 java.time.LocalDate、java.time.LocalDateTime 吗?

应当如何选择?标准姿势是什么?

参考:
https://stackoverflow.com/questions/2305973/java-util-date-vs-java-sql-date

SQL

DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `name` varchar(64) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='订单';

INSERT INTO `order` VALUES ('1', '1', '订单一'), ('2', '1', '订单二'), ('3', '1', '订单三'), ('4', '2', '订单四'), ('5', '2', '订单五');

DROP TABLE IF EXISTS `order_product`;
CREATE TABLE `order_product` (
  `order_id` int(10) unsigned NOT NULL,
  `product_id` int(10) unsigned NOT NULL,
  PRIMARY KEY (`order_id`,`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单产品关联表';

INSERT INTO `order_product` VALUES ('1', '1'), ('1', '2'), ('1', '3'), ('2', '2'), ('2', '3');

DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `price` double(10,2) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='产品';

INSERT INTO `product` VALUES ('1', '大白菜', '1.23'), ('2', '土豆', '2.45'), ('3', '西红柿', '3.78'), ('4', '芹菜', '2.08'), ('5', '鸡蛋', '0.51');

DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='角色';

INSERT INTO `role` VALUES ('1', '管理员'), ('2', '总编'), ('3', '编辑');

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `role_id` tinyint(3) unsigned NOT NULL COMMENT '角色ID',
  `username` varchar(32) NOT NULL COMMENT 'Email用户名,唯一',
  `password` varchar(32) NOT NULL COMMENT '密码',
  `salt` varchar(6) NOT NULL COMMENT '盐',
  `name` varchar(32) NOT NULL COMMENT '姓名',
  `birthday` date DEFAULT NULL COMMENT '生日',
  `sex` enum('male','female') NOT NULL COMMENT '性别',
  `access` datetime DEFAULT NULL COMMENT 'datetime类型',
  `access_time` time DEFAULT NULL COMMENT 'time类型',
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
  `state` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '状态',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='用户';

INSERT INTO `user` VALUES ('1', '1', 'a@a.com', '6f5275a26b06ee3bdf4fb1d2ca89577c', 'wnyk0a', '雷小军', '1970-08-08', 'male', '1987-09-08 01:02:03', '01:02:03', '2017-07-01 09:36:23', '2017-07-01 17:29:06', '1'), ('2', '2', 'b@b.com', '3206c77753829fc30fffa37881a63341', 'xxmao1', '董明珠', '1960-05-05', 'female', '1987-09-08 01:02:03', '01:02:03', '2017-07-01 09:36:50', '2017-07-01 17:28:42', '1');

DROP TABLE IF EXISTS `user_detail`;
CREATE TABLE `user_detail` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `user_id` int(10) unsigned NOT NULL,
  `address` varchar(32) NOT NULL DEFAULT '' COMMENT '地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='用户详情';


INSERT INTO `user_detail` VALUES ('1', '1', '北京'), ('2', '2', '广州');