MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
世界上最昂贵的东西是“免费”。
为了降低项目成本,我们有一套完整的 MySQL 开源社区版集群。希望能在低成本的基础上,带来期望的收益。
然而,经过不停的填坑操作告诉我们一个道理。
“免费” === 无人维护,商业运用还是 Oracle 关系型数据库来的香。
01 背景
这里是凭爱发电的开源项目 oPos。
考虑到将来还要自己全栈做 dev-ops,为了不给自己挖太深的坑。本项目的数据库存储采用以下技术选型:
本文的主要作用是记录 MySQL 安装与 JPA 的建表操作过程。为以后的技术复盘、运维做准备。
PS.欢迎大家 star: https://github.com/FoamValue/oPos.git
02 Docker 安装
Docker 是个好工具。
它是一个开源的虚拟应用容器引擎。随着云计算、AI、大数据等技术浪潮下,可以自动化部署、运维成千上万台服务器的 Docker 容器与虚拟技术,成为一件新的技术“神器”。
个人使用非常简单,直接下载安装程序即可。
03 Docker 安装 MySQL
首先,我们使用 search 命令来感受下 Docker 的强大。
罗列了所有 MySQL 的版本,再也没有寻找安装包该在哪里下载的痛苦了。
商业项目建议使用相对稳定的老版本,例如 5.6、5.7。
但,既然是开源项目。那就勇猛直前的最新 latest 版本就好。顺便还能感受下新的版本特性。
下载完成之后,可以使用 images 命令查看本地的镜像版本。例如:mysql latest,zookeeper 3.4.14。
目前,还没有部署测试环境的概念。
所以,现在选用“不建立映射目录”的方式运行。也就是,存储数据会丢失。
使用 Navicat 配置 MySQL 的访问方式。
创建一个 utf8 编码格式的数据库 oPos。
到这里,一个名叫 oPos 的关系型数据库就创建好了。
04 JPA 配置
在国内使用 JPA 来操作数据库,这样的运用场景是非常少的。
虽然,有更优秀的操作数据库的解决方案。但是,JPA 真的就没有优点了吗?
答案当然是:我也不知道。
JPA 特别适合中小型项目,它能帮助后端开发工程师更好的理解数据设计,让后端开发工程师把更多的时间、精力放在代码设计与优化之上。
至于 SQL 查询的销量,就让 JPA 自身优化去吧。
首先,在项目中引入 JPA、mysql 依赖包。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
在 application-dev.yml 中增加数据库链接的配置。
spring:
profiles: dev
datasource:
jdbcUrl: jdbc:mysql://127.0.0.1:3306/oPos?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=true
username: root
password: 123456
driverClassName: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
poolName: hikari-local
autoCommit: true
connectionTestQuery: SELECT 1
connectionTimeout: 30000
idleTimeout: 30000
maxLifetime: 1800000
maximumPoolSize: 5
minimumIdle: 1
jpa:
hibernate:
ddl-auto: update
show-sql: true
增加一个 MySQL 工厂与 Spring 事务配置类。
**
* Application config.
*
* @author chenxinjie
* @date 2020-08-01
*/
@Configuration
@EnableJpaRepositories
@EnableTransactionManagement
public class ApplicationConfig {
/**
* data source.
*
* @return
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
/**
* entity manager factory.
*
* @return
*/
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("cn.live.opos");
factory.setDataSource(dataSource());
return factory;
}
/**
* transaction manager.
*
* @param entityManagerFactory manager factory.
* @return
*/
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
以上,JPA 操作数据库的配置就结束了。
05 JPA 创建表
上一节说到,JPA 可以帮助后段开发工程师更好的理解数据库设计,就体现这里。
以下是一张导购表的 JPA 实体 Java 类。
UscGuideEntity 使用了大量的 javax.persistence.* 注解进行修饰,这样的目的是在应用启动的过程中,程序会主动的像数据库中创建指定的表。
/**
* usc_guide.
*
* @author chenxinjie
* @date 2020-08-01
*/
@Entity
@Table(name = "usc_guide", uniqueConstraints = { @UniqueConstraint(columnNames = "no") })
public class UscGuideEntity {
private static final long serialVersionUID = -5648617800765002770L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "id", length = 32)
private String id;
@Column(name = "no", length = 20, nullable = false)
private String no;
@Column(name = "name", length = 40, nullable = false)
private String name;
@Column(name = "gender", columnDefinition = "int default 0", nullable = false)
private int gender;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)
private Date ts;
public final String getId() {
return id;
}
public final void setId(String id) {
this.id = id;
}
public final String getNo() {
return no;
}
public final void setNo(String no) {
this.no = no;
}
public final String getName() {
return name;
}
public final void setName(String name) {
this.name = name;
}
public final int getGender() {
return gender;
}
public final void setGender(int gender) {
this.gender = gender;
}
public final Date getTs() {
return ts;
}
public final void setTs(Date ts) {
this.ts = ts;
}
public static final long getSerialversionuid() {
return serialVersionUID;
}
}
使用 Java 类来创建数据库表,这样的方式。将数据库表对象化,让后端开发人员非常的舒服。
当然,JPA 并不仅仅如此。它还有更加贴合手动建表的配置方式,例如:
1. 指定表名、唯一约束:
@Table(name = "usc_guide", uniqueConstraints = { @UniqueConstraint(columnNames = "no") })
2. 程序自动生成主键:
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
@Column(name = "id", length = 32)
private String id;
3. 字段长度、是否为空,等自定义配置:
@Column(name = "gender", columnDefinition = "int default 0", nullable = false)
4. 时间戳配置:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "ts", columnDefinition = "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP()", nullable = false)
private Date ts;
5. 懒加载的一对多、多对多、一对一等配置:
@OneToMany(cascade = { CascadeType.REFRESH, CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.REMOVE }, fetch = FetchType.LAZY, mappedBy = "orderEntity")
private Set<OscOrderItemEntity> orderItems;
@OneToOne
@JoinColumn(name = "sku", referencedColumnName = "sku", insertable = false, updatable = false)
private PscSkuEntity skuEntity;
6. 不挑数据库、换个数据库配置,就能自动建表。
7. 等等
06 小结
今天先写到这里。
夜深了,让我们下周再见。?
这个周末,又一次成功“强迫”自己学习。
感谢各位小伙伴的阅读,这里是一个技术人的学习与分享。