概述

介绍了 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/

phoenix 开发API系列(三)phoenix api 结合数据库的更多相关文章

  1. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  2. WCF开发实战系列三:自运行WCF服务

    WCF开发实战系列三:自运行WCF服务 (原创:灰灰虫的家 http://hi.baidu.com/grayworm)上一篇文章中我们建立了一个WCF服务站点,为WCF服务库运行提供WEB支持,我们把 ...

  3. Web API系列(三)统一异常处理

    前面讲了webapi的安全验证和参数安全,不清楚的朋友,可以看看前面的文章,<Web API系列(二)接口安全和参数校验>,本文主要介绍Web API异常结果的处理.作为内部或者是对外提供 ...

  4. Kafka系列三 java API操作

    使用java API操作kafka 1.pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xs ...

  5. RabbitMQ系列(三)--Java API

    基于java使用RabbitMQ 框架:SpringBoot1.5.14.RELEASE maven依赖: <dependency> <groupId>com.rabbitmq ...

  6. flask开发restful api系列(3)--利用alembic进行数据库更改

    上面两章,主要讲基本的配置,今天我们来做一个比较有趣的东西,为每个客户加一个头像图片.如果我们图片保存在自己的服务器,对于服务器要求有点高,每次下载的时候,都会阻塞网络接口,要是1000个人同时访问这 ...

  7. Apache Kafka系列(三) Java API使用

    Apache Kafka系列(一) 起步 Apache Kafka系列(二) 命令行工具(CLI) Apache Kafka系列(三) Java API使用 摘要: Apache Kafka Java ...

  8. Hello Web API系列教程——Web API与国际化

    软件国际化是在软件设计和文档开发过程中,使得功能和代码设计能处理多种语言和文化习俗,在创建不同语言版本时,不需要重新设计源程序代码的软件工程方法.这在很多成熟的软件开发平台中非常常见.对于.net开发 ...

  9. html5 canvas常用api总结(三)--图像变换API

    canvas的图像变换api,可以帮助我们更加方便的绘画出一些酷炫的效果,也可以用来制作动画.接下来将总结一下canvas的变换方法,文末有一个例子来更加深刻的了解和利用这几个api. 1.画布旋转a ...

  10. 【开发者portal在线开发插件系列三】字符串 及 可变长度字符串

    基础篇 基础场景见上面两个帖子,这里单独说明字符串和可变长度字符串的用法. 话不多说,开始今天的演(表)示(演) Profile和插件开发 添加一个string类型的属性: 在插件里添加一条数据上报消 ...

随机推荐

  1. Python模块:PIL

    PIL:是Python Image Library的缩写,图像处理的模块.Image,ImageFont,ImageDraw,ImageFilter Image模块: 常用方法: open() #打开 ...

  2. 2.jenkins配置邮件提醒

    1.前言 在Jenkins的使用中邮件提醒是一个常用功能,Jenkins默认安装了Mailer Plugin插件用于实现此功能. 2.邮件服务器配置 首先在Jenkins的"系统管理&quo ...

  3. Twitter的分布式自增ID算法snowflake (Java版)

    概述 分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的. 有些时候我们希望能使用一种 ...

  4. iOS:xCode7版本运行xCode8.0的代码

    怎么在xCode7版本上运行xCode8.0的代码? 1.右键你的"LaunchScreen.sb"文件并用编辑器打开sb 2.删掉"<capability nam ...

  5. Python切片

    切片是啥, 可以吃么 切片肿么用哈 辣么长,记不住 切片是啥, 可以吃么 嘛,所谓切片故名思意就有选取的意思啦, 跟java里面的subString()意思差不多, 从原始的字符串中按规则提取出新的字 ...

  6. doT.js源码解读

    doT.js非常的简洁.全部代码也就200行不到.它的基本思路就是通过强大的正则表达式,把模块转变成可执行的函数,动态生成html字符串.核心new Function(c.varname, str); ...

  7. javascript学习面向对象(二)

    主要内容: prototype扩展应用示例: 对比如下: 数组中forEach用法示例: 从上面示例可以看出,forEach只适合遍历一维数组: 应用prototype扩展实现全部元素遍历如下: 简单 ...

  8. 交换机的link-dependency链路依赖功能

    在生产环境中,如果各主机连接到交换机的1-16端口,交换机的18端口上联到外部网络,如果此时交换机的18端口断掉,在主机端网卡仍然有连接,对于一些网络的配置可能就感知不到外部连接的消失,会有问题(如E ...

  9. js模块和级联

    1.模块 模块模式的一般形式是:一个定义了私有变量和函数的函数,利用闭包创建可以访问私有变量和函数的特权函数,最后返回这个特权函数,或者把它们保存到一个可访问的地方.使用模块模式就可以摒弃全局变量的使 ...

  10. GridView基础知识

    首先,gridview是封装好的,直接在设计界面使用,基本不需要写代码: 1.绑定数据源 GridView最好与LinQDatasourse配合使用,相匹配绑定数据: 2.外观控制 整体控制 自动选择 ...