mongoose入门

news/2024/5/12 6:36:30/文章来源:https://blog.csdn.net/qq_38930804/article/details/137558197

来源(书栈小编注)

MongoDB是一个开源的NoSQL数据库,相比MySQL那样的关系型数据库,它更显得轻巧、灵活,非常适合在数据规模很大、事务性不强的场合下使用。同时它也是一个对象数据库,没有表、行等概念,也没有固定的模式和结构,所有的数据以文档的形式存储(文档,就是一个关联数组式的对象,它的内部由属性组成,一个属性对应的值可能是一个数、字符串、日期、数组,甚至是一个嵌套的文档。),数据格式就是JSON。
假定读者已经了解了mongdb和mysql的区别和为什么选用mongodb,继而介绍nodejs里的mongoose模块进行实战,具体分4步骤

  • mongoose是什么?
  • mongoose入门
  • mongoose概念
  • mongoose crud

Mongoose是什么?

Mongoose是MongoDB的一个对象模型工具,是基于node-mongodb-native开发的MongoDB nodejs驱动,可以在异步的环境下执行。同时它也是针对MongoDB操作的一个对象模型库,封装了MongoDB对文档的的一些增删改查等常用方法,让NodeJS操作Mongodb数据库变得更加灵活简单。
Mongoose,因为封装了对MongoDB对文档操作的常用处理方法,可以高效的操作mongodb,同时可以理解mongoose是一个简易版的orm ,提供了类似schema定义,hook、plugin、virtual、populate等机制,让NodeJS操作Mongodb数据库变得特别简单!
以往书中往往直接上例子,混合各种库和代码,容易让人晕,必须在例子中才能知道m是如何使用的,我一直认为这是不合理的,为什么我要掌握其他的知识才能学mongoose?
其实,它也仅仅是一个node模块而已。
官网:http://mongoosejs.com/

mongoose入门

前面我们已经认识了Mongoose,也了解了MongoDB,回顾一下:MongoDB是一个对象数据库,是用来存储数据的;Mongoose是封装了MongoDB操作的一个对象模型库,是用来操作这些数据的。
好,下面我们就来进行操作数据的第一步吧。

准备

1、 安装mongoose

npm install --save mongoose

2、 引用mongoose

var mongoose = require("mongoose");

3、 使用”mongoose”连接数据库

var db = mongoose.connect("mongodb://user:pass@ip:port/database");

说明

  • user 是mongodb里用户名
  • pass 是mongodb里用户对应的密码
  • ip 是mongodb服务器可以访问ip地址,比如本地为127.0.0.1
  • port 是mongodb服务器可以访问端口,默认是27017

测试

执行下面代码检查默认数据库test,是否可以正常连接成功?

var mongoose = require("mongoose");
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld"); 
db.connection.on("error", function (error) {  console.log("数据库连接失败:" + error); 
}); 
db.connection.on("open", function () {  console.log("数据库连接成功"); 
});

执行代码

node connect.js
数据库连接成功
数据库连接失败:MongoError: connect ECONNREFUSED 127.0.0.1:27017

最小demo

这里给出极简demo,用于讲解mongoose从连接数据库到对数据库进行操作完整过程,这样更容易让读者了解核心原理,代码如下

// 1、引入`mongoose`模块
var mongoose = require('mongoose');
// 2、通过`mongoose.connect`连接mongodb数据库
mongoose.connect('mongodb://127.0.0.1/db_helloworld');
// 3、通过`mongoose.model`定义模型(model)
var Cat = mongoose.model('Cat', { name: String });
// 4、通过`new`关键字实例化Cat模型,参数是`{ name: 'Zildjian' }`,创建kitty对象
var kitty = new Cat({ name: 'Zildjian' });
// 5、执行`kitty.save`来保存到数据库
kitty.save(function (err) {if (err) {console.log('save error:' + err);}console.log('save sucess');
});

核心步骤说明

  • 定义模型(model)
  • 通过new关键字实例化Cat模型,创建kitty对象
  • 执行kitty.save来保存到数据库

这个其实就是mongoose最常见的用法,首先约定schema,即在模型model定义的时候指定字段和字段类型,避免乱用schema-free问题。之后对实例化模型创建的对象进行操作,完成我们常见的增删改查功能。

模型(model)定义即定义对象,对象操作即对数据库进行操作

执行如下

node helloworld.js

如无错误日志,即代表数据保存成功。此时打开robo mongodb客户端查看一下具体数据是否保存成功。

实例

  • 连接数据库信息放到独立文件里
  • 模型定义放到独立文件
  • 在具体调用的文件里,使用模型定义

连接数据库

看一下实际代码,db/mini/connect.js

var mongoose = require("mongoose");
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld"); 
db.connection.on("error", function (error) {  console.log("数据库连接失败:" + error); 
}); 
db.connection.on("open", function () {  console.log("数据库连接成功");
});

一般项目里,所有模型都共用一个数据库连接信息,所以把连接数据库的代码抽取到connect.js里,然后在对应的模型里会app入口引用即可。

模型定义

看一下实际模型定义代码,db/mini/user.js

var mongoose = require('mongoose');
// 定义Schema
UserSchema = new mongoose.Schema({username: {// 真实姓名type: String,required: true},password: { // 密码type: String,required: true}
});
// 定义Model
var UserModel = mongoose.model('User', UserSchema);
// 暴露接口
module.exports = UserModel;

这是MVC里Model层最长见的代码,没有连接信息,也没有其他额外不相干代码,当你看到user.js你就能理解它在数据库里对应的表结构,以及字段的类型、约束等信息,一般来说,代码写的越干净,可读性会更好一些。
这里定义的User模型里只有 用户名 和 密码 2个字段,它们都必须有值的,也就是说当你创建用户的时候,没有密码或者没有用户名你是无法创建成功的。

测试代码

看一下实际代码db/mini/user.js

// 1、引入`mongoose connect`
require('./connect');
// 2、引入`User` Model
var User = require('./user');
// 3、定义`user` Entity
var user = new User({username: 'i5ting',password: '0123456789'
});
// 4、对数据库进行操作
user.save(function(err, doc){if (err) {console.log('save error:' + err);}console.log('save sucess \n' + doc);
})

核心步骤

  • 引入数据库连接,保证mongodb已经连接成功
  • 引入模型(model)定义文件,即文档(表)结构定义
  • 实例化UserModel,创建user实体
  • 最后通过user实体对数据库进行操作,完成用户注册功能。

这是项目里数据访问层的代码,它真实的对数据库进行操作,所以它一般会出现在controller或service层。

执行测试

node db/mini/test.js 
数据库连接成功
save sucess 
{ _id: 57341fc54d97ee0249082a1d,password: '0123456789',username: 'i5ting',__v: 0 }

概念

结合上面的实例来讲4个核心概念,以便于理解

  • ORM 对象关系映射
  • Schema
  • Model 模型
  • Entity 实体

对象关系映射

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。如今已有很多免费和收费的ORM产品,而有些程序员更倾向于创建自己的ORM工具。
面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。
对象关系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。
ORM方法论基于三个核心原则:

  • 简单:以最基本的形式建模数据。
  • 传达性:数据库结构被任何人都能理解的语言文档化。
  • 精确性:基于数据模型创建正确标准化的结构。

典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。
让我们从O/R开始。字母O起源于 对象(OBJECT),而R则来自于 关系(RELATIONAL)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
最简单的理解:

  1. ORM是让用语言中的对象来操作数据库,至于如何实现就是orm工具实现的,可以理解mongoose是orm工具。

mongoose包括以下四部分:

  • 一个对持久类对象进行CRUD操作的API,可以理解为实体Entity上的方法
  • 一个语言或API用来规定与类和类属性相关的查询,比如Population
  • 一个规定MAPPING METADATA的工具,可以理解为Schema定义
  • 一种技术可以让ORM的实现各种db操作的封装

Schema

Everything in Mongoose starts with a Schema. Each schema maps to a MongoDB collection and defines the shape of the documents within that collection.
Schema是一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力,仅仅只是定义数据库模型在程序片段中的一种表现,可以说是数据属性模型(传统意义的表结构),又或着是“集合”的模型骨架。
最简单的理解:

  1. Schema是对文档(表)结构的定义

那如何去定义一个Schema呢,请看示例:

// 定义Schema
UserSchema = new mongoose.Schema({username: {// 真实姓名type: String,required: true},password: { // 密码type: String,required: true}
});

基本属性类型有:字符串、日期型、数值型、布尔型(Boolean)、null、数组、内嵌文档等,当然它还有更丰富的对字段进行校验约束的功能。

参考:https://mongoosejs.com/docs/schematypes.html

模型(Model)

Models are fancy constructors compiled from our Schema definitions. Instances of these models represent documents which can be saved and retrieved from our database. All document creation and retrieval from the database is handled by these models.
模型(Model)是由Schema构造生成的模型,除了Schema定义的数据库骨架以外,还具有数据库操作的行为,类似于管理数据库属性、行为的类。
如何通过Schema来创建Model呢,如下示例:

var db = mongoose.connect("mongodb://127.0.0.1:27017/test");  
// 创建Model 
var TestModel = db.model("test1", TestSchema);
// 定义Model
var UserModel = mongoose.model('User', UserSchema);

User是模型名称,它对应到mongodb里就是数据库中的集合名称,默认会转成复数,变为’users’,当我们对其添加数据时如果users已经存在,则会保存到其目录下,如果未存在,则会创建users集合,然后在保存数据。
拥有了Model,我们也就拥有了操作数据库的金钥匙,在后面的内容中,我们就会学习使用Model来进行增删改查的具体操作,所以,一定要熟悉他的创建格式哟!
如果你想对某个集合有所作为,那就交给Model模型来处理吧,创建一个Model模型,我们需要指定:1.集合名称,2.集合的Schema结构对象,满足这两个条件,我们就会拥有一个操作数据库的金钥匙。

实体(Entity)

Mongoose documents represent a one-to-one mapping to documents as stored in MongoDB. Each document is an instance of its Model.
实体(Entity)是由Model创建的实体,使用save方法保存数据,Model和Entity都有能影响数据库的操作,但Model比Entity更具操作性。
使用Model创建Entity,如下示例:

var user = new User({username: 'i5ting',password: '0123456789'
});
console.log(user.username); // i5ting 
console.log(user.password); //0123456789

创建成功之后,Schema属性就变成了Model和Entity的公共属性了。

总结

Schema是骨架,模型(model)是根据Schema创建的模板,也就是说Schema和Model是定义部分,而实体Entity是模型实例化后创建的对象,它才是真正对数据库进行操作的。
所以我们会把定义部分(Schema + model)和实体操作部分(Entity)分开,定义是不变的,而实体是对数据库进行操作,操作类是术语可变的,所以在mvc分层的时候model实际放的是定义部分,而在controller里使用的是实体操作部分的。
基于前面的内容,接下来我们就开始学习对数据的具体操作了,下面是关于一些基础数据的定义,相信对于你来说已经不陌生了,请在仔细温习一遍吧!

CRUD(增删改查)

  • CRUD(增删改查)
    • 增加(Create)
    • 读取(Retrieve)
      • find:根据条件查询,返回的是数组
      • findOne:根据条件查询,返回的是一条数据对象
    • 更新(Update)
      • findByIdAndUpdate:根据ID查找并更新
      • findOneAndUpdate:根据查询条件查找并更新
    • 删除(Delete)
    • 执行测试
    • 调试模式

CRUD为数据库的最常见的4种基本操作,即增加(Create)、读取(Retrieve)(重新得到数据)、更新(Update)和删除(Delete)几个单词的首字母简写。主要被用在描述软件系统中数据库或者持久层的基本操作功能。
mongoose提供如下的crud方法

  • save
  • find | findOne
  • update
  • remove

下面我们使用user模型为例,给出具体例子

增加(Create)

文档

Model#save(product,)
@description Saves this document.
Parameters:
- product, <function(err, > Number)} [fn] optional callback
Returns:<Promise> Promise

code

const user = new User({username: 'i5ting',password: '0123456789'
});
user.save((err, u) => {t.false(err);t.is(u.username, 'i5ting');
});

读取(Retrieve)

find:根据条件查询,返回的是数组

文档

Model.find(conditions, [fields], [options], [callback])
Finds documents
Parameters:
- conditions <Object>
- [fields] <Object> optional fields to select
- [options] <Object> optional
- [callback] <Function>
Returns:<Query>

code

User.find({}, (err, docs) => {t.false(err);t.is(docs.length, 1);t.is(docs[0].username, 'i5ting');
});

findOne:根据条件查询,返回的是一条数据对象

文档

Model.findOne([conditions], [fields], [options], [callback])
Finds one document.
Parameters:
- [conditions] <Object>
- [fields] <Object> optional fields to select
- [options] <Object> optional
- [callback] <Function>
Returns:<Query>

code

User.findOne({username: 'i5ting'}, (err, doc) => {t.false(err);t.is(doc.length, 1);t.is(doc.username, 'i5ting');
});

更新(Update)

findByIdAndUpdate:根据ID查找并更新

文档说明如下

Model.findByIdAndUpdate(id, [update], [options], [callback])
Issues a mongodb findAndModify update command by a documents id.
show code
Parameters:
- id <ObjectId, HexId> an ObjectId or string that can be cast to one.
- [update] <Object>
- [options] <Object>
- [callback] <Function>
Returns:<Query>

code

 User.findByIdAndUpdate(u._id, {username: 'sang',
}, (err, user) => {t.false(err);t.is(user.username, 'sang');
});

findOneAndUpdate:根据查询条件查找并更新
Model.findOneAndUpdate([conditions], [update], [options], [callback])
Issues a mongodb findAndModify update command.
Parameters:
- [conditions] <Object>
- [update] <Object>
- [options] <Object>
- [callback] <Function>
Returns:<Query>

code

User.findOneAndUpdate({username: 'i5ting for update 2',
}, {username: 'sang',
}, (err, user) => {t.false(err);t.is(user.username, 'sang');
});

删除(Delete)

文档

Model.remove(conditions, [callback])
Removes documents from the collection.
Parameters:
- conditions <Object>
- [callback] <Function>
Returns:<Promise> Promise

code

User.remove({username: 'i5ting for delete'}, (err, doc) => {t.false(err);t.is(doc.result.ok, 1);t.is(doc.result.n, 1);
});

执行测试

调试模式

调试模式是mongoose提供的一个非常实用的功能,用于查看mongoose模块对mongodb操作的日志,一般开发时会打开此功能,以便更好的了解和优化对mongodb的操作。
打开调试的核心代码是设置 debug 变量值为 true 即可

var mongoose = require("mongoose");
// 核心代码,是否开启测试
mongoose.set('debug', true);
var db = mongoose.connect("mongodb://127.0.0.1:27017/db_helloworld"); 
db.connection.on("error", function (error) {  console.log("数据库连接失败:" + error); 
}); 
db.connection.on("open", function () {  console.log("数据库连接成功");
});
数据库连接成功
Mongoose: users.remove({}) {}#save()#find() return array✔ #findById() return array✔ #findOne() return user obj✔ #remove()#findByIdAndUpdate()#findOneAndUpdate()
Mongoose: users.insert({ username: 'i5ting', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d4"), __v: 0 })   
Mongoose: users.find({}) { fields: undefined }  
Mongoose: users.findOne({ username: 'i5ting' }) { fields: undefined }  
Mongoose: users.insert({ username: 'i5ting for delete', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d5"), __v: 0 })   
Mongoose: users.insert({ username: 'i5ting for update 1', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d6"), __v: 0 })   
Mongoose: users.insert({ username: 'i5ting for update 2', password: '0123456789', _id: ObjectId("5734490640caa6d36906b8d7"), __v: 0 })   
Mongoose: users.remove({ username: 'i5ting for delete' }) {}  
Mongoose: users.findAndModify({ _id: ObjectId("5734490640caa6d36906b8d6") }) [] { '$set': { username: 'sang' } } { new: false, upsert: false }
Mongoose: users.findAndModify({ username: 'i5ting for update 2' }) [] { '$set': { username: 'sang' } } { new: false, upsert: false }

总结

从mongoose是什么,到如何使用,以及核心概念(orm以及schema、model、entity),最后给出CRUD操作,希望读者能够认真体会orm和具体分层含义。
本节以最简单的user,结合ava完成单元测试,我们测试数据库代码并不一定要在koa或其他框架内部,最小化问题,mongoose它只是一个node模块,这样对于我们理解它是比较好的方式。接下来我们会讲解更多高级mongoose技巧,它们的基础都是本节内容,所以本节必须掌握,是本章重点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_1045676.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创新指南|贝恩的产品经理RAPID框架:解决问题的分步指南,使决策过程既高效又民主

您是否曾发现自己陷入项目的阵痛之中&#xff0c;决策混乱、角色不明确、团队成员之间的冲突不断升级&#xff1f;作为产品经理&#xff0c;驾驭这艘船穿过如此汹涌的水域可能是令人畏惧的。应对这些挑战的关键在于采用清晰、结构化的决策方法。输入贝恩的 RAPID 框架&#xff…

Linux文件搜索工具(gnome-search-tool)

opensuse下安装: sudo zypper install gnome-search-tool 操作界面:

【Spring】SpringBoot整合Redis,用Redis实现限流(附Redis解压包)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 本文介绍SpringBoot整合Redis并且进行接口的限流&#xff0c;文章主要介绍的是一种思想&#xff0c;具体代码还要结合实际。 一、Windows安装Redis Redis的解压包我放在了百度网盘上&#xff0c;有需要的可以下载。 R…

【第七篇】使用BurpSuite进行主动、被动扫描和主动、被动爬虫

文章目录 前言主动扫描被动扫描主动爬虫被动爬虫前言 Burp Scanner 既可以用作全自动扫描仪,也可以用作增强手动测试工作流程的强大手段。 扫描网站涉及两个阶段: 抓取内容和功能: Burp Scanner 首先在目标站点周围导航,密切反映真实用户的行为。它对站点的结构和内容以及…

06 Php学习:字符串

PHP 中的字符串变量 在 PHP 中&#xff0c;字符串是一种常见的数据类型&#xff0c;用于存储文本数据。字符串变量可以包含字母、数字、符号等字符&#xff0c;并且可以进行各种操作和处理。以下是关于 PHP 中字符串变量的一些重要信息&#xff1a; 定义字符串变量&#xff1…

Spring boot 入门 ---(一),2024年最新java进阶训练营

spring-snapshots http://repo.spring.io/snapshot spring-milestones http://repo.spring.io/milestone spring-boot-starter-parent是使用Spring Boot的一种不错的方式&#xff0c;但它 并不总是最合适的。有时你可能需要继承一个不同的父POM&#xff0c;或只是不喜欢我…

JVM面试整理--对象的创建和堆

文章目录 对象的创建过程是怎样的?对象在内存中的结构是怎样的&#xff08;专业的叫法&#xff1a;对象的内存布局&#xff09;对象在内存分配时使用的哪种方式&#xff08;有的地方也称为&#xff1a;分配算法&#xff09;知道什么是“指针碰撞”吗&#xff1f;知道什么是“空…

不允许在constexpr函数中进行声明

这是我用pycharm在windows系统下复现sfm深度学习网络(Deep Two-View Structure-from-Motion Revisited&#xff09;遇见的问题&#xff0c;复现时有段代码pytorch扩展cuda/c&#xff0c;pycharm中出现C标准相关的报错如下&#xff1a; 在网上查找很久无果&#xff0c;后面通过…

JVM垃圾收集——垃圾收集器

文章目录 1、垃圾收集器的发展和分类1.1、评估垃圾收集器的性能指标1.1.1、吞吐量1.1.2、停顿时间1.1.3、吞吐量和停顿时间的比较 1.2、垃圾收集器的发展史1.3、垃圾收集器的分类1.4、查看默认的垃圾收集器 2、Serial收集器&#xff1a;串行回收3、ParNew收集器&#xff1a;并行…

【漏洞复现】深澜计费管理系统任意文件读取漏洞

0x01 产品简介 深澜计费管理系统是一套完善的、领先的具有复杂生物型特征的弹性认证计费系统。其主要由以下几个模块组成&#xff1a;AAA认证计费平台、系统运营维护管理平台、用户及策略管理平台、用户自助服务平台、智能客户端模块、消息推送模块以及数据统计模块。该系统为…

Qt Creator实例之图标主题

Chart themes 是 Qt Creator 中图表的主题&#xff0c;它可以用于改变图表的外观和风格&#xff0c;使其更符合你的需求和设计。此示例显示了所有支持的图表类型的不同内置主题的外观。为了给结果一个更和谐的外观&#xff0c;应用程序的背景调色板是根据所选主题定制的。 char…

Mybatis-Plus05(分页插件)

分页插件 MyBatis Plus自带分页插件&#xff0c;只要简单的配置即可实现分页功能 1. 添加配置类 Configuration MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处 public class MybatisPlusConfig {Bean public MybatisPlusIntercepto…

功能测试如何到自动化测试,看这篇就够了。

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号&#xff1a;互联网杂货铺&#xff0c;回复1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 本帖不仅给大家介绍自动化测试&#xff0c;更会提供大…

GFS 分布式文件系统

目录​​​​​​​ GlusterFS简介 GlusterFS特点 GlusterFS 术语 GlusterFS 的工作流程 弹性 HASH 算法 GlusterFS的卷类型 分布式卷 条带卷 复制卷 分布式条带卷 分布式复制卷 条带复制卷 分布式条带复制卷 搭建GFS 节点配置 ​编辑 客户端配置 测试 Glust…

提示工程概要

提示工程 1. 两大原则 原则 1&#xff1a;编写清晰具体的说明 使用分隔符 三引号&#xff1a;“”"三个反引号&#xff1a;三个破折号&#xff1a;—尖括号&#xff1a;<>XML标签&#xff1a; 要求结构化输出 HTMLJSONXMLPython字典 检查条件是否满足 检查执行…

13 指针(上)

指针是 C 语言最重要的概念之一&#xff0c;也是最难理解的概念之一。 指针是C语言的精髓&#xff0c;要想掌握C语言就需要深入地了解指针。 指针类型在考研中用得最多的地方&#xff0c;就是和结构体结合起来构造结点(如链表的结点、二叉树的结点等)。 本章专题脉络 1、指针…

二维相位解包理论算法和软件【全文翻译- 掩码(3.4)】

本节我们将研究从质量图中提取掩码的问题。掩码是一个质量图,其像素只有两个值:0 或 1。零值像素标志着质量最低的相位值,这些相位值将被屏蔽、零权重或忽略。第 5 章中的某些 L/ 正则算法需要使用掩码来定义零权重。掩码还可用于某些路径跟踪算法,如第 4.5 节中将要介绍的…

计算机网友将饭卡余额改成100多万

你在学校干过最疯狂的事是什么&#xff1f; 一位学计算机的网友说&#xff0c;他改造过的水卡和饭卡都能无限使用&#xff0c;两年后在食堂刷卡&#xff0c;被食堂阿姨发现余额竟然还剩一百多万&#xff0c;虽然没有赔钱&#xff0c;但是被学校教务处处分了&#xff0c;怎么说…

QT:信号与槽

作业&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和…

Linux基础篇:Linux第三方软件仓库——可以让Linux变得有趣的软件仓库

Linux第三方软件仓库——可以让Linux变得有趣的软件仓库 一、epel源介绍 EPEL&#xff08;Extra Packages for Enterprise Linux&#xff09;源是一个由Fedora项目组维护的第三方软件仓库&#xff0c;为企业级Linux发行版&#xff08;如Red Hat Enterprise Linux&#xff08;…