443 lines
20 KiB
XML
Executable File
443 lines
20 KiB
XML
Executable File
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>XORM - 官方博客</title><link>http://localhost</link><description>Xorm 是一个简单而强大的Go语言ORM框架</description><lastBuildDate>Mon, 04 Jan 2016 23:17:35 +0800</lastBuildDate><item><title>关于XORM中Mapper的使用</title><link>http://localhost/2016/1/4/1-about-mapper.html</link><pubDate>Mon, 04 Jan 2016 13:08:00 +0000</pubDate><category>go</category><category>golang</category><category>xorm</category><category>orm</category><category>sql</category><category>database</category><description><![CDATA[ <p>XORM中的Mapper是一个接口机制,专门用来在程序名称和数据库名称之间进行转换。XORM库中带有三种Mapper的实现,SnakeMapper, SameMapper 以及 GonicMapper。同时为了方便还提供了CacheMapper, PrefixMapper 以及 SuffixMapper,这几种Mapper可以和前面的组合使用。</p>
|
||
|
||
<h1>SnakeMapper</h1>
|
||
|
||
<p>SnakeMapper是默认的映射机制,他支持数据库表采用匈牙利命名法,而程序中采用驼峰式命名法。下面是一些常见的映射:</p>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>表中名称</th>
|
||
<th>程序名称</th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<tbody>
|
||
<tr>
|
||
<td>user_info</td>
|
||
<td>UserInfo</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td>id</td>
|
||
<td>Id</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h1>SameMapper</h1>
|
||
|
||
<p>SameMapper就是数据库中的命名法和程序中是相同的。那么鉴于在Go中,基本上要求首字母必须大写。所以一般都是表中和程序中均采用驼峰式命名。下面是一些常见的映射:</p>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>表中名称</th>
|
||
<th>程序名称</th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<tbody>
|
||
<tr>
|
||
<td>UserInfo</td>
|
||
<td>UserInfo</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td>Id</td>
|
||
<td>Id</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h1>GonicMapper</h1>
|
||
|
||
<p>GonicMapper是在SnakeMapper的基础上增加了特例,对于常见的缩写不新增下划线处理。这个同时也符合golint的规则。下面是一些常见的映射:</p>
|
||
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>表中名称</th>
|
||
<th>程序名称</th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<tbody>
|
||
<tr>
|
||
<td>user_info</td>
|
||
<td>UserInfo</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td>id</td>
|
||
<td>ID</td>
|
||
</tr>
|
||
|
||
<tr>
|
||
<td>url</td>
|
||
<td>URL</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h1>CacheMapper</h1>
|
||
|
||
<p>CacheMapper 通过使用一个map来将已经映射过的内容保存起来,下次直接查找即可获得。</p>
|
||
|
||
<h1>PrefixMapper</h1>
|
||
|
||
<p>PrefixMapper 前缀映射可以组合SnakeMapper, SameMapper或者GonicMapper来在表名或者字段名的映射完成后,再新增一个固定的前缀。比如和SnakeMapper组合:</p>
|
||
<pre><code class="language-Go">engine.SetTableMapper(core.NewPrefixMapper(core.SnakeMapper{}, "tb_"))
|
||
engine.SetColumnMapper(core.SnakeMapper{})
|
||
</code></pre>
|
||
|
||
<p>那么对于结构体<code>User</code>,数据库中对应的表名即为<code>tb_user</code>,而表中字段名比如<code>id</code>对应的程序中结构体字段名仍为<code>Id</code>。</p>
|
||
|
||
<h1>SuffixMapper</h1>
|
||
|
||
<p>SuffixMapper 后缀映射类似与前缀映射,也可以组合SnakeMapper, SameMapper或者GonicMapper来在表名或者字段名的映射完成后,再新增一个固定的前缀。比如和SnakeMapper组合:</p>
|
||
<pre><code class="language-Go">engine.SetTableMapper(core.NewSuffixMapper(core.SnakeMapper{}, "_table"))
|
||
engine.SetColumnMapper(core.SnakeMapper{})
|
||
</code></pre>
|
||
|
||
<p>那么对于结构体<code>User</code>,数据库中对应的表名即为<code>user_table</code>,而表中字段名比如<code>id</code>对应的程序中结构体字段名仍为<code>Id</code>。</p>
|
||
|
||
<h1>表名和字段名分别映射</h1>
|
||
|
||
<p>在前面的例子中也看到了,这种映射可以对表名和字段名采用相同的映射,也可以表名和字段名采用不同的映射方案。</p>
|
||
|
||
<ul>
|
||
<li><p>表名和字段名使用相同映射方案</p>
|
||
<pre><code class="language-Go">engine.SetMapper(mapper)
|
||
</code></pre></li>
|
||
|
||
<li><p>表名和字段名使用不同的映射方案</p>
|
||
<pre><code class="language-Go">engine.SetTableMapper(mapper1)
|
||
engine.SetColumnMapper(mapper2)
|
||
</code></pre></li>
|
||
</ul>
|
||
|
||
<p>最后,关于名称映射更多的方法可以参考XORM文档 <a href="http://gobook.io/read/go-xorm/manual-zh-cn/chapter-02/3.tags.html">使用Table和Tag改变名称映射</a></p>
|
||
]]></description></item><item><title>在Xorm中使用Join和Extends标记</title><link>http://localhost/2015/12/1/1-xorm-join-extends-usage.html</link><pubDate>Tue, 01 Dec 2015 16:00:00 +0000</pubDate><category>go</category><category>golang</category><category>xorm</category><category>orm</category><category>sql</category><category>database</category><description><![CDATA[ <p>本文主要针对对Xorm已经有了一定了解的读者,如果您是第一次了解Xorm,请先阅读<a href="http://xorm.io/docs">xorm操作手册</a>。</p>
|
||
|
||
<p>Xorm的基本操作都是比较简单的,可能大家也都比较熟悉了。今天主要讲解extends标记和join的使用。通过使用join和extends,可以解决许多需要级联进行的操作。</p>
|
||
|
||
<p>一般我们会针对数据库中的每一个表,建立一个对应的结构体。比如:</p>
|
||
<pre><code class="language-Go">type User struct {
|
||
Id int64
|
||
Name string
|
||
}
|
||
|
||
type Account struct {
|
||
Id int64
|
||
UserId int64 `xorm:"index"`
|
||
Amount int64
|
||
}
|
||
|
||
type Car struct {
|
||
Id int64
|
||
UserId int64 `xorm:"index"`
|
||
Type int
|
||
}
|
||
</code></pre>
|
||
|
||
<p>我们定义了三个结构体,对应数据库的三个表,我们在启动时通过:</p>
|
||
<pre><code class="language-Go">engine.Sync2(new(User), new(Account), new(Car))
|
||
</code></pre>
|
||
|
||
<p>来进行数据库结构的同步。在这个数据库结构中,我们假设一个用户拥有一个Account,一个用户拥有多个Car。</p>
|
||
|
||
<p>OK。复杂需求来了。</p>
|
||
|
||
<p>1)我们需要获得所有的用户的姓名和对应的账户的余额:</p>
|
||
<pre><code class="language-Go">type AccountUser struct {
|
||
Account `xorm:"extends"`
|
||
User `xorm:"extends"`
|
||
}
|
||
|
||
var accounts = make([]*AccountUser, 0)
|
||
engine.Table("account").Join("INNER", "user", "account.user_id = user.id").Find(&accounts)
|
||
</code></pre>
|
||
|
||
<p>OK。这样,我们就取出了user和对应的account,我们通过<code>account.Account</code>可以获取到Account的信息,通过<code>account.User</code>可以获取到User的信息。</p>
|
||
|
||
<p>这个是两个表Join,那么如果是三个表也是类似的做法。</p>
|
||
|
||
<p>2)我只需要用户名,不需要其它的内容:</p>
|
||
<pre><code class="language-Go">type AccountUser struct {
|
||
Account `xorm:"extends"`
|
||
Name string
|
||
}
|
||
var accounts = make([]*AccountUser, 0)
|
||
engine.Table("account").Join("INNER", "user", "account.user_id = user.id").Find(&accounts)
|
||
</code></pre>
|
||
|
||
<p>其实我们代码也是差不多的,但是这里我们实际上在查询数据库的时候是查询了user表的所有内容的。只是在最后赋值到结构体时,按需赋值。</p>
|
||
|
||
<p>3)更复杂的,我们还想知道每人有几辆车。</p>
|
||
<pre><code class="language-Go">type AccountUser struct {
|
||
Account `xorm:"extends"`
|
||
Name string
|
||
NumCars int
|
||
}
|
||
var accounts = make([]*AccountUser, 0)
|
||
engine.Sql("select account.*, user.name, (select count(id) from car where car.user_id = user.id) as num_cars from account, user where account.user_id = user.id").Find(&accounts)
|
||
</code></pre>
|
||
|
||
<p>在这样的复杂需求下,我们使用了Sql函数和extends标记结合来完成这个操作。</p>
|
||
]]></description></item><item><title>Xorm博客定型</title><link>http://localhost/2015/10/1/welcome.html</link><pubDate>Thu, 01 Oct 2015 16:00:00 +0000</pubDate><category>go</category><category>golang</category><category>xorm</category><category>orm</category><category>sql</category><category>database</category><description><![CDATA[ <p>终于迎来了个人认为最有发展潜力的静态站点生成工具 <a href="https://github.com/go-xiaohei/pugo">Pugo</a>发布了第一个稳定版本,本博客将使用其搭建,将会发布关于xorm的高质量文章和新版本等信息.</p>
|
||
]]></description></item><item><title>XORM的七种武器</title><link>http://localhost/2014/1/1/1-7-weapons.html</link><pubDate>Wed, 01 Jan 2014 16:00:00 +0000</pubDate><category>go</category><category>golang</category><category>xorm</category><category>orm</category><category>sql</category><category>database</category><description><![CDATA[ <p><a href="https://github.com/lunny/xorm">xorm</a> 是一个简单而强大的 Go 语言开源 ORM 库. 通过它可以使数据库操作非常简便。</p>
|
||
|
||
<h1>xorm 的七种武器</h1>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 是一个简单而强大的 Go 语言开源 ORM 库. 通过它可以使数据库操作非常简便。</p>
|
||
|
||
<p>了解过 Go 的人可能会有疑问,Go 已经提供了 database/sql 接口,操作各种数据库接口都一致了,还有必要再使用 ORM 吗?也有人觉得对于复杂 SQL 语句,ORM 是无法应付的。</p>
|
||
|
||
<p>是的,<a href="https://github.com/lunny/xorm">xorm</a> 不是为了取代 SQL,它甚至可以和 SQL 混用,它是在 databse/sql 接口的基础之上提供了更多的特性。我们将这些功能和特性比喻成七种武器,来帮助开发者快速的完成数据库的操作。</p>
|
||
|
||
<!--more-->
|
||
|
||
<h2>安装</h2>
|
||
|
||
<p>当然,第一步,我们必须要安装 <a href="https://github.com/lunny/xorm">xorm</a>:</p>
|
||
|
||
<p>如果你有安装 gopm,强烈建议使用 <a href="https://github.com/gpmgo/gopm">gopm</a> 来进行 go 的包管理:</p>
|
||
<pre><code>gopm get github.com/lunny/xorm
|
||
</code></pre>
|
||
|
||
<p>如果没有安装 gopm,当然也可以直接用 go 工具进行安装:</p>
|
||
<pre><code>go get github.com/lunny/xorm
|
||
</code></pre>
|
||
|
||
<h2>数据库及驱动支持</h2>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 当前支持如下 5 种数据库驱动和 4 种数据库。</p>
|
||
|
||
<ul>
|
||
<li><p>Mysql: <a href="https://github.com/go-sql-driver/mysql">github.com/go-sql-driver/mysql</a></p></li>
|
||
|
||
<li><p>MyMysql: <a href="https://github.com/ziutek/mymysql/godrv">github.com/ziutek/mymysql/godrv</a></p></li>
|
||
|
||
<li><p>SQLite: <a href="https://github.com/mattn/go-sqlite3">github.com/mattn/go-sqlite3</a></p></li>
|
||
|
||
<li><p>Postgres: <a href="https://github.com/lib/pq">github.com/lib/pq</a></p></li>
|
||
|
||
<li><p>MsSql: <a href="https://github.com/lunny/godbc">github.com/lunny/godbc</a></p></li>
|
||
</ul>
|
||
|
||
<h2>第一种武器:结构体和数据库表的映射</h2>
|
||
|
||
<p>在 <a href="https://github.com/lunny/xorm">xorm</a> 中,我们用一个结构体和数据库中的表进行对应,结构体中的 field 和数据库中的 column 进行对应,通过在 field 后面的 tag 来进行一些特殊的设置,例如:unique,表示唯一索引;pk 表示主键;version 表示乐观锁字段,等等。写过 sql 语句的同学可能会觉得这些标记很熟悉,是的,大部分和 sql 语句里面的 column 定义类似。</p>
|
||
<pre><code>type User struct {
|
||
Id int64
|
||
Name string `xorm:"unique not null"`
|
||
Age int
|
||
Avatar []byte
|
||
Created time.Time `xorm:"created"`
|
||
Updated time.Time `xorm:"updated"`
|
||
Version int `xorm:"version"`
|
||
}
|
||
</code></pre>
|
||
|
||
<p>对应的过程必然涉及到命名的映射。默认的 <a href="https://github.com/lunny/xorm">xorm</a> 提供了 SnakeMapper,SameMapper, PrefixMapper,
|
||
SuffixMapper 几种命名方式和方案,基本可以满足各种需要。</p>
|
||
|
||
<h2>第二种武器:连写神技</h2>
|
||
|
||
<p>使用可以连写的 API 对于一个拥有语法提示的编辑器简直就是效率利器,那么我们还有什么理由不支持呢。看看我们这个能写多长:</p>
|
||
<pre><code>engine.Where("id=?", 1).And("name = ?", "xlw").Or("age > ?", 20).Asc("name").Desc("id").Find(&users)
|
||
</code></pre>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 主要的操作实际上是两个 RAW 函数和七个 ORM 函数:</p>
|
||
|
||
<h3>RAW 函数</h3>
|
||
|
||
<ul>
|
||
<li><p>Query:执行 SQL 查询语句</p>
|
||
<pre><code>results, err := engine.Query("select * from user")
|
||
</code></pre></li>
|
||
|
||
<li><p>Exec:执行 SQL 执行语句</p>
|
||
<pre><code>affected, err := engine.Exec("update user set .... where ...")
|
||
</code></pre></li>
|
||
</ul>
|
||
|
||
<h3>ORM 函数</h3>
|
||
|
||
<ul>
|
||
<li><p>Insert:插入一条或多条数据</p>
|
||
<pre><code>affected, err := engine.Insert(&struct)
|
||
// INSERT INTO struct () values ()
|
||
affected, err := engine.Insert(&struct1, &struct2)
|
||
// INSERT INTO struct1 () values ()
|
||
// INSERT INTO struct2 () values ()
|
||
affected, err := engine.Insert(&sliceOfStruct)
|
||
// INSERT INTO struct () values (),(),()
|
||
affected, err := engine.Insert(&struct1, &sliceOfStruct2)
|
||
// INSERT INTO struct1 () values ()
|
||
// INSERT INTO struct2 () values (),(),()
|
||
</code></pre></li>
|
||
|
||
<li><p>Get:获取单条数据</p>
|
||
<pre><code>has, err := engine.Get(&user)
|
||
// SELECT * FROM user LIMIT 1
|
||
</code></pre></li>
|
||
|
||
<li><p>Find:获取多条数据</p>
|
||
<pre><code>err := engine.Find(&users)
|
||
// SELECT * FROM user
|
||
</code></pre></li>
|
||
|
||
<li><p>Iterate & Rows:获取多条数据并逐条处理</p>
|
||
<pre><code>err := engine.Iterate(..., func(...) {
|
||
// ...
|
||
})
|
||
// SELECT * FROM user
|
||
|
||
|
||
rows, err := engine.Rows(...)
|
||
// SELECT * FROM user
|
||
for rows.Next() {
|
||
rows.Scan(&user)
|
||
}
|
||
</code></pre></li>
|
||
|
||
<li><p>Update:更新一条或多条记录</p>
|
||
<pre><code>affected, err := engine.Update(&user)
|
||
// UPDATE user SET
|
||
</code></pre></li>
|
||
|
||
<li><p>Delete:删除数据</p>
|
||
<pre><code>affected, err := engine.Delete(&user)
|
||
// DELETE FROM user Where ...
|
||
</code></pre></li>
|
||
|
||
<li><p>Count:根据查询条件计算数量</p>
|
||
<pre><code>counts, err := engine.Count(&user)
|
||
// SELECT count(*) AS total FROM user
|
||
</code></pre></li>
|
||
</ul>
|
||
|
||
<p>这些函数放到连写的最后,前面可以采用各种条件的连写。</p>
|
||
|
||
<h2>第三种武器:表结构同步</h2>
|
||
|
||
<p>随着需求的改变,有的时候,我们不得不去修改原有的数据结构,那么此时,我们可能就要去修改数据库的表结构或者索引之类。这是一个繁琐的工作,而且很可能会漏掉之类。通过 <a href="https://github.com/lunny/xorm">xorm</a> 的 <code>Sync</code> 函数,这个工作将变得简单得多。</p>
|
||
<pre><code>err := engine.Sync(new(User))
|
||
</code></pre>
|
||
|
||
<p>只需要在程序启动时,执行 <code>Sync</code>,并将需要同步的一个或者多个表对应的 Struct 作为参数传入,那么 engine 将自动的检测并新增表,新增字段,新增索引。</p>
|
||
|
||
<p>是不是很简单,很强大。当然,其实也可以做到自动删除列,但是这样的话,很有可能会引起数据丢失,因此当前只提供了自动新增的功能。这个功能后面还会继续增强。</p>
|
||
|
||
<h2>第四种武器:混合事务</h2>
|
||
|
||
<p>当使用事务处理时,需要创建 Session 对象。在进行事物处理时,可以混用 ORM 方法和 RAW 方法,如下代码所示:</p>
|
||
<pre><code>session := engine.NewSession()
|
||
defer session.Close()
|
||
|
||
// add Begin() before any action
|
||
err := session.Begin()
|
||
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny"}
|
||
_, err = session.Insert(&user1)
|
||
if err != nil {
|
||
session.Rollback()
|
||
return
|
||
}
|
||
|
||
_, err = session.Where("id = ?", 2).Update(&Userinfo{Username: "yyy"})
|
||
if err != nil {
|
||
session.Rollback()
|
||
return
|
||
}
|
||
|
||
_, err = session.Exec("delete from userinfo where username = ?", user2.Username)
|
||
if err != nil {
|
||
session.Rollback()
|
||
return
|
||
}
|
||
|
||
// add Commit() after all actions
|
||
err = session.Commit()
|
||
if err != nil {
|
||
return
|
||
}
|
||
</code></pre>
|
||
|
||
<h2>第五种武器:数据库缓存</h2>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 内置了一致性缓存支持,根据测算,开启缓存后,查询性能提高了 3-5 倍。不过缓存默认并没有开启。要开启缓存,需要在engine创建完后进行配置,如:</p>
|
||
|
||
<p>启用一个全局的内存缓存</p>
|
||
<pre><code>cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
|
||
engine.SetDefaultCacher(cacher)
|
||
</code></pre>
|
||
|
||
<p>上述代码采用了 LRU 算法的一个缓存,缓存方式是存放到内存中,缓存 struct 的记录数为 1000 条,缓存针对的范围是所有具有主键的表,没有主键的表中的数据将不会被缓存。
|
||
如果只想针对部分表,则:</p>
|
||
<pre><code>cacher := xorm.NewLRUCacher(xorm.NewMemoryStore(), 1000)
|
||
engine.MapCacher(&user, cacher)
|
||
</code></pre>
|
||
|
||
<p>如果要禁用某个表的缓存,则:</p>
|
||
<pre><code>engine.MapCacher(&user, nil)
|
||
</code></pre>
|
||
|
||
<p>设置完之后,其它代码基本上就不需要改动了,缓存系统已经在后台运行。</p>
|
||
|
||
<p>当前实现了内存存储的 CacheStore 接口 MemoryStore,如果需要采用其它设备存储,可以实现 CacheStore 接口。</p>
|
||
|
||
<p>不过需要特别注意不适用缓存或者需要手动编码的地方:</p>
|
||
|
||
<ul>
|
||
<li><p>当使用了 <code>Distinct</code>,<code>Having</code>,<code>GroupBy</code> 方法将不会使用缓存</p></li>
|
||
|
||
<li><p>在 <code>Get</code> 或者 <code>Find</code> 时使用了 <code>Cols</code>,<code>Omit</code> 方法,则在开启缓存后此方法无效,系统仍旧会取出这个表中的所有字段。</p></li>
|
||
|
||
<li><p>在使用 Exec 方法执行了方法之后,可能会导致缓存与数据库不一致的地方。因此如果启用缓存,尽量避免使用 Exec。如果必须使用,则需要在使用了 Exec 之后调用 ClearCache 手动做缓存清除的工作。比如:</p>
|
||
<pre><code>engine.Exec("update user set name = ? where id = ?", "xlw", 1)
|
||
engine.ClearCache(new(User))
|
||
</code></pre></li>
|
||
</ul>
|
||
|
||
<h2>第六种武器:乐观锁</h2>
|
||
|
||
<p>很多从事金融软件的朋友都会关注这个问题,乐观锁普遍的在 Java,.Net的ORM框架中被实现。使用如下:</p>
|
||
|
||
<p>要使用乐观锁,需要使用 version 标记</p>
|
||
<pre><code>type User struct {
|
||
Id int64
|
||
Name string
|
||
Version int `xorm:"version"`
|
||
}
|
||
</code></pre>
|
||
|
||
<p>在 Insert 时,version 标记的字段将会被设置为 1,在 Update 时,Update 的内容必须包含 version 原来的值。</p>
|
||
<pre><code>var user User
|
||
engine.Id(1).Get(&user)
|
||
// SELECT * FROM user WHERE id = ?
|
||
engine.Id(1).Update(&user)
|
||
// UPDATE user SET ..., version = version + 1 WHERE id = ? AND version = ?
|
||
</code></pre>
|
||
|
||
<h2>第七种武器:数据库反转</h2>
|
||
|
||
<p>现在是不是有点冲动想开始用<a href="https://github.com/lunny/xorm"> xorm</a> 来管理你的数据库了呢?可以已有数据库怎么处理呢?要重写很多代码吗?</p>
|
||
|
||
<p>还在羡慕 Java 的 Hibernate 可以通过数据库自动生成 Bean 和 DAO 代码吗?现在 Go 也有了,而且支持生成 c++ 代码,欢呼吧。</p>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 自带了一个命令行工具,当前提供了反转命令。通过执行</p>
|
||
<pre><code>go install github.com/lunny/xorm/xorm
|
||
</code></pre>
|
||
|
||
<p>即可安装该工具。安装完成后,我们就可以来使用 <code>xorm</code> 这个命令了。<a href="https://github.com/lunny/xorm">xorm</a> 的反转命令当前支持 sqlite3,mysql,postgres 以及 mssql 四种数据库。命令执行如下:</p>
|
||
<pre><code>xorm reverse sqite3 test.db templates/goxorm
|
||
</code></pre>
|
||
|
||
<p>其中,第二和第三个参数为数据库驱动的连接参数,最后一个参数为模板路径。对的,你可以在这个模板的基础上进行修改,最后也许你的大部分 models 代码都可以自动生成。我的一个同事已经通过这个工具,生成了一个 Mysql 数据库的 C++ 操作代码。</p>
|
||
|
||
<h2>最后</h2>
|
||
|
||
<p><a href="https://github.com/lunny/xorm">xorm</a> 项目已经发展了半年多,目前我们已经有两位长期的贡献者,很多同学也给出了各种方面的建议和修正。目前 <a href="https://github.com/lunny/xorm">xorm</a> 还在不断的成长,欢迎大家多提意见建议贡献代码。</p>
|
||
]]></description></item></channel></rss> |