四、快速上手 ODM 操作 Mongodb

文章目录

  • 一、ODM 的选择和安装
  • 二、MongoEngine 模型介绍
  • 三、文档的嵌套模型
  • 四、使用 ODM 查询数据
    • 4.1 查询一个文档
    • 4.2 条件查询
    • 4.3 统计、排序和分页
  • 五、使用 ODM 新增数据
  • 六、使用 ODM 修改和删除数据

一、ODM 的选择和安装

MongoEngine: 使用最为广泛的 ODM。http://mongoengine.org/
uMongo: 支持 sync/async 特性的 ODM。https://umongo.readthedocs.io/en/latest/
安装:

pip install -i http://pypi.douban.com/simple --trusted-host pypi.douban.com mongoengine

连接 MongoDB 数据库:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 13:35
# @Author  : AmoXiang
# @File    : 1.连接.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from mongoengine import connect, disconnect

# 方式一:使用默认配置
# connect(db='test')
connect('test')
# 方式二: 指定主机地址和端口号
# connect('students', host='172.0.0.1', port=27017)
connect('students', host='mongodb://localhost/students', alias='students1')

# 连接到多个数据库 建立连接 使用alias指定别名
# connect(alias='db1', db='test')
# connect(alias='db2', db='test-temp')

# 断开连接
# disconnect(alias='db1')

二、MongoEngine 模型介绍

MongoEngine ODM 模型,示例代码如下:
在这里插入图片描述
MongoEngine 常见数据模型,如下表所示:

数据类型通用参数,参考如下:

db_field: 文档中的field/域/列名称
required: 是否为必填项
default: 默认值
unique: 唯一性约束
choices: 可选择的列表
primary_key: 是否为文档的主键,默认为Fasle

类属性 meta:类属性,其配置项为 python 的 dict(字典)。 示例代码:

class User(Document):
	username = StringField()
	meta = {}
# 类属性meta常见配置项
# 1.db_alias: 指定文档所在的数据库(逻辑库)
# 2.collection: 指定文档所在的集合
# 3.ordering: 指定文档的默认排序规则
# 4. indexes: 指定文档的索引规则

学生信息数据字典,如下表所示:

Python 代码实现,示例如下:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 13:58
# @Author  : AmoXiang
# @File    : 2.ODM模型.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from enum import Enum
from mongoengine import Document, connect
from mongoengine.fields import IntField, StringField, EnumField

# 连接到数据库
connect('test')


class SexChoices(Enum):
    MEN = '男'
    WOMEN = '女'


class Student(Document):
    """ 学生信息 """
    stu_no = IntField(required=True, unique=True, verbose_name='学号')
    stu_name = StringField(required=True, max_length=16, verbose_name='姓名')
    # sex = StringField(max_length=2, verbose_name='性别', choices=[SexChoices.MEN, SexChoices.WOMEN])
    sex = EnumField(enum=SexChoices, verbose_name='性别')
    class_name = StringField(max_length=10, verbose_name='班级')
    address = StringField(max_length=255, verbose_name='家庭住址')
    phone_no = StringField(max_length=11, verbose_name='电话号码')
    age = IntField(min_value=0, max_value=150, verbose_name='年龄')

    meta = {
        # 指定集合
        'collection': 'students',
        'ordering': ['-age']
    }

三、文档的嵌套模型

文档嵌套的场景:

// 情况一: 数组-简单数据类型
{"grades": [76, 51, 84]}
// 情况二: 数组-文档
{"grades": ["score": 76}, {"score": 51}]}
// 情况三: 单个文档
"grade": {"course_name": "语文", "score": 76]}

示例代码如下:

from enum import Enum
from mongoengine import Document, connect, EmbeddedDocument
from mongoengine.fields import IntField, StringField, EnumField, ListField, EmbeddedDocumentField

# 连接到数据库
connect('test')


class SexChoices(Enum):
    MEN = '男'
    WOMEN = '女'


class CourseGrade(EmbeddedDocument):
    """ 成绩信息(科目 、老师、成绩) -被嵌套的文档 """
    course_name = StringField(max_length=64, required=True, verbose_name='课程名称')
    teacher = StringField(max_length=16, verbose_name='老师')
    score = IntField(required=True, min_value=0, max_value=100, verbose_name='老师')


class Student(Document):
    """ 学生信息 """
    stu_no = IntField(required=True, unique=True, verbose_name='学号')
    stu_name = StringField(required=True, max_length=16, verbose_name='姓名')
    # sex = StringField(max_length=2, verbose_name='性别', choices=[SexChoices.MEN, SexChoices.WOMEN])
    sex = EnumField(enum=SexChoices, verbose_name='性别')
    class_name = StringField(max_length=10, verbose_name='班级')
    address = StringField(max_length=255, verbose_name='家庭住址')
    phone_no = StringField(max_length=11, verbose_name='电话号码')
    age = IntField(min_value=0, max_value=150, verbose_name='年龄')

    grades = ListField(EmbeddedDocumentField(CourseGrade), verbose_name='成绩列表')

    meta = {
        # 指定集合
        'collection': 'students',
        # 排序规则:年龄倒序
        'ordering': ['-age']
    }


class StudentGrade(Document):
    """ 学生成绩 """
    stu_no = IntField(required=True, unique=True, verbose_name='学号')
    stu_name = StringField(required=True, max_length=16, verbose_name='姓名')
    # sex = StringField(max_length=2, verbose_name='性别', choices=[SexChoices.MEN, SexChoices.WOMEN])
    sex = EnumField(enum=SexChoices, verbose_name='性别')
    class_name = StringField(max_length=10, verbose_name='班级')
    address = StringField(max_length=255, verbose_name='家庭住址')
    phone_no = StringField(max_length=11, verbose_name='电话号码')
    age = IntField(min_value=0, max_value=150, verbose_name='年龄')

    grade = EmbeddedDocumentField(CourseGrade, verbose_name='成绩列表')

    meta = {
        # 指定集合
        'collection': 'grades',
        # 排序规则:年龄倒序
        'ordering': ['-age']
    }

四、使用 ODM 查询数据

4.1 查询一个文档

结果集,结果集 QuerySet 的获取:

User.objects
# 结果集上的常用方法:
# 1.all(): 查询所有的文档
# 2.filter(): 按照条件查询
# 3.count(): 满足条件的文档数
# 4.sum()/average(): 求和/求平均数
# 5.order_by(): 排序
# 6. .skip().limit(): 分页
....

单个文档查询:

# first(): 没有文档则返回 None
User.objects.first()
get(**kwargs): 
# 1.多个文档时: 异常 MultipleObjectsReturned 
# 2.没有文档时: 异常 DoesNotExist
# 3.仅有一个文档时: 返回 ODM 对象

4.2 条件查询

查询条件的使用,在 MongoEngine 中使用 双下划线(__) 分割:

MongoEngine 中的字符串查询(i表示不区分大小写):

多个条件组合查询,Q函数的使用:

from mongoengine.queryset.visitor import Q 
# 1.多个条件同时满足
Student.objects(Q(key1=value1) & Q(key2=value2))
# 2.多个条件部分满足
Student.objects(Q(key1=value1) | Q(key2=value2))

4.3 统计、排序和分页

聚合统计:

# 1.满足条件的文档数
User.objects.count()
# 2.求和/求平均数
User.objects.filter().sum(field)

排序:

# 排序规则 -: 倒序排列 (+): 正序排列
# 示例代码
Students.objects().order_by('+field1', '-field2')

分页处理:

# 方式一: 切片方式
User.objects.all()[10:15]
# 方式二: .skip().limit()
User.objects.skip(10).limit(5)

参考代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 14:44
# @Author  : AmoXiang
# @File    : 4.查询文档.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from bson import ObjectId
# from mongoengine.queryset.visitor import Q
from mongoengine import Q

from school_models import Student, StudentGrade, SexChoices


class TestMongoEngine(object):

    def get_one_student(self):
        """ 查询一个学生信息 """
        return Student.objects.first()

    def get_student_by_pk(self, pk):
        """ 根据学生的ID来查询 """
        object_id = ObjectId(pk)
        # return Student.objects.get(id=object_id)
        return Student.objects.get(id=pk)
        # return Student.objects.get(age=12)

    def get_students_01(self):
        # 查询所有的文档
        # queryset = Student.objects()
        # queryset = Student.objects.all()
        # 12岁以上的学生信息
        # queryset = Student.objects(age__gt=12)
        queryset = Student.objects.filter(age__gt=12)
        print(queryset)
        for item in queryset:
            print(item, type(item))

    def get_grade_01(self):
        # 及格的成绩信息
        queryset = StudentGrade.objects.filter(grade__score__gte=60)
        for item in queryset:
            print(item.stu_name, item.grade.score)

    def get_students_02(self):
        # //查找所有姓“李”的学生信息
        # //SELECT * FROM school_student_info WHERE stu_name LIKE '李%';
        # //SELECT * FROM school_student_info WHERE stu_name LIKE "李%";
        # db.students.find({stu_name: /^李/});
        queryset = Student.objects.filter(stu_name__startswith='李')
        for item in queryset:
            print(item)

    def get_students_03(self):
        """ 查询年龄在9~12之间(含)的学生信息 """
        # //查询年龄在9~12之间(含)的学生信息
        # //SELECT * FROM school_student_info WHERE age BETWEEN 9 AND 12;
        # db.students.find({age: {$gte: 9,$lte: 12}});
        # queryset = Student.objects.filter(age__gte=9, age__lte=12)
        queryset = Student.objects.filter(Q(age__gte=9) & Q(age__lte=12))
        for item in queryset:
            print(item)

    def get_students_04(self):
        """ 查询所有12岁以上的男生和9岁以下的女生 """
        # //查询所有12岁以上的男生和9岁以下的女生
        # //SELECT * FROM school_student_info WHERE (age > 12 AND sex ='男') OR (age < 9 AND sex ='女');
        # db.students.find({
        #     $or: [
        #         {sex: "男", age: {$gt: 12}},
        #         {sex: "女", age: {$lt: 9}}
        #     ]
        # });
        queryset = Student.objects.filter(Q(age__gt=12, sex=SexChoices.MEN) | Q(age__lt=9, sex=SexChoices.WOMEN))
        # 指定排序规则
        queryset = queryset.order_by('age')
        for item in queryset:
            print(item)
        print('学生人数:', queryset.count())

    def get_students_05(self):
        # //统计语文成绩的最高分/最低分/平均分
        # //SELECT MAX(score), MIN(score),AVG(score) FROM school_student_grade WHERE course_id=1;
        # db.grades.aggregate([
        # //where
        # {
        #     $match: {"grade.course_name": "语文"}
        # },
        # //group by
        # {
        #     $group: {
        #         _id: null,
        #         maxScore: {$max: "$grade.score"},
        #         minScore: {$min: "$grade.score"},
        #         avgScore: {$avg: "$grade.score"},
        #     }
        # }
        # ]);
        queryset = StudentGrade.objects.filter(grade__course_name='语文')
        avg_score = queryset.average('grade.score')
        print('全年级语文成绩平均分', avg_score)
        # 张三的总分
        # //统计学生张三的各科总分
        # //SELECT * FROM school_student_info WHERE stu_name = '张三';
        # //SELECT * FROM school_student_grade WHERE student_id=5;
        # //SELECT SUM(score) FROM school_student_grade WHERE student_id=5;
        # db.grades.aggregate([
        # //where
        # {
        #     $match: {"stu_name": "张三"}
        # },
        # //group by
        # {
        #     $group: {
        #         _id: null,
        #         totalScore: {$sum: "$grade.score"}
        #     }
        # }
        # ]);
        queryset = StudentGrade.objects.filter(stu_name='张三')
        sum_score = queryset.sum('grade.score')
        print('张三的总分', sum_score)

    def paginate(self, page=1, page_size=5):
        """
        分页函数
        :param page: 当前第几页
        :param page_size: 每页多少条数据
        :return:
        """
        # 切片分页
        start = (page - 1) * page_size
        end = page * page_size
        queryset = Student.objects.all()[start: end]
        for item in queryset:
            print(item)
        # skip limit
        print('-----------------')
        queryset = Student.objects().skip(start).limit(page_size)
        for item in queryset:
            print(item)


def main():
    obj = TestMongoEngine()
    # result = obj.get_one_student()
    # print(result)
    # result = obj.get_student_by_pk('64120cbce602000052002ec1')
    # print(result)
    # ID不存在
    # result = obj.get_student_by_pk('60d376bff95e00004900257b')
    # print(result.stu_no)
    # print(result)

    # obj.get_students_01()
    # obj.get_grade_01()
    # obj.get_students_02()
    # obj.get_students_03()
    # obj.get_students_04()
    # obj.get_students_05()

    # 分页
    obj.paginate(3)


if __name__ == '__main__':
    main()

五、使用 ODM 新增数据

使用 ODM 新增数据:

# 1.第一步,构造 ODM 模型类对象
user_obj = User(username="lili")
# 2.第二步,验证数据
user_obj.validate()
# 3.第三步,保存数据
user_obj.save()

模型中验证器:

# 内置的验证器 如: max_length, min_value
# 自定义的验证器
def phone_required(value):
    pattern = r'^1[0-9]{10}$'
    if not re.search(pattern, value):
        raise ValidationError('请输入手机号码')

使用 create() 方法,参考代码:

User.objects.create(**kwargs)

示例代码:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 15:30
# @Author  : AmoXiang
# @File    : 5.新增文档.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from school_models import Student, StudentGrade, SexChoices, CourseGrade


class TestMongoEngine(object):

    def add_one(self):
        """ 数据的新增 """
        # stu_obj = Student(stu_no=2003, stu_name='王二小2')
        # stu_obj = Student(stu_no=2003, stu_name='王二小2', phone_no='abc123')
        stu_obj = Student(stu_no=2003, stu_name='王二小2', phone_no='13500000000')
        stu_obj.validate()
        result = stu_obj.save()
        print(result)
        print(result.id)

    def add_one_2(self):
        """ 使用create方法新增数据 """
        result = Student.objects.create(stu_no=2004, stu_name='王二小4', phone_no='13500000001')
        print(result)
        print(result.id)

    def add_one_3(self):
        """ 嵌套文档的插入 """
        grade1 = CourseGrade(course_name='语文', score=100)
        grade2 = CourseGrade(course_name='数学', score=100)
        grade3 = CourseGrade(course_name='英语', score=100)
        grades = [grade1, grade2, grade3]
        stu_obj = Student(stu_no=2005, stu_name='王二小5', phone_no='13500000000')
        stu_obj.grades = grades
        stu_obj.validate()
        result = stu_obj.save()
        print(result)
        print(result.id)


def main():
    obj = TestMongoEngine()
    # obj.add_one()
    # obj.add_one_2()
    obj.add_one_3()


if __name__ == '__main__':
    main()

六、使用 ODM 修改和删除数据

使用 ODM 修改数据,如下所示:
在这里插入图片描述
修改一条数据:

User.objects.update_one()

批量修改数据:

User.objects.update()

示例代码:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 15:37
# @Author  : AmoXiang
# @File    : 6.修改文档.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from school_models import Student, StudentGrade, SexChoices, CourseGrade


class TestMongoEngine(object):

    def update_one(self):
        """ 数据的修改 """
        queryset = Student.objects.filter(stu_no=2001)
        # result = queryset.update_one(stu_name='王二大', phone_no='13400000000')
        result = queryset.update_one(stu_name='王二大', unset__phone_no=True)
        print(result)

    def update_one_2(self):
        """ 数据的修改 -save() """
        stu_obj = Student.objects.filter(stu_no=2001).first()
        if stu_obj:
            stu_obj.stu_name = '王三'
            # stu_obj.phone_no = '王三'
            result = stu_obj.save()
            print(result)

    def update_many(self):
        """ 9岁的学生年龄+1 """
        queryset = Student.objects.filter(age=9)
        for item in queryset:
            print(item)
        queryset.update(inc__age=1)
        print('------------------')
        queryset = Student.objects.filter(age=10)
        for item in queryset:
            print(item)


def main():
    obj = TestMongoEngine()
    # obj.update_one()
    # obj.update_one_2()
    obj.update_many()


if __name__ == '__main__':
    main()

使用 ODM 删除数据,示例代码:

User.objects.delete()

参考代码如下:

# -*- coding: utf-8 -*-
# @Time    : 2023-03-19 15:38
# @Author  : AmoXiang
# @File    : 7.删除文档.py
# @Software: PyCharm
# @Blog    : https://blog.csdn.net/xw1680

from school_models import Student, StudentGrade, SexChoices, CourseGrade


class TestMongoEngine(object):

    def delete_data(self):
        """ 删除数据练习 """
        # 删除学号> 2000的学生信息
        queryset = Student.objects(stu_no__gt=2000)
        print('学生人数', queryset.count())
        result = queryset.delete()
        print('删除的结果', result)


def main():
    obj = TestMongoEngine()
    obj.delete_data()


if __name__ == '__main__':
    main()

至此今天的学习就到此结束了,笔者在这里声明,笔者写文章只是为了学习交流,以及让更多学习数据库的读者少走一些弯路,节省时间,并不用做其他用途,如有侵权,联系博主删除即可。感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!


在这里插入图片描述

    好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
    如果我的博客对你有帮助、如果你喜欢我的博客内容,请 点赞评论收藏 一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
 编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了 关注 我哦!

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

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

相关文章

【C++】命名空间

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;C的学习之路 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言一、命名空间产生的背景二、命名空…

基础篇:07-Nacos注册中心

1.Nacos安装部署 1.1 下载安装 nacos官网提供了安装部署教程&#xff0c;其下载链接指向github官网&#xff0c;选择合适版本即可。如访问受阻可直接使用以下最新稳定版压缩包&#xff1a;&#x1f4ce;nacos-server-2.1.0.zip&#xff0c;后续我们也可能会更改为其他版本做更…

图论学习(五)

极图 l部图的概念与特征 定义&#xff1a;若简单图G的点集V有一个划分&#xff1a; 且所有的Vi非空&#xff0c;Vi内的点均不邻接&#xff0c;设G是一个l部图。 如果l2&#xff0c;则G就是偶图。n阶无环图必是n部图。若l1<l2≤n&#xff0c;则任意的l1部图也是l2部图。…

【毕业设计】基于SpringBoot+Vue论坛管理系统【源码(完整源码请私聊)+论文+演示视频+包运行成功】

您好&#xff0c;我是码农飞哥&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精通 &#x1f601; 2. 毕业设计专栏&…

JavaScript学习笔记(7.0)

<!--* Author: RealRoad1083425287qq.com* Date: 2023-03-13 14:50:18* LastEditors: Mei* LastEditTime: 2023-03-13 15:08:54* FilePath: \vscode\鼠标跟随.html* Description: * * Copyright (c) 2023 by ${git_name_email}, All Rights Reserved. --> <!DOCTYPE …

Vue3(递归组件) + 原生Table 实现树结构复杂表格

一、递归组件 什么是递归&#xff0c;Javascript中经常能接触到递归函数。也就是函数自己调用自己。那对于组件来说也是一样的逻辑。平时工作中见得最多应该就是菜单组件&#xff0c;大部分系统里面的都是递归组件。文章中我做了按需引入的配置&#xff0c;所以看不到我引用组…

什么是让ChatGPT爆火的大语言模型(LLM)

什么是让ChatGPT爆火的大语言模型(LLM) 更多精彩内容: https://www.nvidia.cn/gtc-global/?ncidref-dev-876561 文章目录什么是让ChatGPT爆火的大语言模型(LLM)大型语言模型有什么用&#xff1f;大型语言模型如何工作&#xff1f;大型语言模型的热门应用在哪里可以找到大型语言…

西安石油大学C语言期末真题实战

很简单的一道程序阅读题&#xff0c;pa’默认为a【0】&#xff0c;接下来会进行3次循环 0 1 2 输出结果即可 前3题就是一些基础定义&#xff0c;在此不多赘述 要注意不同的数据类型的字节数不同 a<<2 b>>1&#xff08;b>>1;就是说b自身右位移一位&#xff08…

支付系统设计:消息重试组件封装

文章目录前言一、重试场景分析一、如何实现重试1. 扫表2. 基于中间件自身特性3. 基于框架4. 根据公司业务特性自己实现的重试二、重试组件封装1. 需求分析2. 模块设计2.1 持久化模块1. 表定义2. 持久化接口定义3. 持久化配置类2.2 重试模块1.启动2.重试3. 业务端使用1. 引入依赖…

Linux基础(3) Vim编辑器与Shell命令脚本

1、VIM文本编辑器 VIM编辑器的三大模式 命令模式&#xff1a; 控制光标移动&#xff0c;可对文本进行复制、粘贴和查找等工作输入模式&#xff1a; 正常的文本录入。末行模式&#xff1a; 保存或退出文档&#xff0c;以及设置编辑环境三种模式的切换&#xff1a; ​注意&…

app自动化测试——Android studio安装与配置

文章目录一、Appium框架介绍二、Appium 生态工具三、环境安装四、安装Android studio五、配置环境变量六、创建模拟器查看设备启动模拟器一、Appium框架介绍 1、跨语言&#xff1a;java、python等 2、跨平台&#xff1a;Android、IOS、Windows、Mac 3、底层多引擎切换 4、生态…

(待补充)小蒟蒻的刷题成长之路-------2023年中国高校计算机大赛-团队程序设计天梯赛(GPLT)上海理工大学校内选拔赛(同步赛)

小蒟蒻的刷题成长之路 蓝桥杯的比赛流程和必考点_蓝桥杯省赛考点_时雨h的博客-CSDN博客 大一学生一周十万字爆肝版C语言总结笔记_大一c语言笔记_时雨h的博客-CSDN博客 程序设计与 C 语言期末复习_时雨h的博客-CSDN博客 P8597 [蓝桥杯 2013 省 B] 翻硬币个人思考总结第五届传智杯…

西瓜视频登录页面

题目 代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>登录页面</title><style>td{width: 160px;height: 25px;}img{width: 20px;height: 20px;}.number, .password{background: rgba(0,0,0,.05);}.numbe…

指针进阶(上)

内容小复习&#x1f431;&#xff1a; 字符指针:存放字符的数组 char arr1[10]; 整型数组:存放整型的数组 int arr2[5]; 指针数组:存放的是指针的数组 存放字符指针的数组(字符指针数组) char* arr3[5]; 存放整型指针的数组(整型指针数组) int* arr[6]; 下面进入学习了哦~&…

【二分查找】

二分查找704. 二分查找35. 搜索插入位置34. 在排序数组中查找元素的第一个和最后一个位置结语704. 二分查找 给定一个 n 个元素有序的&#xff08;升序&#xff09;整型数组 nums 和一个目标值 target &#xff0c;写一个函数搜索 nums 中的 target&#xff0c;如果目标值存在…

mybatis中获取参数的两种方式:${}和#{}

目录 1.#{} 2.${} 3.总结 1.#{} 本质是占位符赋值 示例及执行结果&#xff1a; 结论&#xff1a;通过执行结果可以看到&#xff0c;首先对sql进行了预编译处理&#xff0c;然后再传入参数&#xff0c;有效的避免了sql注入的问题&#xff0c;并且传参方式也比较简单&#xf…

Python制作9行最简单音乐播放器?不,我不满足

人生苦短 我用python 好久不见啦~这次就来给大家整个大福利 ~ 源码资料电子书:点击此处跳转文末名片获取 最简单的9行代码音乐播放器如下&#xff1a; import time import pygamefile r歌曲路径 pygame.mixer.init() print(正在播放,file) track pygame.mixer.music.load(f…

计算机面试常见问答题目

英语口语 自我介绍 Hello, teachers. My name is Wang Xu. I come from Ningxia. I graduated from the School of Computer Science, Xi an Jiaotong University, majoring in Internet of Things. Next, I will introduce myself from four aspects. First of all, I studi…

Java开发 - ELK初体验

前言 前面我们讲过消息队列&#xff0c;曾提到消息队列也具有保存消息日志的能力&#xff0c;今天要说的EL看也具备这个能力&#xff0c;不过还是要区分一下功能的。消息队列的日志主要指的是Redis的AOF&#xff0c;实际上只是可以利用了消息队列来保存&#xff0c;却并不是消…

网络编程1(网络背景知识)

A给B发送消息如何保证数据一定能够发送到B的主机上&#xff0c;而不是其他地方 通过IP地址可以实现网络中制定的两个主机之间的通信&#xff0c;除此之外还要确定是哪个进程来处理&#xff0c;这里就用到端口&#xff08;port&#xff09; 端口—在一台主机上用于唯一标识一个…