Gorm及XML库的使用|青训营笔记

103 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第7天

该项目前两篇的地址 第一篇 第二篇

Gorm及XML库的使用|青训营笔记——将数据从XML文件写到数据库(改进)

改进将数据从XML文件到数据库
  • 第一步仍然是读入文件并反序列化

    //读入文件并反序列化
    	file, err := ioutil.ReadFile(filePath)
    	if err != nil {
    		return err
    	}
    	var c = Contacts{}
    	err1 := xml.Unmarshal(file, &c)
    	if err1 != nil {
    		return err1
    	}
    
  • 进行数据的检验

    这里将读入文件中含有相同电话号码视为数据有错误,读入的数据和数据库中数据有相同的电话号码视为修改

    • 检验读入文件中的数据

      将一个个数据放在map中,如果该电话号码没有被标记为true则标记为true,如果被标记过则直接返回error

      //校验文件
      	m := make(map[string]bool)
      	for _, v := range c.C {
      		phone := v.Phone
      		if m[phone] == true {
      			return fmt.Errorf("输入的数据有误")
      		}
      		m[phone] = true
      	}
      
    • 对比读入文件中的数据与数据库中的数据

      执行到了这一步,在上面的检验中,所有的phone都被记录到map中并标记为true,现在我们只需要拿到数据库中的数据,如果数据中的phone字段在map中被标记为true,则将该电话标记改为false用来和需要重新创建的数据作为区别

      //校验数据库中是否有相同的电话号码
      	fromDB := FromDB(db)//从数据库中读取文件
      	for _, v := range fromDB {
      		//复用m
      		if m[v.Phone] == true { //这里将需要改变的标记为false
      			m[v.Phone] = false
      		}
      	}
      
  • 将需要创建的值和更改的值放到不同的slice中

    逐个对比从XMl文件中读入的数据与map中的标记

    //将需要创建的值和更改的值放到不同的slice中
    	//这里还需要将从XML文件中读入的数据转存到数据库对应的结构体中
    	createSlice := make([]ContactsModel, 0)
    	updateSlice := make([]ContactsModel, 0)
    	for _, v := range c.C {
    		if m[v.Phone] == true {
    			createSlice = append(createSlice,
    				struct {
    					gorm.Model
    					Name  string
    					Sex   string
    					Phone string
    				}{Name: v.Name, Sex: v.Sex, Phone: v.Phone})
    			continue
    		}
    		updateSlice = append(updateSlice,
    			struct {
    				gorm.Model
    				Name  string
    				Sex   string
    				Phone string
    			}{Name: v.Name, Sex: v.Sex, Phone: v.Phone})
    	}
    
  • 利用gorm执行创建和修改操作

    //利用gorm执行创建和修改操作
    	if len(createSlice) != 0 {
    		db.Model(&ContactsModel{}).Create(&createSlice)
    	}
    	for _, v := range updateSlice {
    		db.Model(&ContactsModel{}).Where("phone=?", v.Phone).Updates(v)
    	}
    
  • 在上一步中可能在执行数据库操作的某一部出错,有的数据已经执行了操作,有的没有正确执行,我们可以打开数据库事务来保证数据的一致性

    db.Transaction(func(tx *gorm.DB) error {
    		if len(createSlice) != 0 {
    			result := tx.Model(&ContactsModel{}).Create(&createSlice)
    			if result.Error != nil {
    				return result.Error
    			}
    		}
    		for _, v := range updateSlice {
    			result := tx.Model(&ContactsModel{}).Where("phone=?", v.Phone).Updates(v)
    			if result.Error != nil {
    				return result.Error
    			}
    		}
    		return nil
    	})
    

    如果返回的不是nil,gorm会自动执行数据库回滚操作

  • 我们执行一遍操作得到的output.xml文件中有乱码

    <Contacts>
        <contact sex="M">
            <name>&#xA;            张三&#xA;        </name>
            <phone>11111111111</phone>
        </contact>
        <contact sex="W">
            <name>&#xA;            李四&#xA;        </name>
            <phone>22222222222</phone>
        </contact>
        <contact sex="M">
            <name>&#xA;            王五&#xA;        </name>
            <phone>44444444444</phone>
        </contact>
    </Contacts>
    

    这是由于写入的时候没有处理空格和换行符引起的,这里我们添加一个函数作为处理

    //去除字符串中的空格和换行符
    func replaceString(s string) (newString string) {
    	s = strings.Replace(s, "\n", "", -1)
    	newString = strings.Replace(s, " ", "", -1)
    	return
    }
    

    并将“将需要创建的值和更改的值放到不同的slice中”这一步操作修改为

    createSlice := make([]ContactsModel, 0)
    	updateSlice := make([]ContactsModel, 0)
    	for _, v := range c.C {
    		temp := ContactsModel{
    			Name:  replaceString(v.Name),
    			Sex:   replaceString(v.Sex),
    			Phone: replaceString(v.Phone),
    		}
    		if m[v.Phone] == true {
    			createSlice = append(createSlice, temp)
    			continue
    		}
    		updateSlice = append(updateSlice, temp)
    	}
    

代码地址

[code] github.com/Tian2002/xm…