web开发之数据库技术

简介:本文将从web开发中的数据存储和持久化开始讨论,然后引入web开发中涉及到数据库相关技术,包括管理连接的sql库,以及连接数据库和不同编程语言的数据库驱动,同时还会介绍orm机制。

💇为什么我们在web开发中需要数据库💇

假设我们在设计一款基于图片的社交软件,我们可以通过在软件上分享和浏览图片来找到感兴趣的好友,只要有基本编程经验的人都知道,既然我们允许用户上传图片,那么势必得有服务器为我们进行存储,当然我们可以使用文件进行存储,小规模的数据可以接受,但要知道的是,我们设计的应用是要为大量的人服务的,因此我们有必要使用高效的文件系统来为我们提供数据的快速存储和检索功能,数据库服务就是为了完成这一使命而诞生的。

:happy: 数据库技术简要介绍:happy:

将大量的数据按照一定的方式组织存放在计算机中,这样的数据集合称之为数据集合,而通过特定的组织方式,以及访问方法将为外部提供数据库的访问,称之为数据库管理系统。常用的数据库管理系统一般都是RDBMS,也就是关系型数据库,他是建立在严格的代数数学基础之上的,表现形式上,关系型数据库组织为一个个的二维表格,表格中的每一行代表一行数据,第一行是列名,代表行中每一列的实际含义,举例说明如下:

商品编号 商品名称 商品种类 销售单价 进货单价
0001 T恤衫 衣服 1000 500
0002 菜刀 厨具 300 100
0003 圆珠笔 文具 50 30

表的列称为字段,而每一行称之为表中的记录,关系型数据库的操作一定是以行为单位进行读写的,表中一般将某一字段设置为表中的主键,被设置为主键的字段不允许重复,数据库内部会将其设置为索引,加速数据操作的过程。数据库设计完成后,对外提供SQL,通过这一领域类型语言,可以实现对数据库的操作。数据库和使用数据库的用户构成了标准的CS模型。

🌈数据库驱动技术 🌈 ​

前面已经提到,客户端通过SQL来进行数据库的访问,这样的情况对于我们手动的编写SQL程序是可以满足的,但是更多的应用场景是,我们是在应用程序中访问数据库,具体的表现形式就是,我们需要以其他编程语言的方式,来进行数据库的方式,这个时候,就需要数据库驱动技术了,数据库驱动简单来讲,就是一种适配器接口,通过该驱动,能够为我们实现以编程语言的方式连接访问数据库,并且执行SQL语言。数据库的具体实现也不止一种,数据库驱动就是为我们屏蔽掉这些差异,只需要通过简单配置的方式就可以实现数据库的访问。具体实现上来讲,无非就是通过网络进行和数据库的连接,然后将SQL发送至数据库服务端即可。下面用一段go程序进行说明:

import (
    //通用的数据库连接服务库
    //执行通用的网络链接服务,使用了池化思想
	"database/sql"
    "fmt"
    //执行仅导入且执行包中的init函数,允许导入后不适用
    //第三方的PostgreSQL驱动包
    _ "github.com/lib/pq"
)
var Db * sql.DB
func init() {
    var err error
    Db,err = sql.Open("postgres","user=gwp dbname=gwp password=gwp sslmode=disable")
    if(err != nil) {
        panic(err)
    }
}

通过init函数就完成了数据库的链接服务,以后我们进行数据库的访问,都是通过该数据库句柄进行操作的。

对了,在执行该代码之前,我们还需要在系统中进行数据库的初始化设置,下载安装Postgre数据库,然后执行以下sql代码:

//创建用户
createuser -P -d gwp
//创建数据库名称
createdb gwp
//创建post表,将id设置为主键
create table posts (
	id serial primary key,
    content text,
    author varchar(255)
);

这样我们就通过第三方编程语言的方式完成了数据库的链接,下面我们讨论如何进行数据的操作,也就是执行数据库的CRUD操作。

🚂向着持久化前进🚂

在上一节中我们得到了数据操作句柄,通过该句柄,我们就能够进行数据库的使用了,所谓的使用,也就是我们能够将原先以sql进行数据库操作的方式,改成了通过编程的方式进行操作,并且还添加了特定的语言特性。现在我们可以对数据库进行一定的操作了,比如说进行查询,修改,新数据的插入等等。OK,我们先来简单的看一下基本的操作,有着一个基本的认识:

type Post struct{
    Id int
    Content string
    Author string
}
func GetPost(id int) (post Post,err error) {
    post = Post{}
    err = Db.QueryRow("select id,content,author from posts where id = $1",id).
    		Scan(&post.Id,&post.Content,&post.Author)
    return
}
func (post * Post) Create() (err error) {
    statement := "insert into posts (content, author) values ($1,$2) retuning id"
    stmt,err := Db.Prepare(statement)
    if err != nil{
        return
    }
    defer stmt.Close()
    err = stmt.QueryRow(post.Content,post.Author).Scan(&post.Id)
    if err != nil {
        return
    }
    return
}

上面两个函数分别实现了数据库的记录插入和查询操作。可以看出,我们在进行数据库的操作时,大部分可以抽象成将数据库中表中的记录和我们的自定义结构(面向对象中叫做对象)进行相互的映射操作。因此便引入了我们下面要讲的服务:orm

🐰关系映射器ORM🐰

编程设计上就是在进行着各种程度的抽象,通过抽象我们将大的任务分解成小的任务,通过抽象,我们也将机械重复的工作进行了自动化处理。object relational mapper:关系映射器的想法便是将上面需要手动进行映射的工作变得完全自动化。下面我们用实际的代码进行介绍:

//为了方便,我们仅仅介绍代码中发生的变动
import (
	"github.com/jmoiron/sqlx"
)
type Post struct{
    Id int
    Content string
    AuthorName string 'db: author'
}
var Db * sqlx.DB
Db,err = sqlx.Open("postgres","user=gwp dbname=gwp password=gwp sslmode=disable")
func (post *Post) Create)() (err error) {
    post = Post{}
    err = Db.QueryRow("insert into posts (content,author) values ($1,$2) returing id").
    		StructScan(&post)
    if(err != nil){
        return
    }
    return
}

可以看到,代码量大大的减少了,这样我们就没有必要将原先的映射关系在手动的书写一遍了,顺便讲解一下其原理,SturctScan方法根据结构字段的英文小写映射到对应的表中同名字段中去,假如我们想明确结构体中和表中不同名之间的映射,那么需要手动的进行设置,设置方法就是在定义结构体时进行备注说明。

总结,在编程应用中使用数据库技术,不仅仅需要考虑数据库本身,还涉及到一些仅仅用sql来操作数据中的其他问题,比如应用程序和不同数据库的连接操作,这需要数据库驱动来为我们屏蔽掉这些数据库的差异,同时,为了建立数据表中的数据和结构(对象)的数据映射,我们还需要第三方库来为我们完成这些重复的工作,对于go,有sqlx和gorm这样的第三方库,对于java,有Hibernate和Mybatis这样的第三方库。

posted @ 2020-08-08 14:43  smalllll  阅读(785)  评论(0编辑  收藏  举报