Tag站长知识库:分享、传递知识使我们更快乐,更幸福,更和谐!
最近更新热门图文热门文章全站推荐Tag标签网站地图
本节将对 db/sql 官方标准库作一些简单分析,并介绍一些应用比较广泛的开源 ORM 和 SQL Builder。并从企业级应用开发和公司架构的角度来分析哪种技术栈对于现代的企业级应用更为合适。
import "database/sql"
import _ "github.com/go-sql-driver/mysql"
db, err := sql.Open("mysql", "user:password@/dbname")
import _ "github.com/go-sql-driver/mysql"
func init() {
sql.Register("mysql", &MySQLDriver{})
}
type Driver interface {
Open(name string) (Conn, error)
}
type Conn interface {
Prepare(query string) (Stmt, error)
Close() error
Begin() (Tx, error)
}
package mainimport ( "database/sql" _ "github.com/go-sql-driver/mysql")func main() { // db 是一个 sql.DB 类型的对象 // 该对象线程安全,且内部已包含了一个连接池 // 连接池的选项可以在 sql.DB 的方法中设置,这里为了简单省略了 db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/hello") if err != nil { log.Fatal(err) } defer db.Close() var ( id int name string ) rows, err := db.Query("select id, name from users where id = ?", 1) if err != nil { log.Fatal(err) } defer rows.Close() // 必须要把 rows 里的内容读完,或者显式调用 Close() 方法, // 否则在 defer 的 rows.Close() 执行之前,连接永远不会释放 for rows.Next() { err := rows.Scan(&id, &name) if err != nil { log.Fatal(err) } log.Println(id, name) } err = rows.Err() if err != nil { log.Fatal(err) }}如果大家想了解官方这个 database/sql 库更加详细的用法的话,可以参考 http://go-database-sql.org/ 。
>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
# 伪代码
shopList := []
for product in productList {
shopList = append(shopList, product.GetShop)
}
o := orm.NewOrm()
num, err := o.QueryTable("cardgroup").Filter("Cards__Card__Name", cardName).All(&cardgroups)
num, err := o.QueryTable("cardgroup").Filter("Cards__Card__Name", cardName).All(&cardgroups)
可以看得出来这个 Filter 是有表 join 的操作么?当然了,有深入使用经验的用户还是会觉得这是在吹毛求疵。但这样的分析想证明的是,ORM 想从设计上隐去太多的细节。而方便的代价是其背后的运行完全失控。这样的项目在经过几任维护人员之后,将变得面目全非,难以维护。where := map[string]interface{} {
"order_id > ?" : 0,
"customer_id != ?" : 0,
}
limit := []int{0,100}
orderBy := []string{"id asc", "create_time desc"}
orders := orderModel.GetList(where, limit, orderBy)
where := map[string]interface{} {
"product_id = ?" : 10,
"user_id = ?" : 1232,
}
if order_id != 0 {
where["order_id = ?"] = order_id
}
res, err := historyModel.GetList(where, limit, orderBy)
const ( getAllByProductIDAndCustomerID = `select * from p_orders where product_id in (:product_id) and customer_id=:customer_id`)// GetAllByProductIDAndCustomerID// @param driver_id// @param rate_date// @return []Order, errorfunc GetAllByProductIDAndCustomerID(ctx context.Context, productIDs []uint64, customerID uint64) ([]Order, error) { var orderList []Order params := map[string]interface{}{ "product_id" : productIDs, "customer_id": customerID, } // getAllByProductIDAndCustomerID 是 const 类型的 sql 字符串 sql, args, err := sqlutil.Named(getAllByProductIDAndCustomerID, params) if err != nil { return nil, err } err = dao.QueryList(ctx, sqldbInstance, sql, args, &orderList) if err != nil { return nil, err } return orderList, err}像这样的代码,在上线之前把 DAO 层的变更集的 const 部分直接拿给 DBA 来进行审核,就比较方便了。代码中的 sqlutil.Named 是类似于 sqlx 中的 Named 函数,同时支持 where 表达式中的比较操作符和 in。
编程帮,一个分享编程知识的公众号。跟着站长一起学习,每天都有进步。
通俗易懂,深入浅出,一篇文章只讲一个知识点。
文章不深奥,不需要钻研,在公交、在地铁、在厕所都可以阅读,随时随地涨姿势。
文章不涉及代码,不烧脑细胞,人人都可以学习。
当你决定关注「编程帮」,你已然超越了90%的程序员!