主頁 > 後端開發 > Go語言(Golang)資料庫編程

Go語言(Golang)資料庫編程

2023-05-12 08:00:34 後端開發

Go 資料庫編程

一、連接資料庫

準備連接到資料庫

  • 要想連接到 SQL 資料庫,首先需要加載目標資料庫的驅動,驅動里面包含著于該資料庫互動的邏輯,
  • sql.Open()
    • 資料庫驅動的名稱
    • 資料源名稱
    • 得到一個指向 sql.DB 這個 struct 的指標
  • sql.DB 是用來操作資料庫的,它代表了0個或者多個底層連接的池,這些連接由sql 包來維護,sql 包會自動的創建和釋放這些連接
    • 它對于多個 goroutine 并發的使用是安全的
package main

import (
  "context"
  "database/sql"
  "fmt"
  "log"
  
  _ "github.com/denisenkom/go-mssqldb"
)

var db *sql.DB

const (
  server = "xxxx.database.windows.net"
  port = 1433
  user = "xxxxx"
  password = "xxxxx"
  database = "go-db"
)

func main() {
  connStr := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
                        server, user, password, port, database)
  
  db, err := sql.Open("sqlserver", connStr)
  if err != nil {
    log.Fataln(err.Error())
  }
  
  ctx := context.Background()
  
  err = db.PingContext(ctx)
  if err != nil {
    log.Fataln(err.Error())
  }
  
  fmt.Println("Connected!")
}

Note

  • Open() 函式并不會連接資料庫,甚至不會驗證其引數,它只是把后續連接到資料庫所必需的 structs 給設定好了
  • 而真正的連接是在被需要的時候才進行懶設定的
  • sql.DB 不需要進行關閉(當然你想關閉也是可以的)
  • 它就是用來處理資料庫的,而不是實際的連接
  • 這個抽象包含了資料庫連接的池,而且會對此進行維護
  • 在使用 sql.DB 的時候,可以定義它的全域變數進行使用,也可以將它傳遞到函式/方法里,

如何獲得驅動

  • 正常的做法是使用 sql.Register() 函式、資料庫驅動的名稱和一個實作了 driver.Driver 介面的 struct,來注冊資料庫的驅動,例如:
    • sql.Register("sqlserver", &drv{})
  • 但是我們之前的例子卻沒寫這句話,為什么?
    • 因為 Sql Server 的驅動,是在這個包被引入的時候進行了自我注冊

驅動自動注冊

  • 當 go-mssqldb 包被引入的時候,它的 init 函式將會運行并進行自我注冊(在 Go 語言里,每個包的 init 函式都會在自動的呼叫)
  • 在引入 go-mssqldb 包的時候,把該包的名設定為下劃線 _,這是因為我們不直接使用資料庫驅動(只需要它的”副作用“),我們只使用 database/sql
    • 這樣,如果未來升級驅動,也無需改變代碼
  • Go 語言沒有提供官方的資料庫驅動,所有的資料庫驅動都是第三方驅動,但是它們都遵循 sql.driver 包里面定義的介面

安裝資料庫驅動

  • 這是安裝 Microsoft SQL Server 資料庫驅動的例子:
  • go get github.com/denisenkom/go-mssqldb

func(*DB) PingContext

  • 上例中的 db.PingContext() 函式是用來驗證與資料庫的連接是否仍然有效,如有必要則建立一個連接,
  • 這個函式需要一個 Context (背景關系)型別的引數,這種型別可以攜帶截止時間、取消信號和其它請求范圍的值,并且可以橫跨 API 邊界和行程,
  • 上例中,創建 context 使用的是 context.Background() 函式,該函式回傳一個非 nil 的空 Context,它不會被取消,它沒有值,沒有截止時間,
  • 它通常用在 main 函式、初始化或測驗中,作為傳入請求的頂級 Context,

Exercises

  • 使用 PostgreSQL 建立資料庫,使用 Go 語言進行連接,并 Ping 一下,
  • 使用 SQLite 建立資料庫,使用 Go 語言進行連接,并 Ping 一下,

連接MySQL

https://github.com/go-sql-driver/mysql

go get -u github.com/go-sql-driver/mysql

創建目錄

? mcd go_sql_demo

Code/go/go_sql_demo via ?? v1.20.3 via ?? base
? go mod init go_sql_demo
go: creating new go.mod: module go_sql_demo

Code/go/go_sql_demo via ?? v1.20.3 via ?? base
? c

Code/go/go_sql_demo via ?? v1.20.3 via ?? base
?

main.go

package main

import (
	"database/sql"
	"fmt"

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

// 定義一個全域物件db
var db *sql.DB

// 定義一個初始化資料庫的函式
func initDB() (err error) {
	// DSN:Data Source Name
	dsn := "root:12345678@tcp(127.0.0.1:3306)/db_xuanke?charset=utf8mb4&parseTime=True"
	// 不會校驗賬號密碼是否正確
	// 注意!!!這里不要使用:=,我們是給全域變數賦值,然后在main函式中使用全域變數db
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return err
	}
	// 嘗試與資料庫建立連接(校驗dsn是否正確)
	err = db.Ping()
	if err != nil {
		return err
	}
	return nil
}

func main() {
	err := initDB() // 呼叫輸出化資料庫的函式
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	fmt.Println("connect to database")
}

二、CRUD

查詢

  • sql.DB 型別上用于查詢的方法有:
    • Query
    • QueryRow
    • QueryContext
    • QueryRowContext

Query

  • 回傳的型別是:type Rows struct {}
  • Rows 的方法:
    • func (rs *Rows) Close() error
    • func (rs *Rows) ColumnTypes() ([]*ColumnType, error)
    • func (rs *Rows) Columns() ([]string, error)
    • func (rs *Rows) Err() error
    • func (rs *Rows) Next() bool
    • func (rs *Rows) NextResultSet() bool
    • func (rs *Rows) Scan(dest ...interface{}) error

QueryRow

  • 回傳型別是:type Row struct {}
  • Row 的方法有:
    • func (r *Row) Err() error
    • func (r *Row) Scan(dest ...interface{}) error

https://pkg.go.dev/database/[email protected]

services.go 檔案

package main

func getOne(id int) (a app, err error) {
  a = app{}
  log.Println(db == nil)
  err = db.QueryRow("SELECT Id, Name, Status, Level, [Order] FROM dbo.App WHERE Id=@Id", 				sql.Named("Id", id)).Scan(
    &a.ID, &a.name, &a.status, &a.level, &a.order)
  return
}

func getMany(id int) (apps []app, err error) {
  rows, err = db.Query("SELECT Id, Name, Status, Level, [Order] FROM dbo.App WHERE Id>@Id", 				sql.Named("Id", id))
  for rows.Next() {
    a := app{}
    err = rows.Scan(&a.ID, &a.name, &a.status, &a.level, &a.order)
    if err != nil {
      log.Fatalln(err.Error())
    }
    apps = append(apps, a)
  }
  return
}

models.go 檔案

package main

type app struct {
  ID int
  name string
  status int
  level int
  order int
}

main.go 檔案

package main

import (
  "context"
  "database/sql"
  "fmt"
  "log"
  
  _ "github.com/denisenkom/go-mssqldb"
)

var db *sql.DB

const (
  server = "xxxx.database.windows.net"
  port = 1433
  user = "xxxxx"
  password = "xxxxx"
  database = "go-db"
)

func main() {
  connStr := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;",
                        server, user, password, port, database)
  
  var err error
  db, err = sql.Open("sqlserver", connStr)
  if err != nil {
    log.Fataln(err.Error())
  }
  
  ctx := context.Background()
  
  err = db.PingContext(ctx)
  if err != nil {
    log.Fataln(err.Error())
  }
  
  fmt.Println("Connected!")
  
  log.Println(db == nil)
  // 查詢一筆
  one, err := getOne(103)
  if err != nil {
    log.Fatal(err.Error())
  }
  fmt.Println(one)
  
  apps, err := getMany(103)
  if err != nil {
    log.Fatalln(err.Error())
  }
  
  fmt.Println(apps)
}

更新

  • sql.DB 型別上用于更新(執行命令)的方法有:
    • Exec
    • ExecContext

services.go 檔案

func (a *app) Update() (err error) {
  _, err = db.Exec("UPDATE dbo.App SET Name=@Name, [Order]=@Order WHERE Id=@Id",
        sql.Named("Name", a.name), sql.Named("Order", a.order), sql.Named("Id", a.ID))
  if err != nil {
    log.Fatalln(err.Error())
  }
  return
}

main.go 檔案

a, _ := getOne(103)
fmt.Println(a)
a.name += " 1234"
a.order++

err = a.Update()
if err != nil {
  log.Fatalln(err.Error())
}
a1, _ := getOne(103)
fmt.Println(a1)

洗掉

services.go 檔案

func (a *app) Delete() (err error) {
  _, err = db.Exec("DELETE FROM dbo.App WHERE Id=@Id", sql.Named("Id", a.ID))
  if err != nil {
    log.Fatalln(err.Error())
  }
  return
}

其它

  • Ping
  • PingContext
  • Prepare
  • PrepareContext
  • Transactions
    • Begin
    • Begin Tx

services.go 檔案

func (a *app) Insert() (err error) {
  statement := `INSERT INTO dbo.App
  (Name, NickName, Status, Level, [Order], Pinyin) 
  VALUES (@Name, 'Nick', &Status, @Level, @Order, '...');
  SELE?T isNull(SCOPE_IDENTITY(), -1);`
  stmt, err := db.Prepare(statement)
  if err != nil {
    log.Fatalln(err.Error())
  }
  defer stmt.Close()
  err = stmt.QueryRow(
    sql.Named("Name", a.name), sql.Named("Status", a.status), 
    sql.Named("Level", a.level),
    sql.Named("Order", a.order)).Scan(&a.ID)
  
  if err != nil {
    log.Fatalln(err.Error())
  }
  
  return
}

main.go 檔案

a := app {
  name: "Test",
  order: 1123,
  level: 10,
  status: 1,
}

err = a.Insert()
if err != nil {
  log.Fatalln(err.Error())
}

one, _ := getOne(a.ID)
fmt.Println(one)

三、MySQL CRUD 實踐

在MySQL中創建一個名為sql_test的資料庫

mysql> create database sql_test;
Query OK, 1 row affected (0.01 sec)

mysql> use sql_test;
Database changed
mysql> CREATE TABLE `user` (
    ->     `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
    ->     `name` VARCHAR(20) DEFAULT '',
    ->     `age` INT(11) DEFAULT '0',
    ->     PRIMARY KEY(`id`)
    -> )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

mysql> show tables;
+--------------------+
| Tables_in_sql_test |
+--------------------+
| user               |
+--------------------+
1 row in set (0.01 sec)

mysql>

main.go 檔案

package main

import (
	"database/sql"
	"fmt"

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

// 定義一個全域物件db
var db *sql.DB

// 定義一個初始化資料庫的函式
func initDB() (err error) {
	// DSN:Data Source Name
	dsn := "root:12345678@tcp(127.0.0.1:3306)/sql_test?charset=utf8mb4&parseTime=True"
	// 不會校驗賬號密碼是否正確
	// 注意!!!這里不要使用:=,我們是給全域變數賦值,然后在main函式中使用全域變數db
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		return err
	}
	// 嘗試與資料庫建立連接(校驗dsn是否正確)
	err = db.Ping()
	if err != nil {
		return err
	}
	return nil
}

func main() {
	err := initDB() // 呼叫輸出化資料庫的函式
	if err != nil {
		fmt.Printf("init db failed,err:%v\n", err)
		return
	}
	fmt.Println("connect to database")

	// one, err := queryRowDemo(1)
	// if err != nil {
	// 	log.Fatal(err.Error())
	// }
	// fmt.Println(one)

	// u := user{
	// 	name: "小喬1",
	// 	age:  13,
	// 	id:   0,
	// }
	// err = u.insertRowDemo()
	// if err != nil {
	// 	log.Fatalln(err.Error())
	// }

	// u, _ := queryRowDemo(1)
	// fmt.Println("u:", u)
	// u.name = "貂蟬"
	// u.age = 16

	// err = u.updateRowDemo()
	// if err != nil {
	// 	log.Fatalln(err.Error())
	// }

	// u1, _ := queryRowDemo(1)
	// fmt.Println("u1:", u1)

	last_row, _ := queryMultiRowDemo(0)
	fmt.Println("last_row:", last_row)

	// var u = new(user)
	// u.id = 3
	// err = u.deleteRowDemo()
	// if err != nil {
	// 	log.Fatalln(err.Error())
	// }
}

services.go 檔案

package main

import (
	"fmt"
)

// 查詢單條資料示例
func queryRowDemo(id int) (u user, err error) {
	sqlStr := "select id, name, age from user where id=?"
	// 非常重要:確保QueryRow之后呼叫Scan方法,否則持有的資料庫鏈接不會被釋放
	err = db.QueryRow(sqlStr, id).Scan(&u.id, &u.name, &u.age)
	if err != nil {
		fmt.Printf("scan failed, err:%v\n", err)
		return
	}
	fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
	return
}

// 查詢多條資料示例
func queryMultiRowDemo(id int) (u user, err error) {
	sqlStr := "select id, name, age from user where id > ?"
	rows, err := db.Query(sqlStr, id)
	if err != nil {
		fmt.Printf("query failed, err:%v\n", err)
		return
	}
	// 非常重要:關閉rows釋放持有的資料庫鏈接
	defer rows.Close()
	// 回圈讀取結果集中的資料
	for rows.Next() {
		err = rows.Scan(&u.id, &u.name, &u.age)
		if err != nil {
			fmt.Printf("scan failed, err:%v\n", err)
			return
		}
		fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
	}
	return
}

// 插入資料
func (u *user) insertRowDemo() (err error) {
	sqlStr := "insert into user(name, age) values (?,?)"
	ret, err := db.Exec(sqlStr, u.name, u.age)
	if err != nil {
		fmt.Printf("insert failed, err:%v\n", err)
		return
	}
	theID, err := ret.LastInsertId() // 新插入資料的id
	if err != nil {
		fmt.Printf("get lastinsert ID failed, err:%v\n", err)
		return
	}
	fmt.Printf("insert success, the id is %d.\n", theID)
	return
}

// 更新資料
func (u *user) updateRowDemo() (err error) {
	sqlStr := "update user set age=? where id = ?"
	ret, err := db.Exec(sqlStr, u.age, u.id)
	if err != nil {
		fmt.Printf("update failed, err:%v\n", err)
		return
	}
	n, err := ret.RowsAffected() // 操作影響的行數
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%v\n", err)
		return
	}
	fmt.Printf("update success, affected rows:%d\n", n)
	return
}

// 洗掉資料
func (u *user) deleteRowDemo() (err error) {
	sqlStr := "delete from user where id = ?"
	ret, err := db.Exec(sqlStr, u.id)
	if err != nil {
		fmt.Printf("delete failed, err:%v\n", err)
		return
	}
	n, err := ret.RowsAffected() // 操作影響的行數
	if err != nil {
		fmt.Printf("get RowsAffected failed, err:%v\n", err)
		return
	}
	fmt.Printf("delete success, affected rows:%d\n", n)
	return
}

models.go 檔案

package main

type user struct {
	id   int
	age  int
	name string
}

運行

Code/go/go_sql_demo via ?? v1.20.3 via ?? base 
? go build . && ./go_sql_demo
connect to database
id:1 name:小喬 age:16
id:2 name:小喬 age:12
last_row: {2 12 小喬}

Code/go/go_sql_demo via ?? v1.20.3 via ?? base took 3.3s 
? 

本文來自博客園,作者:QIAOPENGJUN,轉載請注明原文鏈接:https://www.cnblogs.com/QiaoPengjun/p/17390319.html

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/552195.html

標籤:其他

上一篇:openAI發布v0.2.0了

下一篇:返回列表

標籤雲
其他(158836) Python(38128) JavaScript(25413) Java(18033) C(15226) 區塊鏈(8264) C#(7972) AI(7469) 爪哇(7425) MySQL(7177) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5338) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4570) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2432) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1972) 功能(1967) Web開發(1951) HtmlCss(1935) python-3.x(1918) C++(1915) 弹簧靴(1913) xml(1889) PostgreSQL(1875) .NETCore(1860) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Go語言(Golang)資料庫編程

    Go 資料庫編程 一、連接資料庫 準備連接到資料庫 要想連接到 SQL 資料庫,首先需要加載目標資料庫的驅動,驅動里面包含著于該資料庫互動的邏輯。 sql.Open() 資料庫驅動的名稱 資料源名稱 得到一個指向 sql.DB 這個 struct 的指標 sql.DB 是用來操作資料庫的,它代表了0 ......

    uj5u.com 2023-05-12 08:00:34 more
  • openAI發布v0.2.0了

    時隔20天,OpenAI從v0.0.1升級到了v0.2.0。與v0.0.1版相比,v0.2.0版主要做了以下改動: 把cmd目錄下微信公眾號的相關服務遷移到了這里 完善了cmd下的測驗服務,針對openAI庫里實作的各個介面都提供了回應的呼叫介面,服務運行后可以通過postman進行測驗 完成了Fi ......

    uj5u.com 2023-05-12 08:00:27 more
  • spring-transaction原始碼分析(3)Transactional事務失效原因

    問題概述 在Transactional方法中使用this方式呼叫另一個Transactional方法時,攔截器無法攔截到被呼叫方法,嚴重時會使事務失效。 類似以下代碼: @Transactional public void insertBlogList(List<Blog> blogList) { ......

    uj5u.com 2023-05-12 08:00:18 more
  • Fast-GRPC: 用python輕松開發grpc介面

    簡介 Fast-GRPC 旨在幫助開發者更加輕松快捷地使用 Python 開發 gRPC 介面。它的特點包括簡化步驟、簡單上手、快速開發,同時支持異步和同步代碼,以及支持 middleware,靈感來自FastAPI。 安裝 需要python 3.7+ pip install python-fast ......

    uj5u.com 2023-05-12 07:59:32 more
  • 用Python實作藝識訓畫,人生苦短,代碼賽高

    #用Python實作藝識訓畫 藝識訓畫是一個創造性的程序,包括繪畫、素描和繪畫。借助Python編程語言,您可以模擬藝識訓畫的程序。該程序包括以下步驟: 1.匯入所需的庫-您需要匯入NumPy、OpenCV和Matplotlib等庫來執行影像處理任務。 2.加載影像-您可以使用OpenCV加載影像。 ......

    uj5u.com 2023-05-12 07:59:28 more
  • Python工具箱系列(三十一)

    Neo4j是一個高性能的開源的,使用Java語言實作的NoSQL圖資料庫,它將結構化資料存盤在網路上而不是表中。它是一個嵌入式的、基于磁盤的、具備完全的事務特性的Java持久化引擎,但是它將結構化資料存盤在網路(從數學角度叫做圖)上而不是表中。 ......

    uj5u.com 2023-05-12 07:59:14 more
  • 用tk.mybaits實作指定欄位更新

    ? 去年年底的因為業務需要需要在使用tk.mybaits框架的系統中實作指定欄位的更新,可是tk.mybaits框架本身并不支持這個功能,我翻遍了CSDN和其他相關的技術相關的網站都沒有找到相關的解決方法。于是我通過幾天的翻閱相關資料和摸索后終于實作了這個功能。最近事情不是很多,想到又想到了去年解決 ......

    uj5u.com 2023-05-12 07:58:43 more
  • 存下吧!Spring高頻面試題總結

    Spring是什么? Spring是一個輕量級的控制反轉(IoC)和面向切面(AOP)的容器框架。 Spring的優點 通過控制反轉和依賴注入實作松耦合。 支持面向切面的編程,并且把應用業務邏輯和系統服務分開。 通過切面和模板減少樣板式代碼。 宣告式事務的支持。可以從單調繁冗的事務管理代碼中解脫出來 ......

    uj5u.com 2023-05-12 07:57:17 more
  • Spring MVC官方檔案學習筆記(一)之Web入門

    注: 該章節主要為原創內容,為后續的Spring MVC內容做一個先行鋪墊 1.Servlet的構建使用 (1) 選擇Maven -> webapp來構建一個web應用 (2) 構建好后,打開pom.xml檔案,一要注意打包方式為war包,二匯入servlet依賴,如下 <!-- 打war包 --> ......

    uj5u.com 2023-05-12 07:56:59 more
  • docker(一):Develop faster. Run anywhere.

    Docker 是一個開源的應用容器引擎,可以讓開發者將應用程式打包成一個容器,并通過容器來部署、運行和管理應用程式。Docker 的核心概念包括容器和鏡像。容器是鏡像的可運行實體,可以通過 Docker API 或 CLI 來創建、啟動、停止、移動或洗掉容器。鏡像是一個只讀模板,包含了創建 Dock... ......

    uj5u.com 2023-05-12 07:51:36 more