jdbc_client.go 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. package services
  2. import (
  3. // "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math"
  7. "reflect"
  8. "runtime"
  9. "strings"
  10. "time"
  11. "easydo-echo_win7/models"
  12. "easydo-echo_win7/utils"
  13. "database/sql"
  14. "github.com/jmoiron/sqlx"
  15. )
  16. // DBClient 数据库客户端结构体
  17. type DBClient struct {
  18. db *sqlx.DB
  19. log bool
  20. }
  21. // NewDBClient 创建新的数据库客户端
  22. func NewDBClient(db *sqlx.DB, log bool) *DBClient {
  23. build_time := time.Now()
  24. build_time_str := build_time.Format(time.DateTime)
  25. fmt.Printf("%s 数据库的客户端初始化成功\n", build_time_str)
  26. return &DBClient{db: db, log: log}
  27. }
  28. // PageResult 分页查询结果
  29. type PageResult struct {
  30. Total int64 `json:"total"`
  31. Records interface{} `json:"records"`
  32. }
  33. // TransactionFunc 事务处理函数类型
  34. type TransactionFunc func(tx *sqlx.Tx) error
  35. // GetJdbcPage 单表分页查询
  36. func (c *DBClient) GetJdbcPage(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (*PageResult, error) {
  37. // 获取表名
  38. tableName := utils.GetTableName(clazz)
  39. // 获取结构体字段列表
  40. fields, err := c.getStructDBFields(clazz)
  41. if err != nil {
  42. println(err.Error())
  43. return nil, err
  44. }
  45. if len(fields) == 0 {
  46. return nil, errors.New("no db fields found in struct")
  47. }
  48. // 构建字段列表字符串
  49. fieldsStr := strings.Join(fields, ", ")
  50. // 构建查询条件
  51. whereSQL, err := utils.BuildWhereCondition(params)
  52. if err != nil {
  53. println(err.Error())
  54. return nil, err
  55. }
  56. // 执行查询
  57. var querySQL string
  58. var total int64
  59. if len(conn) > 0 {
  60. // 使用事务连接
  61. tx := conn[0]
  62. // 查询数据列表
  63. querySQL = fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  64. if c.log {
  65. build_time_str := time.Now().Format(time.DateTime)
  66. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  67. }
  68. rows, err := tx.Queryx(querySQL)
  69. if err != nil {
  70. println(err.Error())
  71. return nil, err
  72. }
  73. defer rows.Close()
  74. // 将结果映射到结构体列表
  75. resultList, err := c.scanRowsToList(rows, clazz)
  76. if err != nil {
  77. println(err.Error())
  78. return nil, err
  79. }
  80. // 查询总数
  81. paramsCopy := make(map[string]interface{})
  82. for k, v := range params {
  83. if k != "current" && k != "size" && k != "orderBy" {
  84. paramsCopy[k] = v
  85. }
  86. }
  87. countSQL, err := utils.BuildWhereCondition(paramsCopy)
  88. if err != nil {
  89. println(err.Error())
  90. return nil, err
  91. }
  92. querySQL = fmt.Sprintf("SELECT COUNT(1) FROM %s%s", tableName, countSQL)
  93. if c.log {
  94. build_time_str := time.Now().Format(time.DateTime)
  95. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  96. }
  97. err = tx.Get(&total, querySQL)
  98. if err != nil {
  99. println(err.Error())
  100. return nil, err
  101. }
  102. return &PageResult{
  103. Total: total,
  104. Records: resultList,
  105. }, nil
  106. } else {
  107. // 使用普通连接
  108. querySQL = fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  109. if c.log {
  110. build_time_str := time.Now().Format(time.DateTime)
  111. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  112. }
  113. rows, err := c.db.Queryx(querySQL)
  114. if err != nil {
  115. println(err.Error())
  116. return nil, err
  117. }
  118. defer rows.Close()
  119. resultList, err := c.scanRowsToList(rows, clazz)
  120. if err != nil {
  121. return nil, err
  122. }
  123. paramsCopy := make(map[string]interface{})
  124. for k, v := range params {
  125. if k != "current" && k != "size" && k != "orderBy" {
  126. paramsCopy[k] = v
  127. }
  128. }
  129. countSQL, err := utils.BuildWhereCondition(paramsCopy)
  130. if err != nil {
  131. println(err.Error())
  132. return nil, err
  133. }
  134. querySQL = fmt.Sprintf("SELECT COUNT(1) FROM %s%s", tableName, countSQL)
  135. if c.log {
  136. build_time_str := time.Now().Format(time.DateTime)
  137. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  138. }
  139. err = c.db.Get(&total, querySQL)
  140. if err != nil {
  141. println(err.Error())
  142. return nil, err
  143. }
  144. return &PageResult{
  145. Total: total,
  146. Records: resultList,
  147. }, nil
  148. }
  149. }
  150. // GetJdbcPageBySql 使用自定义SQL进行分页查询
  151. func (c *DBClient) GetJdbcPageBySql(params map[string]interface{}, viewSQL string, clazz interface{}, conn ...*sqlx.Tx) (*PageResult, error) {
  152. var total int64
  153. var resultList interface{}
  154. // 获取结构体字段列表
  155. fields, err := c.getStructDBFields(clazz)
  156. if err != nil {
  157. println(err.Error())
  158. return nil, err
  159. }
  160. if len(fields) == 0 {
  161. return nil, errors.New("no db fields found in struct")
  162. }
  163. // 构建字段列表字符串
  164. fieldsStr := strings.Join(fields, ", ")
  165. // 替换原SQL中的SELECT *为SELECT 字段列表
  166. lowerSQL := strings.ToLower(viewSQL)
  167. if strings.Contains(lowerSQL, "select *") {
  168. // 替换SELECT *为SELECT 字段列表
  169. viewSQL = strings.Replace(lowerSQL, "select *", fmt.Sprintf("select %s", fieldsStr), 1)
  170. // 保持原SQL的大小写风格
  171. parts := strings.SplitN(viewSQL, " ", 2)
  172. if len(parts) == 2 {
  173. viewSQL = fmt.Sprintf("SELECT %s %s", fieldsStr, parts[1])
  174. }
  175. }
  176. // 构建查询条件
  177. whereSQL, err := utils.BuildWhereCondition(params)
  178. if err != nil {
  179. println(err.Error())
  180. return nil, err
  181. }
  182. querySQL := fmt.Sprintf("%s%s", viewSQL, whereSQL)
  183. querySQL = strings.ReplaceAll(querySQL, "`", "")
  184. if c.log {
  185. build_time_str := time.Now().Format(time.DateTime)
  186. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  187. }
  188. if len(conn) > 0 {
  189. tx := conn[0]
  190. rows, err := tx.Queryx(querySQL)
  191. if err != nil {
  192. println(err.Error())
  193. return nil, err
  194. }
  195. defer rows.Close()
  196. resultList, err = c.scanRowsToList(rows, clazz)
  197. if err != nil {
  198. println(err.Error())
  199. return nil, err
  200. }
  201. // 构建COUNT SQL
  202. paramsCopy := make(map[string]interface{})
  203. for k, v := range params {
  204. if k != "current" && k != "size" && k != "orderBy" {
  205. paramsCopy[k] = v
  206. }
  207. }
  208. countSQL, err := utils.BuildWhereCondition(paramsCopy)
  209. if err != nil {
  210. println(err.Error())
  211. return nil, err
  212. }
  213. // 转换视图SQL为COUNT SQL
  214. fromIndex := strings.Index(strings.ToLower(viewSQL), "from")
  215. if fromIndex == -1 {
  216. return nil, errors.New("invalid SQL: no FROM clause found")
  217. }
  218. countQuerySQL := fmt.Sprintf("SELECT COUNT(1) %s%s", viewSQL[fromIndex:], countSQL)
  219. countQuerySQL = strings.ReplaceAll(countQuerySQL, "`", "")
  220. if c.log {
  221. build_time_str := time.Now().Format(time.DateTime)
  222. fmt.Printf("%s querySQL======>%s\n", build_time_str, countQuerySQL)
  223. }
  224. err = tx.Get(&total, countQuerySQL)
  225. if err != nil {
  226. println(err.Error())
  227. return nil, err
  228. }
  229. } else {
  230. rows, err := c.db.Queryx(querySQL)
  231. if err != nil {
  232. println(err.Error())
  233. return nil, err
  234. }
  235. defer rows.Close()
  236. resultList, err = c.scanRowsToList(rows, clazz)
  237. if err != nil {
  238. println(err.Error())
  239. return nil, err
  240. }
  241. paramsCopy := make(map[string]interface{})
  242. for k, v := range params {
  243. if k != "current" && k != "size" && k != "orderBy" {
  244. paramsCopy[k] = v
  245. }
  246. }
  247. countSQL, err := utils.BuildWhereCondition(paramsCopy)
  248. if err != nil {
  249. println(err.Error())
  250. return nil, err
  251. }
  252. fromIndex := strings.Index(strings.ToLower(viewSQL), "from")
  253. if fromIndex == -1 {
  254. return nil, errors.New("invalid SQL: no FROM clause found")
  255. }
  256. countQuerySQL := fmt.Sprintf("SELECT COUNT(1) %s%s", viewSQL[fromIndex:], countSQL)
  257. countQuerySQL = strings.ReplaceAll(countQuerySQL, "`", "")
  258. if c.log {
  259. build_time_str := time.Now().Format(time.DateTime)
  260. fmt.Printf("%s querySQL======>%s\n", build_time_str, countQuerySQL)
  261. }
  262. err = c.db.Get(&total, countQuerySQL)
  263. if err != nil {
  264. println(err.Error())
  265. return nil, err
  266. }
  267. }
  268. return &PageResult{
  269. Total: total,
  270. Records: resultList,
  271. }, nil
  272. }
  273. // GetJdbcList 单表查询列表
  274. func (c *DBClient) GetJdbcList(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (interface{}, error) {
  275. tableName := utils.GetTableName(clazz)
  276. // 获取结构体字段列表
  277. fields, err := c.getStructDBFields(clazz)
  278. if err != nil {
  279. println(err.Error())
  280. return nil, err
  281. }
  282. if len(fields) == 0 {
  283. return nil, errors.New("no db fields found in struct")
  284. }
  285. // 构建字段列表字符串
  286. fieldsStr := strings.Join(fields, ", ")
  287. whereSQL, err := utils.BuildWhereCondition(params)
  288. if err != nil {
  289. println(err.Error())
  290. return nil, err
  291. }
  292. querySQL := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  293. if c.log {
  294. build_time_str := time.Now().Format(time.DateTime)
  295. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  296. }
  297. if len(conn) > 0 {
  298. tx := conn[0]
  299. rows, err := tx.Queryx(querySQL)
  300. if err != nil {
  301. println(err.Error())
  302. return nil, err
  303. }
  304. defer rows.Close()
  305. return c.scanRowsToList(rows, clazz)
  306. } else {
  307. rows, err := c.db.Queryx(querySQL)
  308. if err != nil {
  309. println(err.Error())
  310. return nil, err
  311. }
  312. defer rows.Close()
  313. return c.scanRowsToList(rows, clazz)
  314. }
  315. }
  316. // GetJdbcListByObject 根据对象查询列表
  317. func (c *DBClient) GetJdbcListByObject(obj interface{}, conn ...*sqlx.Tx) (interface{}, error) {
  318. // 将对象转换为map
  319. paramMap, err := c.objectToMap(obj)
  320. if err != nil {
  321. println(err.Error())
  322. return nil, err
  323. }
  324. tableName := utils.GetTableName(obj)
  325. // 获取结构体字段列表
  326. fields, err := c.getStructDBFields(obj)
  327. if err != nil {
  328. println(err.Error())
  329. return nil, err
  330. }
  331. if len(fields) == 0 {
  332. return nil, errors.New("no db fields found in struct")
  333. }
  334. // 构建字段列表字符串
  335. fieldsStr := strings.Join(fields, ", ")
  336. whereSQL, err := utils.BuildWhereCondition(paramMap)
  337. if err != nil {
  338. println(err.Error())
  339. return nil, err
  340. }
  341. querySQL := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  342. if c.log {
  343. build_time_str := time.Now().Format(time.DateTime)
  344. fmt.Printf("%s querySQL======>%s\n", build_time_str, querySQL)
  345. }
  346. if len(conn) > 0 {
  347. tx := conn[0]
  348. rows, err := tx.Queryx(querySQL)
  349. if err != nil {
  350. println(err.Error())
  351. return nil, err
  352. }
  353. defer rows.Close()
  354. return c.scanRowsToList(rows, obj)
  355. } else {
  356. rows, err := c.db.Queryx(querySQL)
  357. if err != nil {
  358. println(err.Error())
  359. return nil, err
  360. }
  361. defer rows.Close()
  362. return c.scanRowsToList(rows, obj)
  363. }
  364. }
  365. // GetJdbcModel 查询单个模型(根据对象非空字段)
  366. func (c *DBClient) GetJdbcModel(obj interface{}, conn ...*sqlx.Tx) error {
  367. // 获取表名
  368. tableName := utils.GetTableName(obj)
  369. // 获取结构体字段列表
  370. fields, err := c.getStructDBFields(obj)
  371. if err != nil {
  372. println(err.Error())
  373. return err
  374. }
  375. if len(fields) == 0 {
  376. return errors.New("no db fields found in struct")
  377. }
  378. // 构建字段列表字符串
  379. fieldsStr := strings.Join(fields, ", ")
  380. // 将对象转换为map作为查询条件
  381. whereMap, err := c.objectToMap(obj)
  382. if err != nil {
  383. println(err.Error())
  384. return err
  385. }
  386. // 构建WHERE条件
  387. whereSQL, err := utils.BuildWhereCondition(whereMap)
  388. if err != nil {
  389. println(err.Error())
  390. return err
  391. }
  392. sqlStr := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  393. if c.log {
  394. build_time_str := time.Now().Format(time.DateTime)
  395. fmt.Printf("%s queryMSQL======>%s\n", build_time_str, sqlStr)
  396. }
  397. if len(conn) > 0 {
  398. tx := conn[0]
  399. row := tx.QueryRowx(sqlStr)
  400. return c.scanRowToModel(row, obj)
  401. } else {
  402. row := c.db.QueryRowx(sqlStr)
  403. return c.scanRowToModel(row, obj)
  404. }
  405. }
  406. // GetJdbcModelByMap 根据参数map查询单个模型
  407. func (c *DBClient) GetJdbcModelByMap(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) error {
  408. // 获取表名
  409. tableName := utils.GetTableName(clazz)
  410. // 获取结构体字段列表
  411. fields, err := c.getStructDBFields(clazz)
  412. if err != nil {
  413. println(err.Error())
  414. return err
  415. }
  416. if len(fields) == 0 {
  417. return errors.New("no db fields found in struct")
  418. }
  419. // 构建字段列表字符串
  420. fieldsStr := strings.Join(fields, ", ")
  421. // 构建WHERE条件
  422. whereSQL, err := utils.BuildWhereCondition(params)
  423. if err != nil {
  424. println(err.Error())
  425. return err
  426. }
  427. sqlStr := fmt.Sprintf("SELECT %s FROM %s%s", fieldsStr, tableName, whereSQL)
  428. if c.log {
  429. build_time_str := time.Now().Format(time.DateTime)
  430. fmt.Printf("%s queryMMSQL======>%s\n", build_time_str, sqlStr)
  431. }
  432. if len(conn) > 0 {
  433. tx := conn[0]
  434. row := tx.QueryRowx(sqlStr)
  435. return c.scanRowToModel(row, clazz)
  436. } else {
  437. row := c.db.QueryRowx(sqlStr)
  438. return c.scanRowToModel(row, clazz)
  439. }
  440. }
  441. // GetJdbcModelById 根据ID查询单个模型
  442. func (c *DBClient) GetJdbcModelById(obj interface{}, conn ...*sqlx.Tx) error {
  443. // 获取表名
  444. tableName := utils.GetTableName(obj)
  445. // 获取结构体字段列表
  446. fields, err := c.getStructDBFields(obj)
  447. if err != nil {
  448. println(err.Error())
  449. return err
  450. }
  451. if len(fields) == 0 {
  452. return errors.New("no db fields found in struct")
  453. }
  454. // 构建字段列表字符串
  455. fieldsStr := strings.Join(fields, ", ")
  456. // 获取ID字段名(假设为"id")
  457. idField := "id"
  458. // 尝试从结构体中获取ID字段
  459. v := reflect.ValueOf(obj)
  460. if v.Kind() == reflect.Ptr {
  461. v = v.Elem()
  462. }
  463. t := v.Type()
  464. for i := 0; i < t.NumField(); i++ {
  465. field := t.Field(i)
  466. dbTag := field.Tag.Get("db")
  467. jsonTag := field.Tag.Get("json")
  468. fieldName := strings.ToLower(field.Name)
  469. // 尝试找到ID字段
  470. if dbTag == "id" || jsonTag == "id" || fieldName == "id" {
  471. if dbTag != "" && dbTag != "-" {
  472. idField = dbTag
  473. }
  474. break
  475. }
  476. }
  477. // 获取ID值
  478. var idValue interface{}
  479. idFieldFound := false
  480. for i := 0; i < v.NumField(); i++ {
  481. field := t.Field(i)
  482. fieldValue := v.Field(i)
  483. is_format:=formatSqlValue(field.Name,fieldValue)
  484. if is_format {
  485. continue
  486. }
  487. dbTag := field.Tag.Get("db")
  488. jsonTag := field.Tag.Get("json")
  489. fieldName := strings.ToLower(field.Name)
  490. if dbTag == "id" || jsonTag == "id" || fieldName == "id" {
  491. idValue = fieldValue.Interface()
  492. idFieldFound = true
  493. continue
  494. }
  495. }
  496. if !idFieldFound || isEmptyValue(reflect.ValueOf(idValue)) {
  497. return errors.New("id field not found or is empty")
  498. }
  499. sqlStr := fmt.Sprintf("SELECT %s FROM %s WHERE %s = ?", fieldsStr, tableName, idField)
  500. if c.log {
  501. build_time_str := time.Now().Format(time.DateTime)
  502. fmt.Printf("%s queryIDSQL======>%s %s\n", build_time_str, sqlStr, utils.FormatToString(idValue))
  503. }
  504. if len(conn) > 0 {
  505. tx := conn[0]
  506. row := tx.QueryRowx(sqlStr, idValue)
  507. return c.scanRowToModel(row, obj)
  508. } else {
  509. row := c.db.QueryRowx(sqlStr, idValue)
  510. return c.scanRowToModel(row, obj)
  511. }
  512. }
  513. func (c *DBClient) JdbcInsert(model interface{}, conn ...*sqlx.Tx) error {
  514. // 1. 校验model必须是指针(否则无法赋值自增ID)
  515. val := reflect.ValueOf(model)
  516. if val.Kind() != reflect.Ptr || val.IsNil() {
  517. return fmt.Errorf("model必须是非空指针类型")
  518. }
  519. modelVal := val.Elem() // 解引用指针,获取实际结构体值
  520. // 2. 生成插入SQL(保留原有逻辑)
  521. uuid := utils.GenerateUUID()
  522. sqlStr, err := utils.FormatInsertSql(model, uuid)
  523. if c.log {
  524. build_time_str := time.Now().Format(time.DateTime)
  525. fmt.Printf("%s insertSQL======>%s\n", build_time_str, sqlStr)
  526. }
  527. if err != nil {
  528. return fmt.Errorf("生成插入SQL失败: %w", err)
  529. }
  530. // 3. 执行INSERT并获取自增ID
  531. var lastInsertID int64
  532. if len(conn) > 0 {
  533. // 事务场景
  534. tx := conn[0]
  535. result, err := tx.Exec(sqlStr)
  536. if err != nil {
  537. return fmt.Errorf("事务执行INSERT失败: %w", err)
  538. }
  539. // 检查受影响行数
  540. rowsAffected, err := result.RowsAffected()
  541. if err != nil {
  542. // 某些数据库驱动或特定查询可能不支持RowsAffected
  543. // 但这通常发生在SELECT等语句上,INSERT/UPDATE/DELETE通常支持
  544. return fmt.Errorf("警告:无法获取受影响行数(可能不影响业务): %w", err)
  545. }
  546. // 对于INSERT,通常期望至少插入1行
  547. if rowsAffected == 0 {
  548. return fmt.Errorf("操作未生效(受影响行数为0),请检查数据或约束。SQL: %s", sqlStr)
  549. }
  550. lastInsertID, err = result.LastInsertId()
  551. if err != nil {
  552. return fmt.Errorf("获取事务自增ID失败: %w", err)
  553. }
  554. } else {
  555. // 非事务场景
  556. result, err := c.db.Exec(sqlStr)
  557. if err != nil {
  558. return fmt.Errorf("执行INSERT失败: %w", err)
  559. }
  560. lastInsertID, err = result.LastInsertId()
  561. if err != nil {
  562. fmt.Println("获取自增ID失败: %w", err)
  563. return nil
  564. }
  565. }
  566. // 4. 反射赋值自增ID到model的ID字段
  567. if err := setAutoIncrementID(modelVal, lastInsertID, uuid); err != nil {
  568. // 仅打印警告,不中断流程(避免非自增表场景报错)
  569. fmt.Printf("自增ID赋值失败(非自增表可忽略): %v\n", err)
  570. }
  571. return nil
  572. }
  573. // setAutoIncrementID 反射给model赋值自增ID
  574. // modelVal: 结构体的reflect.Value(已解引用指针)
  575. // lastInsertID: 数据库返回的自增ID
  576. func setAutoIncrementID(modelVal reflect.Value, lastInsertID int64, uuid string) error {
  577. // 遍历结构体字段,找到自增ID字段(db:"id")
  578. for i := 0; i < modelVal.NumField(); i++ {
  579. field := modelVal.Type().Field(i) // 字段元信息
  580. fieldVal := modelVal.Field(i) // 字段值
  581. // 解析db标签,判断是否是ID字段(支持如 db:"id,primarykey" 这类带额外参数的标签)
  582. dbTag := field.Tag.Get("db")
  583. if dbTag == "" {
  584. continue
  585. }
  586. tagParts := strings.Split(dbTag, ",")
  587. if tagParts[0] != "id" {
  588. continue
  589. }
  590. // 处理指针类型
  591. if fieldVal.Kind() == reflect.Ptr {
  592. // 指针为空,需要创建新的实例
  593. if fieldVal.IsNil() {
  594. // 根据指针指向的类型创建新值
  595. elemType := fieldVal.Type().Elem()
  596. newVal := reflect.New(elemType)
  597. fieldVal.Set(newVal)
  598. }
  599. // 获取指针指向的值
  600. elem := fieldVal.Elem()
  601. // 根据指针指向的实际类型赋值
  602. return setValueByKind(elem, lastInsertID, field.Name, uuid)
  603. }
  604. // 非指针类型,检查是否可设置
  605. if !fieldVal.CanSet() {
  606. continue
  607. }
  608. // 根据字段类型赋值自增ID
  609. return setValueByKind(fieldVal, lastInsertID, field.Name, uuid)
  610. }
  611. return fmt.Errorf("未找到可赋值的自增ID字段(需包含 db:\"id\" 标签且为整数类型)")
  612. }
  613. // setValueByKind 根据不同的类型设置值
  614. func setValueByKind(fieldVal reflect.Value, lastInsertID int64, fieldName string, uuid string) error {
  615. // 根据字段类型赋值自增ID,并校验范围
  616. switch fieldVal.Kind() {
  617. case reflect.Int, reflect.Int64:
  618. fieldVal.SetInt(lastInsertID)
  619. case reflect.Uint, reflect.Uint64:
  620. fieldVal.SetUint(uint64(lastInsertID))
  621. case reflect.Int8:
  622. if lastInsertID < math.MinInt8 || lastInsertID > math.MaxInt8 {
  623. return fmt.Errorf("自增ID %d 超出int8字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt8, math.MaxInt8)
  624. }
  625. fieldVal.SetInt(lastInsertID)
  626. case reflect.Int16:
  627. if lastInsertID < math.MinInt16 || lastInsertID > math.MaxInt16 {
  628. return fmt.Errorf("自增ID %d 超出int16字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt16, math.MaxInt16)
  629. }
  630. fieldVal.SetInt(lastInsertID)
  631. case reflect.Int32:
  632. if lastInsertID < math.MinInt32 || lastInsertID > math.MaxInt32 {
  633. return fmt.Errorf("自增ID %d 超出int32字段 %s 范围(%d~%d)", lastInsertID, fieldName, math.MinInt32, math.MaxInt32)
  634. }
  635. fieldVal.SetInt(lastInsertID)
  636. case reflect.Uint8:
  637. if uint64(lastInsertID) > math.MaxUint8 {
  638. return fmt.Errorf("自增ID %d 超出uint8字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint8)
  639. }
  640. fieldVal.SetUint(uint64(lastInsertID))
  641. case reflect.Uint16:
  642. if uint64(lastInsertID) > math.MaxUint16 {
  643. return fmt.Errorf("自增ID %d 超出uint16字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint16)
  644. }
  645. fieldVal.SetUint(uint64(lastInsertID))
  646. case reflect.Uint32:
  647. if uint64(lastInsertID) > math.MaxUint32 {
  648. return fmt.Errorf("自增ID %d 超出uint32字段 %s 范围(0~%d)", lastInsertID, fieldName, math.MaxUint32)
  649. }
  650. fieldVal.SetUint(uint64(lastInsertID))
  651. case reflect.String:
  652. fieldVal.SetString(string(uuid))
  653. default:
  654. return fmt.Errorf("字段 %s 类型 %s 不支持自增ID赋值", fieldName, fieldVal.Kind())
  655. }
  656. return nil
  657. }
  658. // JdbcUpdate 更新数据
  659. func (c *DBClient) JdbcUpdate(model interface{}, whereMap map[string]interface{}, conn ...*sqlx.Tx) error {
  660. sqlStr, err := utils.FormatUpdateSql(model, whereMap)
  661. if c.log {
  662. build_time_str := time.Now().Format(time.DateTime)
  663. fmt.Printf("%s updateSQL======>%s\n", build_time_str, sqlStr)
  664. }
  665. if err != nil {
  666. println(err.Error())
  667. return err
  668. }
  669. if len(conn) > 0 {
  670. tx := conn[0]
  671. _, err := tx.Exec(sqlStr)
  672. if err != nil {
  673. return fmt.Errorf("事务执行UPDATE失败: %w", err)
  674. }
  675. return nil
  676. } else {
  677. _, err := c.db.Exec(sqlStr)
  678. if err != nil {
  679. return fmt.Errorf("执行UPDATE失败: %w", err)
  680. }
  681. return nil
  682. }
  683. }
  684. // JdbcUpdateById 根据ID更新数据
  685. func (c *DBClient) JdbcUpdateById(model interface{}, conn ...*sqlx.Tx) error {
  686. sqlStr, err := utils.FormatUpdateByIdSql(model)
  687. if c.log {
  688. build_time_str := time.Now().Format(time.DateTime)
  689. fmt.Printf("%s updateSQL======>%s\n", build_time_str, sqlStr)
  690. }
  691. if err != nil {
  692. println(err.Error())
  693. return err
  694. }
  695. if len(conn) > 0 {
  696. tx := conn[0]
  697. _, err := tx.Exec(sqlStr)
  698. return err
  699. } else {
  700. _, err := c.db.Exec(sqlStr)
  701. return err
  702. }
  703. }
  704. // JdbcRemoveById 根据ID删除数据
  705. func (c *DBClient) JdbcRemoveById(model interface{}, conn ...*sqlx.Tx) error {
  706. sqlStr, err := utils.FormatRemoveByIdSql(model)
  707. if c.log {
  708. build_time_str := time.Now().Format(time.DateTime)
  709. fmt.Printf("%s removeSQL======>%s\n", build_time_str, sqlStr)
  710. }
  711. if err != nil {
  712. return err
  713. }
  714. if len(conn) > 0 {
  715. tx := conn[0]
  716. _, err := tx.Exec(sqlStr)
  717. return err
  718. } else {
  719. _, err := c.db.Exec(sqlStr)
  720. return err
  721. }
  722. }
  723. // JdbcRemove 根据条件删除数据
  724. func (c *DBClient) JdbcRemove(model interface{}, conn ...*sqlx.Tx) error {
  725. sqlStr, err := utils.FormatRemoveSql(model)
  726. if c.log {
  727. build_time_str := time.Now().Format(time.DateTime)
  728. fmt.Printf("%s removeSQL======>%s\n", build_time_str, sqlStr)
  729. }
  730. if err != nil {
  731. println(err.Error())
  732. return err
  733. }
  734. if len(conn) > 0 {
  735. tx := conn[0]
  736. _, err := tx.Exec(sqlStr)
  737. return err
  738. } else {
  739. _, err := c.db.Exec(sqlStr)
  740. return err
  741. }
  742. }
  743. // GetJdbcCount 统计数量(根据对象)
  744. func (c *DBClient) GetJdbcCount(obj interface{}, conn ...*sqlx.Tx) (int64, error) {
  745. sqlStr, err := utils.FormatSelectCountSql(obj)
  746. if c.log {
  747. build_time_str := time.Now().Format(time.DateTime)
  748. fmt.Printf("%s countSQL======>%s\n", build_time_str, sqlStr)
  749. }
  750. if err != nil {
  751. println(err.Error())
  752. return 0, err
  753. }
  754. var count int64
  755. if len(conn) > 0 {
  756. tx := conn[0]
  757. row := tx.QueryRowx(sqlStr)
  758. err = row.Scan(&count)
  759. } else {
  760. row := c.db.QueryRowx(sqlStr)
  761. err = row.Scan(&count)
  762. }
  763. if err != nil {
  764. println(err.Error())
  765. return 0, err
  766. }
  767. return count, nil
  768. }
  769. // GetJdbcCountByMap 统计数量(根据参数map)
  770. func (c *DBClient) GetJdbcCountByMap(params map[string]interface{}, clazz interface{}, conn ...*sqlx.Tx) (int64, error) {
  771. sqlStr, err := utils.FormatSelectCountSqlByMap(clazz, params)
  772. if c.log {
  773. build_time_str := time.Now().Format(time.DateTime)
  774. fmt.Printf("%s countSQL======>%s\n", build_time_str, sqlStr)
  775. }
  776. if err != nil {
  777. println(err.Error())
  778. return 0, err
  779. }
  780. var count int64
  781. if len(conn) > 0 {
  782. tx := conn[0]
  783. row := tx.QueryRowx(sqlStr)
  784. err = row.Scan(&count)
  785. } else {
  786. row := c.db.QueryRowx(sqlStr)
  787. err = row.Scan(&count)
  788. }
  789. if err != nil {
  790. println(err.Error())
  791. return 0, err
  792. }
  793. return count, nil
  794. }
  795. func (c *DBClient) GetMinioFile(obj interface{}, conn ...*sqlx.Tx) ([]models.MinioFile, error) {
  796. tableName := utils.GetTableName(obj)
  797. id, err := utils.GetIdValue(obj)
  798. if err != nil {
  799. return []models.MinioFile{}, err
  800. }
  801. file := new(models.MinioFile)
  802. file.RefId = &id
  803. file.RefType = &tableName
  804. result, err := c.GetJdbcListByObject(file)
  805. if err != nil {
  806. build_time_str := time.Now().Format(time.DateTime)
  807. fmt.Printf("%s SQL执行失败: %v\n", build_time_str, err)
  808. return []models.MinioFile{}, fmt.Errorf("SQL执行失败: %v", err)
  809. }
  810. list := utils.ConvertInterface[[]models.MinioFile](result)
  811. return list, nil
  812. }
  813. // 辅助方法
  814. // scanRowsToList 将查询结果扫描到结构体列表
  815. func (c *DBClient) scanRowsToList(rows *sqlx.Rows, clazz interface{}) (interface{}, error) {
  816. // 获取类型信息
  817. var elemType reflect.Type
  818. // 处理指针类型
  819. rt := reflect.TypeOf(clazz)
  820. if rt.Kind() == reflect.Ptr {
  821. rt = rt.Elem()
  822. }
  823. // 如果是reflect.Type类型
  824. if rt.Kind() == reflect.Struct {
  825. elemType = rt
  826. } else {
  827. // 尝试从接口获取类型
  828. elemType = reflect.TypeOf(clazz)
  829. if elemType.Kind() == reflect.Ptr {
  830. elemType = elemType.Elem()
  831. }
  832. }
  833. // 创建切片
  834. sliceType := reflect.SliceOf(elemType)
  835. resultSlice := reflect.New(sliceType).Elem()
  836. for rows.Next() {
  837. elem := reflect.New(elemType).Interface()
  838. err := rows.StructScan(elem)
  839. if err != nil {
  840. return nil, err
  841. }
  842. elemValue := reflect.ValueOf(elem).Elem()
  843. for i := 0; i < elemValue.NumField(); i++ {
  844. field := elemValue.Field(i)
  845. fieldType := elemType.Field(i)
  846. // 检查字段名和类型
  847. fieldName := fieldType.Name
  848. is_format:=formatSqlValue(fieldName,field)
  849. if is_format {
  850. continue
  851. }
  852. }
  853. resultSlice = reflect.Append(resultSlice, reflect.ValueOf(elem).Elem())
  854. }
  855. return resultSlice.Interface(), nil
  856. }
  857. // scanRowToModel 将单行查询结果扫描到结构体
  858. func (c *DBClient) scanRowToModel(row *sqlx.Row, clazz interface{}) error {
  859. err := row.StructScan(clazz)
  860. if err != nil {
  861. if errors.Is(err, sql.ErrNoRows) {
  862. if c.log {
  863. build_time_str := time.Now().Format(time.DateTime)
  864. fmt.Printf("%s scanRowToModel======>%s\n", build_time_str, "sql: no rows in result set")
  865. }
  866. return nil
  867. }
  868. return err
  869. }
  870. // 获取结构体值
  871. elemValue := reflect.ValueOf(clazz)
  872. if elemValue.Kind() != reflect.Ptr {
  873. return fmt.Errorf("clazz must be a pointer")
  874. }
  875. elemValue = elemValue.Elem()
  876. if elemValue.Kind() != reflect.Struct {
  877. return fmt.Errorf("clazz must point to a struct")
  878. }
  879. elemType := elemValue.Type()
  880. // 遍历结构体字段
  881. for i := 0; i < elemValue.NumField(); i++ {
  882. field := elemValue.Field(i)
  883. fieldType := elemType.Field(i)
  884. // 检查字段名和类型
  885. fieldName := fieldType.Name
  886. is_format:=formatSqlValue(fieldName,field)
  887. if is_format {
  888. continue
  889. }
  890. }
  891. return nil
  892. }
  893. func formatSqlValue(fieldName string,fieldValue reflect.Value) bool {
  894. // 检查字段名和类型
  895. is_format := true
  896. if strings.HasSuffix(fieldName, "Time") && fieldValue.Type() == reflect.TypeOf((*string)(nil)) {
  897. if fieldValue.IsValid() && !fieldValue.IsNil() {
  898. fieldValue_t := utils.FormatToString(fieldValue.Interface())
  899. t, err := time.Parse(time.RFC3339, fieldValue_t)
  900. if err != nil {
  901. build_time_str := time.Now().Format(time.DateTime)
  902. _, file, line, _ := runtime.Caller(0)
  903. fmt.Printf("%s err %s %d======> %v\n", build_time_str, file, line, err)
  904. return is_format
  905. }
  906. strPtr := new(string)
  907. t_str := t.Format(time.DateTime)
  908. strPtr = &t_str
  909. fieldValue.Set(reflect.ValueOf(strPtr))
  910. return is_format
  911. }
  912. } else if strings.HasSuffix(fieldName, "Date") && fieldValue.Type() == reflect.TypeOf((*string)(nil)) {
  913. if fieldValue.IsValid() && !fieldValue.IsNil() {
  914. fieldValue_t := utils.FormatToString(fieldValue.Interface())
  915. if len(fieldValue_t) > 10 {
  916. t_str := fieldValue_t[:10]
  917. strPtr := new(string)
  918. strPtr = &t_str
  919. fieldValue.Set(reflect.ValueOf(strPtr))
  920. }
  921. return is_format
  922. }
  923. }
  924. return false
  925. }
  926. func (c *DBClient) ScanRowToModel(row *sqlx.Row, clazz interface{}) error {
  927. return c.scanRowToModel(row, clazz)
  928. }
  929. func (c *DBClient) ScanRowToList(rows *sqlx.Rows, clazz interface{}) (interface{}, error) {
  930. return c.scanRowsToList(rows, clazz)
  931. }
  932. // objectToMap 将对象转换为map[string]interface{}
  933. func (c *DBClient) objectToMap(obj interface{}) (map[string]interface{}, error) {
  934. result := make(map[string]interface{})
  935. // 获取对象类型和值
  936. objType := reflect.TypeOf(obj)
  937. objValue := reflect.ValueOf(obj)
  938. // 如果是指针,获取指向的值
  939. if objType.Kind() == reflect.Ptr {
  940. objType = objType.Elem()
  941. objValue = objValue.Elem()
  942. }
  943. // 检查是否是结构体
  944. if objType.Kind() != reflect.Struct {
  945. return nil, errors.New("参数必须是结构体或结构体指针")
  946. }
  947. // 遍历结构体字段
  948. for i := 0; i < objType.NumField(); i++ {
  949. field := objType.Field(i)
  950. fieldValue := objValue.Field(i)
  951. // 跳过不可导出的字段
  952. if !fieldValue.CanInterface() {
  953. continue
  954. }
  955. // 检查字段值是否为空(零值)
  956. if isEmptyValue(fieldValue) {
  957. continue
  958. }
  959. // 获取db标签作为字段名
  960. dbTag := field.Tag.Get("db")
  961. if dbTag == "" || dbTag == "-" {
  962. continue
  963. }
  964. // 添加字段到map
  965. result[dbTag] = fieldValue.Interface()
  966. }
  967. return result, nil
  968. }
  969. // getStructDBFields 获取结构体的db标签字段列表
  970. func (c *DBClient) getStructDBFields(obj interface{}) ([]string, error) {
  971. var fields []string
  972. // 获取对象类型
  973. objType := reflect.TypeOf(obj)
  974. if objType.Kind() == reflect.Ptr {
  975. objType = objType.Elem()
  976. }
  977. // 检查是否是结构体
  978. if objType.Kind() != reflect.Struct {
  979. return nil, errors.New("参数必须是结构体或结构体指针")
  980. }
  981. // 遍历结构体字段
  982. for i := 0; i < objType.NumField(); i++ {
  983. field := objType.Field(i)
  984. // 获取db标签
  985. dbTag := field.Tag.Get("db")
  986. if dbTag != "" && dbTag != "-" {
  987. // 使用反引号包裹字段名,防止关键字冲突
  988. fields = append(fields, fmt.Sprintf("`%s`", dbTag))
  989. }
  990. }
  991. if len(fields) == 0 {
  992. // 如果没有db标签,尝试使用字段名
  993. for i := 0; i < objType.NumField(); i++ {
  994. field := objType.Field(i)
  995. // 只导出可导出的字段(首字母大写)
  996. if field.PkgPath == "" {
  997. fieldName := strings.ToLower(field.Name)
  998. fields = append(fields, fmt.Sprintf("`%s`", fieldName))
  999. }
  1000. }
  1001. }
  1002. return fields, nil
  1003. }
  1004. // isEmptyValue 检查值是否为空(零值)
  1005. func isEmptyValue(v reflect.Value) bool {
  1006. switch v.Kind() {
  1007. case reflect.String:
  1008. return v.String() == ""
  1009. case reflect.Bool:
  1010. return false // 布尔类型没有"空"的概念
  1011. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1012. return v.Int() == 0
  1013. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  1014. return v.Uint() == 0
  1015. case reflect.Float32, reflect.Float64:
  1016. return v.Float() == 0
  1017. case reflect.Ptr, reflect.Interface:
  1018. return v.IsNil()
  1019. case reflect.Slice, reflect.Map, reflect.Array:
  1020. return v.Len() == 0
  1021. default:
  1022. // 对于其他类型,尝试检查IsZero
  1023. return v.IsZero()
  1024. }
  1025. }