| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184 |
- package services
- import (
- // "encoding/json"
- "errors"
- "fmt"
- "math"
- "reflect"
- "runtime"
- "strings"
- "time"
- "easydo-echo_win7/models"
- "easydo-echo_win7/utils"
- "database/sql"
- "github.com/jmoiron/sqlx"
- )
- // DBClient 数据库客户端结构体
- type DBClient struct {
- db *sqlx.DB
- log bool
- }
- // NewDBClient 创建新的数据库客户端
- func NewDBClient(db *sqlx.DB, log bool) *DBClient {
- build_time := time.Now()
- build_time_str := build_time.Format(time.DateTime)
- fmt.Printf("%s 数据库的客户端初始化成功\n", build_time_str)
- return &DBClient{db: db, log: log}
- }
- // PageResult 分页查询结果
- type PageResult struct {
- Total int64 `json:"total"`
- Records interface{} `json:"records"`
- }
- // TransactionFunc 事务处理函数类型
- type TransactionFunc func(tx *sqlx.Tx) error
- // GetJdbcPage 单表分页查询
- func (c *DBClient) GetJdbcPage(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (*PageResult, error) {
- // 获取表名
- tableName := utils.GetTableName(clazz)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- if len(fields) == 0 {
- return nil, errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- // 构建查询条件
- whereSQL, err := utils.BuildWhereCondition(params)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- // 执行查询
- var querySQL string
- var total int64
- if len(conn) > 0 {
- // 使用事务连接
- tx := conn[0]
- // 查询数据列表
- querySQL = fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- rows, err := tx.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- // 将结果映射到结构体列表
- resultList, err := c.scanRowsToList(rows, clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- // 查询总数
- paramsCopy := make(map[string]interface{})
- for k, v := range params {
- if k != "current" && k != "size" && k != "orderBy" {
- paramsCopy[k] = v
- }
- }
- countSQL, err := utils.BuildWhereCondition(paramsCopy)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- querySQL = fmt.Sprintf("SELECT COUNT(1) FROM %s%s", tableName, countSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- err = tx.Get(&total, querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- return &PageResult{
- Total: total,
- Records: resultList,
- }, nil
- } else {
- // 使用普通连接
- querySQL = fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- rows, err := c.db.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- resultList, err := c.scanRowsToList(rows, clazz)
- if err != nil {
- return nil, err
- }
- paramsCopy := make(map[string]interface{})
- for k, v := range params {
- if k != "current" && k != "size" && k != "orderBy" {
- paramsCopy[k] = v
- }
- }
- countSQL, err := utils.BuildWhereCondition(paramsCopy)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- querySQL = fmt.Sprintf("SELECT COUNT(1) FROM %s%s", tableName, countSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- err = c.db.Get(&total, querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- return &PageResult{
- Total: total,
- Records: resultList,
- }, nil
- }
- }
- // GetJdbcPageBySql 使用自定义SQL进行分页查询
- func (c *DBClient) GetJdbcPageBySql(params map[string]interface{}, viewSQL string, clazz interface{}, conn ...*sqlx.Tx) (*PageResult, error) {
- var total int64
- var resultList interface{}
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- if len(fields) == 0 {
- return nil, errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- // 替换原SQL中的SELECT *为SELECT 字段列表
- lowerSQL := strings.ToLower(viewSQL)
- if strings.Contains(lowerSQL, "select *") {
- // 替换SELECT *为SELECT 字段列表
- viewSQL = strings.Replace(lowerSQL, "select *", fmt.Sprintf("select %s", fieldsStr), 1)
- // 保持原SQL的大小写风格
- parts := strings.SplitN(viewSQL, " ", 2)
- if len(parts) == 2 {
- viewSQL = fmt.Sprintf("SELECT %s %s", fieldsStr, parts[1])
- }
- }
- // 构建查询条件
- whereSQL, err := utils.BuildWhereCondition(params)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- querySQL := fmt.Sprintf("%s%s", viewSQL, whereSQL)
- querySQL = strings.ReplaceAll(querySQL, "`", "")
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- if len(conn) > 0 {
- tx := conn[0]
- rows, err := tx.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- resultList, err = c.scanRowsToList(rows, clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- // 构建COUNT SQL
- paramsCopy := make(map[string]interface{})
- for k, v := range params {
- if k != "current" && k != "size" && k != "orderBy" {
- paramsCopy[k] = v
- }
- }
- countSQL, err := utils.BuildWhereCondition(paramsCopy)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- // 转换视图SQL为COUNT SQL
- fromIndex := strings.Index(strings.ToLower(viewSQL), "from")
- if fromIndex == -1 {
- return nil, errors.New("invalid SQL: no FROM clause found")
- }
- countQuerySQL := fmt.Sprintf("SELECT COUNT(1) %s%s", viewSQL[fromIndex:], countSQL)
- countQuerySQL = strings.ReplaceAll(countQuerySQL, "`", "")
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, countQuerySQL)
- }
- err = tx.Get(&total, countQuerySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- } else {
- rows, err := c.db.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- resultList, err = c.scanRowsToList(rows, clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- paramsCopy := make(map[string]interface{})
- for k, v := range params {
- if k != "current" && k != "size" && k != "orderBy" {
- paramsCopy[k] = v
- }
- }
- countSQL, err := utils.BuildWhereCondition(paramsCopy)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- fromIndex := strings.Index(strings.ToLower(viewSQL), "from")
- if fromIndex == -1 {
- return nil, errors.New("invalid SQL: no FROM clause found")
- }
- countQuerySQL := fmt.Sprintf("SELECT COUNT(1) %s%s", viewSQL[fromIndex:], countSQL)
- countQuerySQL = strings.ReplaceAll(countQuerySQL, "`", "")
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, countQuerySQL)
- }
- err = c.db.Get(&total, countQuerySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- }
- return &PageResult{
- Total: total,
- Records: resultList,
- }, nil
- }
- // GetJdbcList 单表查询列表
- func (c *DBClient) GetJdbcList(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (interface{}, error) {
- tableName := utils.GetTableName(clazz)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(clazz)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- if len(fields) == 0 {
- return nil, errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- whereSQL, err := utils.BuildWhereCondition(params)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- querySQL := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- if len(conn) > 0 {
- tx := conn[0]
- rows, err := tx.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- return c.scanRowsToList(rows, clazz)
- } else {
- rows, err := c.db.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- return c.scanRowsToList(rows, clazz)
- }
- }
- // GetJdbcListByObject 根据对象查询列表
- func (c *DBClient) GetJdbcListByObject(obj interface{}, conn ...*sqlx.Tx) (interface{}, error) {
- // 将对象转换为map
- paramMap, err := c.objectToMap(obj)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- tableName := utils.GetTableName(obj)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(obj)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- if len(fields) == 0 {
- return nil, errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- whereSQL, err := utils.BuildWhereCondition(paramMap)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- querySQL := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
- }
- if len(conn) > 0 {
- tx := conn[0]
- rows, err := tx.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- return c.scanRowsToList(rows, obj)
- } else {
- rows, err := c.db.Queryx(querySQL)
- if err != nil {
- println(err.Error())
- return nil, err
- }
- defer rows.Close()
- return c.scanRowsToList(rows, obj)
- }
- }
- // GetJdbcModel 查询单个模型(根据对象非空字段)
- func (c *DBClient) GetJdbcModel(obj interface{}, conn ...*sqlx.Tx) error {
- // 获取表名
- tableName := utils.GetTableName(obj)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(obj)
- if err != nil {
- println(err.Error())
- return err
- }
- if len(fields) == 0 {
- return errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- // 将对象转换为map作为查询条件
- whereMap, err := c.objectToMap(obj)
- if err != nil {
- println(err.Error())
- return err
- }
- // 构建WHERE条件
- whereSQL, err := utils.BuildWhereCondition(whereMap)
- if err != nil {
- println(err.Error())
- return err
- }
- sqlStr := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s queryMSQL======>%s\n", build_time_str, sqlStr)
- }
- if len(conn) > 0 {
- tx := conn[0]
- row := tx.QueryRowx(sqlStr)
- return c.scanRowToModel(row, obj)
- } else {
- row := c.db.QueryRowx(sqlStr)
- return c.scanRowToModel(row, obj)
- }
- }
- // GetJdbcModelByMap 根据参数map查询单个模型
- func (c *DBClient) GetJdbcModelByMap(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) error {
- // 获取表名
- tableName := utils.GetTableName(clazz)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(clazz)
- if err != nil {
- println(err.Error())
- return err
- }
- if len(fields) == 0 {
- return errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- // 构建WHERE条件
- whereSQL, err := utils.BuildWhereCondition(params)
- if err != nil {
- println(err.Error())
- return err
- }
- sqlStr := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s queryMMSQL======>%s\n", build_time_str, sqlStr)
- }
- if len(conn) > 0 {
- tx := conn[0]
- row := tx.QueryRowx(sqlStr)
- return c.scanRowToModel(row, clazz)
- } else {
- row := c.db.QueryRowx(sqlStr)
- return c.scanRowToModel(row, clazz)
- }
- }
- // GetJdbcModelById 根据ID查询单个模型
- func (c *DBClient) GetJdbcModelById(obj interface{}, conn ...*sqlx.Tx) error {
- // 获取表名
- tableName := utils.GetTableName(obj)
- // 获取结构体字段列表
- fields, err := c.getStructDBFields(obj)
- if err != nil {
- println(err.Error())
- return err
- }
- if len(fields) == 0 {
- return errors.New("no db fields found in struct")
- }
- // 构建字段列表字符串
- fieldsStr := strings.Join(fields, ", ")
- // 获取ID字段名(假设为"id")
- idField := "id"
- // 尝试从结构体中获取ID字段
- v := reflect.ValueOf(obj)
- if v.Kind() == reflect.Ptr {
- v = v.Elem()
- }
- t := v.Type()
- for i := 0; i < t.NumField(); i++ {
- field := t.Field(i)
- dbTag := field.Tag.Get("db")
- jsonTag := field.Tag.Get("json")
- fieldName := strings.ToLower(field.Name)
- // 尝试找到ID字段
- if dbTag == "id" || jsonTag == "id" || fieldName == "id" {
- if dbTag != "" && dbTag != "-" {
- idField = dbTag
- }
- break
- }
- }
- // 获取ID值
- var idValue interface{}
- idFieldFound := false
- for i := 0; i < v.NumField(); i++ {
- field := t.Field(i)
- fieldValue := v.Field(i)
- is_format:=formatSqlValue(field.Name,fieldValue)
- if is_format {
- continue
- }
- dbTag := field.Tag.Get("db")
- jsonTag := field.Tag.Get("json")
- fieldName := strings.ToLower(field.Name)
- if dbTag == "id" || jsonTag == "id" || fieldName == "id" {
- idValue = fieldValue.Interface()
- idFieldFound = true
- continue
- }
- }
- if !idFieldFound || isEmptyValue(reflect.ValueOf(idValue)) {
- return errors.New("id field not found or is empty")
- }
- sqlStr := fmt.Sprintf("SELECT %s FROM %s WHERE %s = ?", fieldsStr, tableName, idField)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s queryIDSQL======>%s %s\n", build_time_str, sqlStr, utils.FormatToString(idValue))
- }
- if len(conn) > 0 {
- tx := conn[0]
- row := tx.QueryRowx(sqlStr, idValue)
- return c.scanRowToModel(row, obj)
- } else {
- row := c.db.QueryRowx(sqlStr, idValue)
- return c.scanRowToModel(row, obj)
- }
- }
- func (c *DBClient) JdbcInsert(model interface{}, conn ...*sqlx.Tx) error {
- // 1. 校验model必须是指针(否则无法赋值自增ID)
- val := reflect.ValueOf(model)
- if val.Kind() != reflect.Ptr || val.IsNil() {
- return fmt.Errorf("model必须是非空指针类型")
- }
- modelVal := val.Elem() // 解引用指针,获取实际结构体值
- // 2. 生成插入SQL(保留原有逻辑)
- uuid := utils.GenerateUUID()
- sqlStr, err := utils.FormatInsertSql(model, uuid)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s insertSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- return fmt.Errorf("生成插入SQL失败: %w", err)
- }
- // 3. 执行INSERT并获取自增ID
- var lastInsertID int64
- if len(conn) > 0 {
- // 事务场景
- tx := conn[0]
- result, err := tx.Exec(sqlStr)
- if err != nil {
- return fmt.Errorf("事务执行INSERT失败: %w", err)
- }
- // 检查受影响行数
- rowsAffected, err := result.RowsAffected()
- if err != nil {
- // 某些数据库驱动或特定查询可能不支持RowsAffected
- // 但这通常发生在SELECT等语句上,INSERT/UPDATE/DELETE通常支持
- return fmt.Errorf("警告:无法获取受影响行数(可能不影响业务): %w", err)
- }
- // 对于INSERT,通常期望至少插入1行
- if rowsAffected == 0 {
- return fmt.Errorf("操作未生效(受影响行数为0),请检查数据或约束。SQL: %s", sqlStr)
- }
- lastInsertID, err = result.LastInsertId()
- if err != nil {
- return fmt.Errorf("获取事务自增ID失败: %w", err)
- }
- } else {
- // 非事务场景
- result, err := c.db.Exec(sqlStr)
- if err != nil {
- return fmt.Errorf("执行INSERT失败: %w", err)
- }
- lastInsertID, err = result.LastInsertId()
- if err != nil {
- fmt.Println("获取自增ID失败: %w", err)
- return nil
- }
- }
- // 4. 反射赋值自增ID到model的ID字段
- if err := setAutoIncrementID(modelVal, lastInsertID, uuid); err != nil {
- // 仅打印警告,不中断流程(避免非自增表场景报错)
- fmt.Printf("自增ID赋值失败(非自增表可忽略): %v\n", err)
- }
- return nil
- }
- // setAutoIncrementID 反射给model赋值自增ID
- // modelVal: 结构体的reflect.Value(已解引用指针)
- // lastInsertID: 数据库返回的自增ID
- func setAutoIncrementID(modelVal reflect.Value, lastInsertID int64, uuid string) error {
- // 遍历结构体字段,找到自增ID字段(db:"id")
- for i := 0; i < modelVal.NumField(); i++ {
- field := modelVal.Type().Field(i) // 字段元信息
- fieldVal := modelVal.Field(i) // 字段值
- // 解析db标签,判断是否是ID字段(支持如 db:"id,primarykey" 这类带额外参数的标签)
- dbTag := field.Tag.Get("db")
- if dbTag == "" {
- continue
- }
- tagParts := strings.Split(dbTag, ",")
- if tagParts[0] != "id" {
- continue
- }
- // 处理指针类型
- if fieldVal.Kind() == reflect.Ptr {
- // 指针为空,需要创建新的实例
- if fieldVal.IsNil() {
- // 根据指针指向的类型创建新值
- elemType := fieldVal.Type().Elem()
- newVal := reflect.New(elemType)
- fieldVal.Set(newVal)
- }
- // 获取指针指向的值
- elem := fieldVal.Elem()
- // 根据指针指向的实际类型赋值
- return setValueByKind(elem, lastInsertID, field.Name, uuid)
- }
- // 非指针类型,检查是否可设置
- if !fieldVal.CanSet() {
- continue
- }
- // 根据字段类型赋值自增ID
- return setValueByKind(fieldVal, lastInsertID, field.Name, uuid)
- }
- return fmt.Errorf("未找到可赋值的自增ID字段(需包含 db:\"id\" 标签且为整数类型)")
- }
- // setValueByKind 根据不同的类型设置值
- func setValueByKind(fieldVal reflect.Value, lastInsertID int64, fieldName string, uuid string) error {
- // 根据字段类型赋值自增ID,并校验范围
- switch fieldVal.Kind() {
- case reflect.Int, reflect.Int64:
- fieldVal.SetInt(lastInsertID)
- case reflect.Uint, reflect.Uint64:
- fieldVal.SetUint(uint64(lastInsertID))
- case reflect.Int8:
- if lastInsertID < math.MinInt8 || lastInsertID > math.MaxInt8 {
- return fmt.Errorf("自增ID %d 超出int8字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt8, math.MaxInt8)
- }
- fieldVal.SetInt(lastInsertID)
- case reflect.Int16:
- if lastInsertID < math.MinInt16 || lastInsertID > math.MaxInt16 {
- return fmt.Errorf("自增ID %d 超出int16字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt16, math.MaxInt16)
- }
- fieldVal.SetInt(lastInsertID)
- case reflect.Int32:
- if lastInsertID < math.MinInt32 || lastInsertID > math.MaxInt32 {
- return fmt.Errorf("自增ID %d 超出int32字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt32, math.MaxInt32)
- }
- fieldVal.SetInt(lastInsertID)
- case reflect.Uint8:
- if uint64(lastInsertID) > math.MaxUint8 {
- return fmt.Errorf("自增ID %d 超出uint8字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint8)
- }
- fieldVal.SetUint(uint64(lastInsertID))
- case reflect.Uint16:
- if uint64(lastInsertID) > math.MaxUint16 {
- return fmt.Errorf("自增ID %d 超出uint16字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint16)
- }
- fieldVal.SetUint(uint64(lastInsertID))
- case reflect.Uint32:
- if uint64(lastInsertID) > math.MaxUint32 {
- return fmt.Errorf("自增ID %d 超出uint32字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint32)
- }
- fieldVal.SetUint(uint64(lastInsertID))
- case reflect.String:
- fieldVal.SetString(string(uuid))
- default:
- return fmt.Errorf("字段 %s 类型 %s 不支持自增ID赋值", fieldName, fieldVal.Kind())
- }
- return nil
- }
- // JdbcUpdate 更新数据
- func (c *DBClient) JdbcUpdate(model interface{}, whereMap map[string]interface{}, conn ...*sqlx.Tx) error {
- sqlStr, err := utils.FormatUpdateSql(model, whereMap)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s updateSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- println(err.Error())
- return err
- }
- if len(conn) > 0 {
- tx := conn[0]
- _, err := tx.Exec(sqlStr)
- if err != nil {
- return fmt.Errorf("事务执行UPDATE失败: %w", err)
- }
- return nil
- } else {
- _, err := c.db.Exec(sqlStr)
- if err != nil {
- return fmt.Errorf("执行UPDATE失败: %w", err)
- }
- return nil
- }
- }
- // JdbcUpdateById 根据ID更新数据
- func (c *DBClient) JdbcUpdateById(model interface{}, conn ...*sqlx.Tx) error {
- sqlStr, err := utils.FormatUpdateByIdSql(model)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s updateSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- println(err.Error())
- return err
- }
- if len(conn) > 0 {
- tx := conn[0]
- _, err := tx.Exec(sqlStr)
- return err
- } else {
- _, err := c.db.Exec(sqlStr)
- return err
- }
- }
- // JdbcRemoveById 根据ID删除数据
- func (c *DBClient) JdbcRemoveById(model interface{}, conn ...*sqlx.Tx) error {
- sqlStr, err := utils.FormatRemoveByIdSql(model)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s removeSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- return err
- }
- if len(conn) > 0 {
- tx := conn[0]
- _, err := tx.Exec(sqlStr)
- return err
- } else {
- _, err := c.db.Exec(sqlStr)
- return err
- }
- }
- // JdbcRemove 根据条件删除数据
- func (c *DBClient) JdbcRemove(model interface{}, conn ...*sqlx.Tx) error {
- sqlStr, err := utils.FormatRemoveSql(model)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s removeSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- println(err.Error())
- return err
- }
- if len(conn) > 0 {
- tx := conn[0]
- _, err := tx.Exec(sqlStr)
- return err
- } else {
- _, err := c.db.Exec(sqlStr)
- return err
- }
- }
- // GetJdbcCount 统计数量(根据对象)
- func (c *DBClient) GetJdbcCount(obj interface{}, conn ...*sqlx.Tx) (int64, error) {
- sqlStr, err := utils.FormatSelectCountSql(obj)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s countSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- println(err.Error())
- return 0, err
- }
- var count int64
- if len(conn) > 0 {
- tx := conn[0]
- row := tx.QueryRowx(sqlStr)
- err = row.Scan(&count)
- } else {
- row := c.db.QueryRowx(sqlStr)
- err = row.Scan(&count)
- }
- if err != nil {
- println(err.Error())
- return 0, err
- }
- return count, nil
- }
- // GetJdbcCountByMap 统计数量(根据参数map)
- func (c *DBClient) GetJdbcCountByMap(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (int64, error) {
- sqlStr, err := utils.FormatSelectCountSqlByMap(clazz, params)
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s countSQL======>%s\n", build_time_str, sqlStr)
- }
- if err != nil {
- println(err.Error())
- return 0, err
- }
- var count int64
- if len(conn) > 0 {
- tx := conn[0]
- row := tx.QueryRowx(sqlStr)
- err = row.Scan(&count)
- } else {
- row := c.db.QueryRowx(sqlStr)
- err = row.Scan(&count)
- }
- if err != nil {
- println(err.Error())
- return 0, err
- }
- return count, nil
- }
- func (c *DBClient) GetMinioFile(obj interface{}, conn ...*sqlx.Tx) ([]models.MinioFile, error) {
- tableName := utils.GetTableName(obj)
- id, err := utils.GetIdValue(obj)
- if err != nil {
- return []models.MinioFile{}, err
- }
- file := new(models.MinioFile)
- file.RefId = &id
- file.RefType = &tableName
- result, err := c.GetJdbcListByObject(file)
- if err != nil {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s SQL执行失败: %v\n", build_time_str, err)
- return []models.MinioFile{}, fmt.Errorf("SQL执行失败: %v", err)
- }
- list := utils.ConvertInterface[[]models.MinioFile](result)
- return list, nil
- }
- // 辅助方法
- // scanRowsToList 将查询结果扫描到结构体列表
- func (c *DBClient) scanRowsToList(rows *sqlx.Rows, clazz interface{}) (interface{}, error) {
- // 获取类型信息
- var elemType reflect.Type
- // 处理指针类型
- rt := reflect.TypeOf(clazz)
- if rt.Kind() == reflect.Ptr {
- rt = rt.Elem()
- }
- // 如果是reflect.Type类型
- if rt.Kind() == reflect.Struct {
- elemType = rt
- } else {
- // 尝试从接口获取类型
- elemType = reflect.TypeOf(clazz)
- if elemType.Kind() == reflect.Ptr {
- elemType = elemType.Elem()
- }
- }
- // 创建切片
- sliceType := reflect.SliceOf(elemType)
- resultSlice := reflect.New(sliceType).Elem()
- for rows.Next() {
- elem := reflect.New(elemType).Interface()
- err := rows.StructScan(elem)
- if err != nil {
- return nil, err
- }
- elemValue := reflect.ValueOf(elem).Elem()
- for i := 0; i < elemValue.NumField(); i++ {
- field := elemValue.Field(i)
- fieldType := elemType.Field(i)
- // 检查字段名和类型
- fieldName := fieldType.Name
- is_format:=formatSqlValue(fieldName,field)
- if is_format {
- continue
- }
- }
- resultSlice = reflect.Append(resultSlice, reflect.ValueOf(elem).Elem())
- }
- return resultSlice.Interface(), nil
- }
- // scanRowToModel 将单行查询结果扫描到结构体
- func (c *DBClient) scanRowToModel(row *sqlx.Row, clazz interface{}) error {
- err := row.StructScan(clazz)
- if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
- if c.log {
- build_time_str := time.Now().Format(time.DateTime)
- fmt.Printf("%s scanRowToModel======>%s\n", build_time_str, "sql: no rows in result set")
- }
- return nil
- }
- return err
- }
- // 获取结构体值
- elemValue := reflect.ValueOf(clazz)
- if elemValue.Kind() != reflect.Ptr {
- return fmt.Errorf("clazz must be a pointer")
- }
- elemValue = elemValue.Elem()
- if elemValue.Kind() != reflect.Struct {
- return fmt.Errorf("clazz must point to a struct")
- }
- elemType := elemValue.Type()
- // 遍历结构体字段
- for i := 0; i < elemValue.NumField(); i++ {
- field := elemValue.Field(i)
- fieldType := elemType.Field(i)
- // 检查字段名和类型
- fieldName := fieldType.Name
- is_format:=formatSqlValue(fieldName,field)
- if is_format {
- continue
- }
- }
- return nil
- }
- func formatSqlValue(fieldName string,fieldValue reflect.Value) bool {
- // 检查字段名和类型
- is_format := true
- if strings.HasSuffix(fieldName, "Time") && fieldValue.Type() == reflect.TypeOf((*string)(nil)) {
- if fieldValue.IsValid() && !fieldValue.IsNil() {
- fieldValue_t := utils.FormatToString(fieldValue.Interface())
- t, err := time.Parse(time.RFC3339, fieldValue_t)
- if err != nil {
- build_time_str := time.Now().Format(time.DateTime)
- _, file, line, _ := runtime.Caller(0)
- fmt.Printf("%s err %s %d======> %v\n", build_time_str, file, line, err)
- return is_format
- }
- strPtr := new(string)
- t_str := t.Format(time.DateTime)
- strPtr = &t_str
- fieldValue.Set(reflect.ValueOf(strPtr))
- return is_format
- }
- } else if strings.HasSuffix(fieldName, "Date") && fieldValue.Type() == reflect.TypeOf((*string)(nil)) {
- if fieldValue.IsValid() && !fieldValue.IsNil() {
- fieldValue_t := utils.FormatToString(fieldValue.Interface())
- if len(fieldValue_t) > 10 {
- t_str := fieldValue_t[:10]
- strPtr := new(string)
- strPtr = &t_str
- fieldValue.Set(reflect.ValueOf(strPtr))
- }
- return is_format
- }
- }
- return false
- }
- func (c *DBClient) ScanRowToModel(row *sqlx.Row, clazz interface{}) error {
- return c.scanRowToModel(row, clazz)
- }
- func (c *DBClient) ScanRowToList(rows *sqlx.Rows, clazz interface{}) (interface{}, error) {
- return c.scanRowsToList(rows, clazz)
- }
- // objectToMap 将对象转换为map[string]interface{}
- func (c *DBClient) objectToMap(obj interface{}) (map[string]interface{}, error) {
- result := make(map[string]interface{})
- // 获取对象类型和值
- objType := reflect.TypeOf(obj)
- objValue := reflect.ValueOf(obj)
- // 如果是指针,获取指向的值
- if objType.Kind() == reflect.Ptr {
- objType = objType.Elem()
- objValue = objValue.Elem()
- }
- // 检查是否是结构体
- if objType.Kind() != reflect.Struct {
- return nil, errors.New("参数必须是结构体或结构体指针")
- }
- // 遍历结构体字段
- for i := 0; i < objType.NumField(); i++ {
- field := objType.Field(i)
- fieldValue := objValue.Field(i)
- // 跳过不可导出的字段
- if !fieldValue.CanInterface() {
- continue
- }
- // 检查字段值是否为空(零值)
- if isEmptyValue(fieldValue) {
- continue
- }
- // 获取db标签作为字段名
- dbTag := field.Tag.Get("db")
- if dbTag == "" || dbTag == "-" {
- continue
- }
- // 添加字段到map
- result[dbTag] = fieldValue.Interface()
- }
- return result, nil
- }
- // getStructDBFields 获取结构体的db标签字段列表
- func (c *DBClient) getStructDBFields(obj interface{}) ([]string, error) {
- var fields []string
- // 获取对象类型
- objType := reflect.TypeOf(obj)
- if objType.Kind() == reflect.Ptr {
- objType = objType.Elem()
- }
- // 检查是否是结构体
- if objType.Kind() != reflect.Struct {
- return nil, errors.New("参数必须是结构体或结构体指针")
- }
- // 遍历结构体字段
- for i := 0; i < objType.NumField(); i++ {
- field := objType.Field(i)
- // 获取db标签
- dbTag := field.Tag.Get("db")
- if dbTag != "" && dbTag != "-" {
- // 使用反引号包裹字段名,防止关键字冲突
- fields = append(fields, fmt.Sprintf("`%s`", dbTag))
- }
- }
- if len(fields) == 0 {
- // 如果没有db标签,尝试使用字段名
- for i := 0; i < objType.NumField(); i++ {
- field := objType.Field(i)
- // 只导出可导出的字段(首字母大写)
- if field.PkgPath == "" {
- fieldName := strings.ToLower(field.Name)
- fields = append(fields, fmt.Sprintf("`%s`", fieldName))
- }
- }
- }
- return fields, nil
- }
- // isEmptyValue 检查值是否为空(零值)
- func isEmptyValue(v reflect.Value) bool {
- switch v.Kind() {
- case reflect.String:
- return v.String() == ""
- case reflect.Bool:
- return false // 布尔类型没有"空"的概念
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return v.Int() == 0
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- return v.Uint() == 0
- case reflect.Float32, reflect.Float64:
- return v.Float() == 0
- case reflect.Ptr, reflect.Interface:
- return v.IsNil()
- case reflect.Slice, reflect.Map, reflect.Array:
- return v.Len() == 0
- default:
- // 对于其他类型,尝试检查IsZero
- return v.IsZero()
- }
- }
|