专栏首页FoamValue「拥抱开源」从零开始 Docker、Mysql & JPA

「拥抱开源」从零开始 Docker、Mysql & JPA

MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。

世界上最昂贵的东西是“免费”。

为了降低项目成本,我们有一套完整的 MySQL 开源社区版集群。希望能在低成本的基础上,带来期望的收益。

然而,经过不停的填坑操作告诉我们一个道理。

“免费” === 无人维护,商业运用还是 Oracle 关系型数据库来的香。


01 背景

这里是凭爱发电的开源项目 oPos。

考虑到将来还要自己全栈做 dev-ops,为了不给自己挖太深的坑。本项目的数据库存储采用以下技术选型:

  1. Docker ✔︎
  2. MySQL ✔︎
  3. Oracle

本文的主要作用是记录 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 来操作数据库,这样的运用场景是非常少的。

  1. 历史原因,大量的老开发人员习惯于 iBatis 操作数据库的风格。
  2. MyBatis 的出现,继承了 iBatis 的基础上,又进行了大量的优化。
  3. 在商业运用中,大量的 SQL 查询需要手动干预进行优化。

虽然,有更优秀的操作数据库的解决方案。但是,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 小结

今天先写到这里。

夜深了,让我们下周再见。?

这个周末,又一次成功“强迫”自己学习。

感谢各位小伙伴的阅读,这里是一个技术人的学习与分享。

本文分享自微信公众号 - FoamValue(gh_3c635269f459),作者:陈鑫杰

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Servlet API 源码剖析

    从目录出发,整个源代码分为 servlet、http、descriptor、annotation 四个部分。

    FoamValue
  • 工厂模式 Factory Pattern

    Factory Pattern,是 Java 常用的设计模式之一。它提供了一种与创建逻辑无关的创建实例的能力。

    FoamValue
  • 「拥抱开源」Nacos 实战篇

    启动之后,使用浏览器打开 http://localhost:8848/nacos。

    FoamValue
  • spring之通过FactoryBean配置Bean

    绝命生
  • spring之通过静态工厂方法配置Bean

    绝命生
  • spring之通过实例工厂方法配置Bean

    绝命生
  • Mybatis入门

    发现一个非常好的Mybatis详细教程,地址:https://www.w3cschool.cn/mybatis/

    SuperHeroes
  • 一个小时学会MySQL数据库

    随着移动互联网的结束与人工智能的到来大数据变成越来越重要,下一个成功者应该是拥有海量数据的,数据与数据库你应该知道。 一、数据库概要 数据库(Database)...

    张果
  • 控制反转-Ioc之Unity

    本篇幅主要介绍控制反转的一些概念,和如何使用Unity实现Ioc。在介绍的时候,会尽量结合代码来讲解一些概念。

    少羽大怪兽
  • 领域驱动设计案例之领域层实体与聚合根实现

    用户1910585

扫码关注云+社区

领取腾讯云代金券