Use go to encapsulate a handy ORM

Source: Internet
Author: User
Tags bulk insert
This is a creation in Article, where the information may have evolved or changed. # using go to package a convenient ORM recently in the go to write a Web development framework, see some ORM, most of the need to join their own SQL, for me this used to ' Laravel ' people, it is a bit awkward, so I want to write an ORM, It is convenient for the database to be coherent operation because of the code too much, do not post, only to talk about ideas, the specific code here [Silsuer/bingo] (Https://github.com/silsuer/bingo) # # ideas 1. Determine the final effect I want to make like ' Laravel ', the operation database is probably the ' db::table (dbName)->where (' id ', 1)->get () ' 2. Coherent operation principle to make this kind of coherent operation effect, in addition to the end of the method, the middle successive calls of those methods must return an identical object 3. Defining database objects in this case, first define a ' MySQL ' Structure of ' go//MySQL structure, used to store SQL statements and execute type Mysql struct {connection *sql. DB//Database connection object SQL string//The final statement to execute Wheresql string//Where statement Limitsql string//Limit statement Columnsql string//Select in the column language Sentence Tablesql string//Table name statement Orderbysql string//ORDER BY Statement Groupbysql string//GROUP BY Statement Havingsql string//Having statement TA Blename string//Table name Tableschema string//database, useful Errors when caching table structure []ERROR//Save error result SQL that can occur in a coherent operation. Result//Save execution Statement results after Rows *sql. Rows//Saves row Results []sql] After executing a multiline query statement. Result Row *sql. Row//Save line//res []map[string]interface{}//To generate a map} ' for each successive call, we just need to return the pointer to the current struct. 4.Connect to a database for convenience, define a ' DB () ' function in the public function, which returns a database object (pointer) ' Go func DB (interface{}} {///return a drive operation class//Incoming DB configuration env DRI Ver, instantiate different classes, singleton mode, get unique driver if Driver = = nil {driverinit ()} Con: = Driver.getconnection ()//Get database connection return con} ' can see, for To save resources, our database connection and drive connection are singleton mode, only allowed to exist once the following is the Initialize database driver method ' Driverinit () ' ' Go//Database driver type driver struct {name string/driver name Dbco Nfig string//configuration}//Driver initialization func Driverinit () {Driver = &driver{} driver.name = strings. ToUpper (Env.get ("Db_driver")) switch Driver.name {case "MYSQL": After initializing the drive, start initializing the database connection Driver.dbconfig = Env.get ("Db_ USERNAME ") +": "+ env.get (" Db_password ") +" @tcp ("+ Env.get (" db_host ") +": "+ env.get (" Db_port ") +") "+"/"+ Env.get ( "Db_name") + "?" + "charset=" + env.get ("Db_charset") Break Default:break} "" When we initialize the driver, we will determine what kind of database is used in the configuration file and then splice it according to the database. A string that connects to the database so that our ORM can support multiple databases to provide a possible configured string to do, the next step is to start getting a singleton connection to the database "go//Based on database driver, get database connection func (d *driver) getconnection ( ) interface{} {switch D.name {case "MySQL": M: = MySQL. Mysql{}//Instantiate struct M.tableschema = Env.get ("db_name")//Database name M.init (driver.dbconfig)//Set table name and database connection return &M//Return instance Brea K Default:break} return nil} "' Gets the connection when first creating a database object, and then assigns some basic information to the object's corresponding property, the ' Init ' method obtains the unique connection of this person's database: ' ' Go func (M *mysql ) Init (config string) {//Get a singleton connection m.connection = getinstanceconnection (config)//Get database connection} var once sync. Once//sets the database connection of the Singleton to Func getinstanceconnection (config string) *sql. DB {once. Do (func () {//Only once db, err: = SQL. Open ("MySQL", config) if err! = Nil {panic (ERR)} conn = db}) return conn} ' Once.do ' is a method provided in the ' sync ' package that allows the code to execute only once so we get The connection to the database is taken, and then the connection is placed in the ' Mysql ' object ' connection ' and returned to 5. To perform a coherent operation note that because the database we are using is different, ' DB () ' Returns a ' interface{} ', so we need to re-switch to ' *mysql. Mysql ': ' Go bingo. DB (). (*mysql. MySQL) Next, you just need to define a variety of ' Mysql ' struct methods, and then return this struct pointer on it, space problem, write only one of the simplest in the ' Test ' table query ' id>1 ' data, the code effect is this: ' Go res:= Bingo. DB (). (*mysql. Mysql). Table ("Test"). Where ("id", ">", 1). Get () ' ' First, write the ' Table ' method, just assign a value to the Mysql object: ' Go/Initialize some SQL value func (M *mysql) Table (tableName String) *mysql {m.tablesql = "" + TableName + "" M.wheresql = "" M.columnsql = "*" M.tablename = tableName return m } ' then write the ' Where ' method, which is slightly more complicated, if the two parameters are passed, then they are equal to the relationship, if it is three parameters then the second parameter is their direct relationship ' go func (M *mysql) Where (args ... interface{}) *mysql {//To get the field type based on the name of the field passed in, and then to determine whether the third parameter is to be quoted//up to three parameters A=b//First determine where SQL has no where a=b CIF: = M.gettabl Einfo (). Info//First determine if this field exists in the table, and if so, get the type get value such as cType: = "" If _, OK: = Cif[converttostring (Args[0]); OK {cType = cif[converttostring (Args[0])]. Type} else {m.errors = append (M.errors, Errors. New ("Cannot find a column named" +converttostring (Args[0]) + "in" +m.tablename+ "table") return m//terminate this function} var ifwhere BOOL Wherearr: = Strings. Fields (M.wheresql) If Len (wherearr) = = 0 {//Empty Ifwhere = false} else {if strings. ToUpper (wherearr[0]) = = "where" {Ifwhere = TRUE//exists where} else {Ifwhere = false//does not exist where}} switch Len (args) {CA SE 2://have where only need to write a=b if Ifwhere {//If it is a string type, quote if Isstring (cType) {m.wheresql = M.wheresql + ' and ' + converttostring (args[0]) + ' = ' + converttostring (args[1]) + '} else {m.wheresql = M.wheresql + ' and ' + ConvertToString (Args[0]) + ' = ' + converttostring (Args[1])}} else {//no where to write where a=b if Isstring (cType) {M.where SQL = ' where ' + converttostring (args[0]) + ' = ' + converttostring (args[1]) + '} else {m.wheresql = ' where ' + conve Rttostring (Args[0]) + ' = ' + converttostring (Args[1])}} break Case 3://There is a where only need to write a=b if Ifwhere {//If it is a string type, quoted if Isstring (cType) {m.wheresql = M.wheresql + ' and ' + converttostring (args[0]) + converttostring (args[1]) + "+ Convertt Ostring (args[2]) + "} else {m.wheresql = M.wheresql + ' and ' + converttostring (args[0]) + converttostring (args[1]) + ConvertToString (Args[2])}} else {//There is no where to write where a=b if Isstring (cType) {m.wheresql = ' where ' + converttostring ( Args[0]) + converttostring (args[1]) + ' + converttostring (args[2]) + '} else {m.wheresql = ' WHERE ' + Converttostri Ng (Args[0]) + ConverttosTring (args[1]) + converttostring (args[2])}} break default:m.errors = Append (M.errors, Errors. New ("Missing args length in where function")} return M} "" I used the ' gettableinfo () ' method, which is to get the structure of the current table, in order to quickly perform operations on the table, or Filter out the table does not exist fields need to cache the structure of the table, the column name and column type cache, the specific code is not affixed, here [cache table structure] (https://github.com/silsuer/bingo/blob/master/drivers/db/mysql /INSERT.GO) then will be based on the ' Mysql ' struct ' wheresql ' field, stitching the new ' Wheresql ', and re-assigning the value Next, write ' Get () ' method, execute the last SQL statement can ' go/query data func (M *mysql ) Get () *mysql {m.sql = "select" + M.columnsql + "from" + m.tablesql + m.wheresql + m.limitsql + m.orderbysql rows, err : = M.connection.query (M.sql) m.checkappenderror (err) m.rows = Rows return m} ' first splicing the statement, then executes the native Query method, placing the execution result in the struct. We get the structure and we can hit it out and see "go/Get all data in the test table with IDs greater than 1 res:= bingo. DB (). (*mysql. Mysql). Table ("Test"). Where ("id", ">", 1). Get ()//Determine if execution is wrong if Len (res. Errors)!=0{FMT. Fprintln (W, "Execution Error! ")}//execute successfully and start traversing for Res. Rows.next () {var id,age int var name string res. Rows.scan (&id,&name,&age) fmt. Fprintln (W, "ID:"+strconv. Itoa (ID) + "name:" +name+ "Age:" +strconv. Itoa (age)} "6. Summary due to the space problem, I only wrote the simplest conditional query, the other can go to [GitHub] (Https://github.com/silsuer/bingo) to see the current implementation is: 1. Create DATABASE 2. Create data Table 3. Insert Data (4 ways: Insert a piece of data, insert a piece of data and filter out extra fields, BULK insert data, BULK Insert data and filter extra fields) 4. Update data (3 ways: Update One piece of data, update one data and filter out extra fields, batch update data and filter extra fields) 5. Query data (conditional query, limit, order BY, etc.) 6. Delete Data 7. Delete Data Table (2 methods: Delete Delete, truncate empty) 8. Clears all table information in the database without deleting table 9. Clear the database and delete all table 10. The Delete data table will be implemented with: 1. Correlation Query 2. Join Query 3. Group Query 4. Quick Paging 5. Database Migration 7. Specific usage please go to see the readme, time problem, write a little messy, and so this thing will be re-finishing a document after the last sentence, seeking star, the brand ~~~ヾ (*´▽ ' *) Dentetsu 424 reads  ∙  1 likes  

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.