phoenix 开发API系列(三)phoenix api 结合数据库

编程爱好者联盟 2016-09-14

概述

;

介绍了 ;api ;的各种写法之后,下面介绍构建 ;api ;时与数据库连接的方式。

;下面使用的工程的完整代码已经公开在: ;http://git.oschina.net/wangyubin/phoenix-api

;

ecto ;简介

;

ecto ;其实是独立于 ;phoenix ;framework ;的,它是 ;elixir ;语言实现的用来访问数据库的框架,类似于 ;ORM ;但是和传统的 ;ORM ;又有些不一样。 ;可以这么理解,它是利用了 ;elixir ;语言的动态性和函数式的特性,参考了传统的 ;ORM ;的优势后而开发的新一代数据库访问层。

;

ecto ;的四个主要组件

;
  1. Ecto.Repo ;数据库包装器, ;通过它可以执行数据库的增删改查, ;通过它配置数据库连接
  2. Ecto.Schema ;这是 ;ORM ;的核心,定义了操作对象和底层数据库表之间的映射
  3. Ecto.Changeset ;这是 ;Ecto ;的一个创新的地方,在 ;Changeset ;中,可以定义校验数据层合法性的方法,在真正写入数据库之前,对数据进行校验
  4. Ecto.Query ;以 ;elixir ;语法编写的查询,可以避免 ;SQL ;注入等常见问题
;

ecto ;使用示例

;

创建示例工程

;
  • 新建工程
;
$ mix new ecto_sample
;
  • 添加依赖 ;(mix.exs)
;
defp deps do
  [
    {:postgrex, ">= 0.0.0"},
    {:ecto, "~> 2.0.0"}
  ]
end
;
  • 设置应用信息 ;(mix.exs)
;
def application do
  [applications: [:logger, :postgrex, :ecto]]
end
;
  • 获取依赖包
;
$ mix deps.get
;

数据库连接配置

;
# vi config/config.exs
config :ecto_sample, ecto_repos: [EctoSample.Repo]

config :ecto_sample, EctoSample.Repo,
  adapter: Ecto.Adapters.Postgres,
  database: "ecto_sample",
  username: "iotalab",
  password: "iotalab",
  hostname: "localhost"
;

配置好数据库连接之后,就可以在命令行下创建数据库了

;

$ mix ecto.create
;

创建 ;model ;和 ;migration ;代码

;

首先,通过命令行创建一个用来生成表的的 ;users ;module。

;

$ mix ecto.gen.migration users
;

这个命令会在 ;priv/repo/migrations ;下自动生成 ;migration ;脚本,只不过脚本是空的。 ;下面先创建 ;users ;表的内容,然后填充 ;migration ;脚本的内容

;

# vi lib/ecto_models.ex
defmodule EctoSample.User do
  use Ecto.Schema

  schema "users" do
    field :name, :string
    field :password, :string
    field :age, :integer

    timestamps
  end
end
;
# vi priv/repo/migrations/20160912131700_users.exs  这个文件是由上一条命令产生的
defmodule EctoSample.Repo.Migrations.Users do
  use Ecto.Migration

  def up do
    create table(:users) do
      add :name, :string
      add :password, :string
      add :age, :integer
      timestamps
    end
  end

  def down do
    drop table(:users)
  end
end
;

创建数据库表

;

创建命令非常简单

;

$ mix ecto.migrate
;

使用示例

;

创建了一个简单的表之后,就可以在命令行下测试是否可以操作数据库了。 ;下面演示了新增一个 ;user ;和 ;删除一个 ;user ;的过程。

;

$ iex -S mix
Erlang/OTP 19 [erts-8.0.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.3.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> u = %EctoSample.User{name: "wyb", password: "passwd", age: 33}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: 33,
 id: nil, inserted_at: nil, name: "wyb", password: "passwd", updated_at: nil}


iex(2)> EctoSample.Repo.insert(u)

22:09:51.433 [debug] QUERY OK db=4.4ms
INSERT INTO "users" ("age","name","password","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5) RETURNING "id" [33, "wyb", "passwd", {{2016, 9, 12}, {14, 9, 51, 0}}, {{2016, 9, 12}, {14, 9, 51, 0}}]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, age: 33,
  id: 3, inserted_at: #Ecto.DateTime<2016-09-12 14:09:51>, name: "wyb",
  password: "passwd", updated_at: #Ecto.DateTime<2016-09-12 14:09:51>}}


iex(3)> u = %EctoSample.User{id: 3}
%EctoSample.User{__meta__: #Ecto.Schema.Metadata<:built, "users">, age: nil,
 id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}


iex(4)> EctoSample.Repo.delete(u)

22:11:28.960 [debug] QUERY OK db=3.4ms
DELETE FROM "users" WHERE "id" = $1 [3]
{:ok,
 %EctoSample.User{__meta__: #Ecto.Schema.Metadata<:deleted, "users">, age: nil,
  id: 3, inserted_at: nil, name: nil, password: nil, updated_at: nil}}
;

补充说明

;

除了修改上面的文件之外,还有下面2个地方需要修改,否则 ;EctoSample ;模块不会加载:

;

# vi lib/ecto_sample.ex
defmodule EctoSample do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(EctoSample.Repo, []),
    ]
    opts = [strategy: :one_for_one, name: EctoTest.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
;
def application do
  [applications: [:logger, :postgrex, :ecto],
   mod: {EctoSample, []}]   # <===  IMPORTANT !!!
end
;

api ;with ;postgresql

;

postgresql ;安装与配置

;

以下安装配置是基于 ;CentOS7 ;的

;

# 安装 package
$ sudo yum install postgresql-server

# init db
$ sudo su - postgres
$ initdb -D /var/lib/pgsql/data

# start db
$ sudo systemctl start postgresql

# create user and database
$ sudo su - postgres
$ psql -U postgres -W       # password is also "postgres"
postgres=# CREATE USER iotalab WITH PASSWORD &#39;iotalab&#39;;
postgres=# CREATE DATABASE test OWNER iotalab ENCODING &#39;UTF8&#39;;
;

设置可以局域网内访问

;

$ sudo su - postgres 
$ cd /var/lib/pgsql/data
;

vim ;pg_hba.conf

;<pre>host ; ; ; ;all ; ; ; ; ; ; ; ; ; ; ; ; ;all ; ; ; ; ; ; ; ; ; ; ; ; ;0.0.0.0/0 ; ; ; ; ; ; ; ; ; ; ; ;md5</pre> ;

vim ;postgresql.conf

;<pre>listen_addresses ;= ;&#39;*&#39;</pre> ;

远程连接不上时试试禁用 ;iptables

;

$ sudo systemctl stop iptables
;

创建 ;数据库和表

;<ol> ;<li>

给这个工程加上 ;数据库的支持 ;其实创建的工程的时候,默认就是支持数据库的。但是前面的示例不需要数据库,所以创建这个工程的时候用了 ;–no-ecto ;的参数。 ;重新创建工程,并将已写的代码复制进去即可,这次创建工程时不加 ;–no-ecto ;参数。

;

$ mix phoenix.new phoenix_api
</li> ;<li>

配置数据库连接并创建数据库 ;修改文件 ;config/dev.exs

;

# Configure your database
config :phoenix_api, PhoenixApi.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: "iotalab",
  password: "iotalab",
  database: "dev_db",
  hostname: "localhost",
  pool_size: 10
;

创建数据库

;

$ mix ecto.create
</li> ;<li>

创建一张用来测试的表

;

$ mix phoenix.gen.model User users name:string email:string age:integer
* creating web/models/user.ex
* creating test/models/user_test.exs
* creating priv/repo/migrations/20160913230129_create_user.exs
;

查看生成的文件,已经根据命令行的中参数,生成了对应的对象,可以发现其中自动添加了 ;timestamps ;方法,这个方法是自动添加一些 ;updated_at, ;inserted_at ;等通用时间字段。 ;然后通过命令行创建表:

;

$  mix ecto.migrate

07:10:52.527 [info]  == Running PhoenixApi.Repo.Migrations.CreateUser.change/0 forward

07:10:52.527 [info]  create table users

07:10:52.537 [info]  == Migrated in 0.0s
</li> ;</ol> ;

增删改查 ;示例

;

在测试代码中构造了 ;增删改查 ;的测试 ;case,然后用 ;mix ;test ;命令来进行测试。 ;具体代码可以参考:http://git.oschina.net/wangyubin/phoenix-api/blob/master/test/models/user_test.exs

;

总结

;

利用 ;ecto ;模块,操作数据库非常简单,但是,写岀优秀 ;api ;的关键还是在于 ;api ;的设计上,学习这个框架的意义是在于把一些通用繁琐的工作交给框架来处理,可以让我们把主要的精力放在业务代码的构建上。

至此,phoenix ;framework ;api ;系列的3篇也结束了。

相关推荐

jiong / 0评论 2020-09-17