实现ORM框架的实例

实现一个 ORM 框架,思路:

  1. 映射结构体和数据库表通过反射获取结构体的字段信息,根据数据库表的列名和结构体字段名的映射关系,将结构体和数据库表进行映射。可以通过 struct tag 实现自定义映射关系。

  1. CRUD 操作根据映射关系,可以实现基本的 CRUD 操作。通过反射获取结构体的字段值,动态生成 SQL 语句执行数据库操作。

  1. 数据库事务ORM 框架应该支持数据库事务。可以使用 Go 语言自带的事务处理机制实现。

  1. 数据库连接池ORM 框架应该支持数据库连接池。可以使用 Go 语言自带的数据库连接池实现。

下面是一个通过反射和接口实现的简单的ORM框架示例,代码如下:

package main

import (
	"database/sql"
	"fmt"
	"log"
	"reflect"

	_ "github.com/go-sql-driver/mysql"
)

type Model struct {
	ID int`orm:"id"`
}

type User struct {
	Model
	Name string`orm:"name"`
	Age  int`orm:"age"`
}

func(u *User) TableName() string {
	return"users"
}

type ORM interface {
	Insert() error
	Query() error
	Update() error
	Delete() error
}

type DB struct {
	*sql.DB
}

func (db *DB) Insert(obj interface{}) error {
	model := reflect.ValueOf(obj).Elem()
	tableName := model.MethodByName("TableName").Call(nil)[0].String()
	fields := make([]string, 0)
	values := make([]interface{}, 0)
	for i := 0; i < model.NumField(); i++ {
		field := model.Type().Field(i)
		if _, ok := field.Tag.Lookup("orm"); ok {
			fields = append(fields, field.Tag.Get("orm"))
			values = append(values, model.Field(i).Interface())
		}
	}
	stmt := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", tableName, fields[0], "?"+strings.Repeat(",?", len(fields)-1))
	result, err := db.Exec(stmt, values...)
	if err != nil {
		return err
	}
	lastInsertID, err := result.LastInsertId()
	if err != nil {
		return err
	}
	model.FieldByName("ID").SetInt(lastInsertID)
	returnnil
}

func (db *DB) Query(obj interface{}) error {
	model := reflect.ValueOf(obj).Elem()
	tableName := model.MethodByName("TableName").Call(nil)[0].String()
	fields := make([]string, 0)
	for i := 0; i < model.NumField(); i++ {
		field := model.Type().Field(i)
		if _, ok := field.Tag.Lookup("orm"); ok {
			fields = append(fields, field.Tag.Get("orm"))
		}
	}
	stmt := fmt.Sprintf("SELECT %s FROM %s WHERE id=?", strings.Join(fields, ","), tableName)
	row := db.QueryRow(stmt, model.FieldByName("ID").Int())
	values := make([]interface{}, 0)
	for i := 0; i < len(fields); i++ {
		values = append(values, model.FieldByName(fields[i]).Addr().Interface())
	}
	err := row.Scan(values...)
	if err != nil {
		return err
	}
	returnnil
}

func (db *DB) Update(obj interface{}) error {
	model := reflect.ValueOf(obj).Elem()
	tableName := model.MethodByName("TableName").Call(nil)[0].String()
	fields := make([]string, 0)
	values := make([]interface{}, 0)
	for i := 0; i < model.NumField(); i++ {
		field := model.Type().Field(i)
		if _, ok := field.Tag.Lookup("orm"); ok {
			fields = append(fields, field.Tag.Get("orm"))
			values = append(values, model.Field(i).Interface())
		}
	}
	values = append(values, model.FieldByName("ID").Int())
	stmt := fmt.Sprintf("UPDATE %s SET %s WHERE id=?", tableName, fields[0]+"=?"+strings.Repeat(","+fields[0]+"=?", len(fields)-1))
	_, err := db.Exec(stmt, values...)
	if err != nil {
		return err
	}
	returnnil
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值