phoenix 開發API系列(三)phoenix api 結合數據庫


概述

介紹了 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 'iotalab';
postgres=# CREATE DATABASE test OWNER iotalab ENCODING 'UTF8';

設置可以局域網內訪問

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

vim pg_hba.conf

host    all             all             0.0.0.0/0            md5

vim postgresql.conf

listen_addresses = '*'

遠程連接不上時試試禁用 iptables

$ sudo systemctl stop iptables

創建 數據庫和表

  1. 給這個工程加上 數據庫的支持 其實創建的工程的時候,默認就是支持數據庫的。但是前面的示例不需要數據庫,所以創建這個工程的時候用了 –no-ecto 的參數。 重新創建工程,並將已寫的代碼復制進去即可,這次創建工程時不加 –no-ecto 參數。

    $ mix phoenix.new phoenix_api
    
  2. 配置數據庫連接並創建數據庫 修改文件 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
    
  3. 創建一張用來測試的表

    $ 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
    

增刪改查 示例

在測試代碼中構造了 增刪改查 的測試 case,然后用 mix test 命令來進行測試。 具體代碼可以參考:http://git.oschina.net/wangyubin/phoenix-api/blob/master/test/models/user_test.exs

總結

利用 ecto 模塊,操作數據庫非常簡單,但是,寫岀優秀 api 的關鍵還是在於 api 的設計上,學習這個框架的意義是在於把一些通用繁瑣的工作交給框架來處理,可以讓我們把主要的精力放在業務代碼的構建上。

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

來源:http://blog.iotalabs.io/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM