Mybatis入门の基础操作

1 Mybatis概述
在这里插入图片描述

   MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

   mybatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。 

   mybatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。 

   采用ORM思想解决了实体和数据库映射的问题,对jdbc进行了封装,屏蔽了jdbc api底层访问细节,使我们不用与jdbc api打交道,就可以完成对数据库的持久化操作。

mybatis技术曾经做过“更名”,早期这个团队将技术框架称为“iBatis",mybatis研发团队”跳槽“google,从google跳”githup",将之前“ibatis"改为”mybaits"

mybatis中文网站:https://mybatis.net.cn/

2 mybatis框架技术定位

SSM框架与三层架构对应关系: Java提供JDBC,Spring提供SpringJdbc,mybatis
在这里插入图片描述

3 Mybatis的优势:传统jdbc存在的问题

在这里插入图片描述

JDBC操作步骤:

1、注册驱动:Class.forName(“com.mysql.jdbc.Driver”)

2、获取连接:Connection connection=DriverManager.getConnection(url,username,password);

3、获取预处理对象:PreparedStatement pstm=connection.PreparedStatement(“sql”);

4、执行sql操作:Result result=pstm.ExecuteQuery();/pstm.ExecuteReader().

5、封装结果集:While(result.next()){……}

6、释放资源:Result.close();  Pstm.close();  Connection.close();

分析:如果我们要在mysql中查询一个内容应该怎样操作才能得到结果?在mysql中我们只需要编写出相应的sql语句即可,但是在jdbc中除了编写sql语句外还要做很多额外的工作才能得到结果。能不能只编写sql语句其余工作不再去关注呢?这就是mybatis的作用,我们唯一要做的就是思考怎样去编写高效的sql语句。

4 Mybatisの入门案例

创建maven控制台程序,按照以下步骤完成mybatis开发环境搭建工作:

  • pom.xml 导入mybatis依赖
<!-- mybatis依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>
<!-- 数据库驱动-->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>
  • 项目中引入数据库配置文件:db.properties
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/bookstore?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc.username=root
jdbc.password=root
  • 添加mybatis核心配置文件mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
 加载数据库配置信息的文件:db.properties
 properties:读取classpath下面的配置文件,所以不用写classpath
 -->
  <properties resource="db.properties"/>
<!--
配置数据库连接信息:从配置文件读取对应的key的值
-->
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>
</configuration>

mybatis-confg.xml是mybatis的核心配置文件,该文件中要配置哪些东西呢:即基本的sql语句执行环境需要的就是数据驱动类型、数据库服务器地址、数据库服务器登录账号及密码。

  • 测试代码
  • public class Tester {
        @Test
        public void test01()throws  Exception{
            //1.读取配置文件,构建mybatis核心执行对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过工厂获取数据库连接对象
            SqlSession session = sqlSessionFactory.openSession();
            System.out.println(session);
        }
    }
    

5 Mybatis的CRUD操作

准备工作

确定要操作的数据库和数据表后,按照持久层dao开发流程,完成代码准备:

创建Notice实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Notice {
    private Integer id;
    private String title;
    private String content;
    private Integer employeeId;
    //jdk1.8新增日期格式:LocalDateTime对象中包含:年月日时分秒组成
    private LocalDateTime createTime;
}

为表创建对应的dao接口:NoticeDao.java

/**
 * mybatis接口不再提供实现类,取而代之使用xml配置文件完成代码执行,
 * xml文件主要作用:写sql,成为sql映射文件
 * sql映射文件要求:文件名必须和接口同名,单词一模一样;文件存放位置和接口所在包一样
 */
public interface NoticeDao {
    /**
     * 查询所有的帖子信息
     */
    List<Notice> selectAll();
}

为NoticeDao接口创建SQL映射文件:NoticeDao.xml

mybatis中规定dao只是用来声明方法的接口类,接口中方法的实现由mapper.xml映射文wrh来实现(sql语句)。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper:sql映射文件.作用:配置sql语句
  namespace:命名空间,理解包 设置当前sql映射文件是对应哪个接口文件,填写接口包名.类名
-->
<mapper namespace="com.woniu.dao.NoticeDao">
    <select id="" resultType="">
        
    </select>
</mapper>

注意:mapper.xml映射文件须和dao接口在同一包中且名称相同。创建好的文件目录如下图所示:

案例一:查询所有公告信息

修改NoticeDao.xml映射文件:为查询方法配置对应的sql语句

注意:使用mapper代理开发时不用为dao接口编写实现类,但是在mapper.xml文件中的mapper节点中的namespace必须指定与同名接口类的全限定名

<!--
id:指定sql为接口里面哪个方法提供的。id设置方法:方法名
resultType:方法返回值类型,如果方法返回值类型是集合,只需要填写集合泛型类型即可
 指定类型时:必须使用全路径:包名.类名
-->
<select id="selectAll" resultType="com.woniu.entity.Notice">
    SELECT id,title,content,employeeId,createtime from wy_notice
</select>

属性说明:

 id: 设置要实现的方法名称
 resultType: 方法返回值类型,如果返回值是集合类型,写集合的泛型类型。
 鉴于之前使用JdbcTemplate执行sql的经验,我们可以这么理解resultType:
  resultType提供类型用于完成查询结果与实体类映射关系,默认情况:entity定义属性时属性名和表列名单词一样的。

注意:使用mapper代理开发时mapper.xml中sql节点的id值必须与dao接口中的方法名称一致

		resultType属性的值必须与dao接口中方法的返回值类型一致

核心配置文件中注册Sql映射文件:NoticeDao.xml

 每一个mapper.xml映射文件要能正确被程序解析到,还要在mybatis核心配置文件中进行注册

<mappers>
    <mapper resource="com/woniu/dao/NoticeDao.xml"/>
</mappers>

		resource读取的是classpath下的文件url地址,所以此处写的是xml的路径,不是接口的包名

常见异常:

如果没有在核心配置文件中“注册”sql映射文件,执行代码时通常会提示以下异常:

测试代码

@Test
public void test01()throws  Exception{
    //1.读取配置文件,构建mybatis核心执行对象
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //通过工厂获取数据库连接对象
    SqlSession session = sqlSessionFactory.openSession();
    System.out.println(session);
    //执行sql语句了 重点,mapper其实就是依靠jdk代理为接口生成实现类
    NoticeDao noticeDaoImpl = sqlSession.getMapper(NoticeDao.class);
    //com.sun.proxy.$Proxy6 基于jdk代理,获取接口对应的实现类
    System.out.println(noticeDaoImpl.getClass());

    List<Notice> notices = noticeDaoImpl.selectAll();
    notices.forEach(System.out::println);
}

观察以上输出结果,我们不难发现,mybatis的底层其实是利用JDK代理完成了dao接口对应实现类的动态生成。我们之前学过JDK代理的知识,我们可以这么理解

所以,在mybatis 框架中它将“通用且重复”的sql执行过程在程序运行过程中,动态增强到xml配置的sql语句前后。简化了程序员持久层开发工作的负担和繁复。

案例二:DML操作の添加公告信息

修改NoticeDao.xml映射文件:为insert方法配置对应的sql语句

注意:使用mapper代理开发时不用为dao接口编写实现类,但是在mapper.xml文件中的mapper节点中的namespace必须指定与同名接口类的全限定名

<insert id="insert">
    insert wy_notice values(null,'测试数据','测试数据内容',1,now())
</insert>

属性说明:

 id: 设置要实现的方法名称
 insert配置新增语句,该标签一般只需要配置id即可
 因为insert没有查询结果集,所以insert标签也就没有resultType属性了

测试代码

@Test
public void testInsert()throws IOException{
    //1.获取SqlSession
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession sqlSession = sqlSessionFactory.openSession(true);
    //2.基于jdk代理,获取要测试接口对应的实现类
    NoticeDao noticeDaoImpl = sqlSession.getMapper(NoticeDao.class);
    int insert = noticeDaoImpl.insert(null);
    System.out.println("insert语句执行后,受影响的行数:" + insert);
}

添加代码执行成功后,数据库数据并没有新增的问题:

测试结果暗示的意思是数据添加成功,我们去刷新mysql数据库,观察发现并没有出现”测试数据“这条新增数据,why???

真相是:mybatis在openSession()时,默认开启了事务手动提交模式,所以在没有代码明确写明“commit()"的情况下,程序操作的结果不会物理更新到数据表中。

解决方案如下:

方案一:手动提交事务

@Test
public void test01()throws  Exception{
    //1.读取配置文件,构建mybatis核心执行对象
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //通过工厂获取数据库连接对象,SqlSession默认配置:事务手动提交,如果openSession(true)设置事务自动提交
    SqlSession session = sqlSessionFactory.openSession();       
    //sql执行:获取UserDao接口的代理对象,
    NoticeDao noticeDaoImpl = session.getMapper(NoticeDao.class);

    int i = noticeDaoImpl.insert(null);
    System.out.println("新增方法执行结果是:" + i);
    //提交事务
    session.commit();
    //释放资源
    session.close();
}

方案二:开启事务自动提交模式

@Test
public void test01()throws  Exception{
    //1.读取配置文件,构建mybatis核心执行对象
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //通过工厂获取数据库连接对象,SqlSession默认配置:事务手动提交,如果openSession(true)设置事务自动提交
    SqlSession session = sqlSessionFactory.openSession(true);       
    //sql执行:获取UserDao接口的代理对象,
    NoticeDao noticeDaoImpl = session.getMapper(NoticeDao.class);

    int i = noticeDaoImpl.insert(null);
    System.out.println("新增方法执行结果是:" + i);
   
    //释放资源
    session.close();
}

扩展补充:SqlSession释放资源的问题

SqlSession使用完毕后,也是要释放数据库资源的,所以此处如果想不写“session.close()“,可以借助JDK1.8中try-catch的新语法,代码如下所示:

@Test
    public void test01()throws  Exception{
        //1.读取配置文件,构建mybatis核心执行对象
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过工厂获取数据库连接对象,SqlSession默认配置:事务手动提交,如果openSession(true)设置事务自动提交
        try(SqlSession session = sqlSessionFactory.openSession(true);) {
            //sql执行:获取UserDao接口的代理对象,
            NoticeDao noticeDaoImpl = session.getMapper(NoticeDao.class);
           
            int i = noticeDaoImpl.insert(null);
            System.out.println("新增方法执行结果是:" + i);
        }
    }

6 日志框架 logback

模仿日志输出,日志将程序执行过程,执行了什么sql,带入什么参数,执行的是什么结果,执行出现问题具体描述信息…

作用:日志框架增强程序员跟踪程序执行过程,对于发生一些程序问题,更好进行定位、分析。

日志框架选择:Springboot内置日志框架:logback

logback使用步骤

  • pom.xml导入logback的依赖:整个日志框架需要导入三个依赖:logback-classic、logback-core、slf4j-api

  • <!-- 日志框架 -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>1.2.3</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    
  • 项目引入自己的日志配置文件:logback.xml

  • <configuration debug="false">
        <!-- appender配置输出的位置和输出日志格式
           CONSOLE:控制台
           -->
        <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%5p | %-40.40logger{39}  :%m%n</pattern>
                <charset>utf8</charset>
            </encoder>
        </appender>
        <!-- 了解日志信息输出的级别:TRACE < DEBUG < INFO < WARN < ERROR
            配置哪些日志在控制台输出,可以通过设置不同的日志级别控制
            日志级别的输出原则:设置级别时,会输出当前设置级别的日志以及比当前更高级别的日志
           -->
    
    <!--
    logger:特定设置,属性
    name:特定配置针对的包名,酌情修改
    level:DEBUG
    additivity:覆盖默认配置
    -->
        <logger name="com.woniu" level="DEBUG" additivity="false">
            <appender-ref ref="CONSOLE"/>
        </logger>
    <!--
    root:基础配置,level:info
    -->
        <root level="INFO">
            <appender-ref ref="CONSOLE" />
        </root>
    </configuration>
    
  • 自己使用log对象输出日志信息

  • @Slf4j //引入日志管理器
    public class xxx{
       @Test
        public void test00(){
            String str="helloworld";
            //观察控制台能否输出对应的信息:信息是否可以输出与logback.xml配置的级别有关系
            log.trace("trace str{}",str);
            log.debug("debug str{}",str);
            log.info("info str{}",str);
            log.warn("warn str{}",str);
            log.error("error str{}",str);
        }
    }
    

按照步骤配置好日志框架后,重新启动上面案例的测试代码,就可以在控制台看到sql的输出信息了。

7 mybatis中#{}和${}设置sql参数对比

案例:根据id查询用户信息

修改UserDao.xml中配置:使用${}带入参数

 <select id="selectById" resultType="com.woniu.entity.Users">
    select * from wy_employee where id=${id}
  </select>

执行测试方法

@Test
public void test01()throws  Exception{
    //1.读取配置文件,构建mybatis核心执行对象
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //通过工厂获取数据库连接对象,SqlSession默认配置:事务手动提交,如果openSession(true)设置事务自动提交
    try(SqlSession session = sqlSessionFactory.openSession(true);) {
        System.out.println(session);
        //sql执行:获取UserDao接口的代理对象,
        UsersDao usersDaoImpl = session.getMapper(UsersDao.class);
        System.out.println(usersDaoImpl.getClass());
        //调用方法,获取执行结果
        List<Users> list = usersDaoImpl.selectAll("id");
        list.forEach(System.out::println);
    }
}

修改UserDao.xml中配置:使用#{}带入参数

 <select id="selectById" resultType="com.woniu.entity.Users">
    select * from wy_employee where id=#{id}
  </select>

再次执行同一个测试方法,观察两次测试的日志输出结果:

由上图得出以下结论:

#{}与${}的区别:
   #{}:使用?占位符,即是将sql语句编译好后再取值,能够有效防止sql注入,#{}取的是属性中的值
   ${}:是sql后面直接拼接参数值,即取值后再编译语句,不能防止注入。
适用场景:${}方式一般用于传入数据库对象,例如传入表名或者列名,就只能使用${}带入参数。
       在实际使用中能使用#{}就不用${},

案例2:根据指定列名完成查询结果的排序

  • UsersDao.java中定义方法

      List<Users> selectAll(String name);
    
  • UsersDao.xml配置sql

    select * from wy_employee order by ${name} desc
  • 测试代码

@Test
public void test01()throws  Exception{
    //1.读取配置文件,构建mybatis核心执行对象
    String resource = "mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    //SqlSession可以理解为Connection,此行代码的意思就是:读取配置文件获取数据库连接的工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //通过工厂获取数据库连接对象,SqlSession默认配置:事务手动提交,如果openSession(true)设置事务自动提交
    try(SqlSession session = sqlSessionFactory.openSession(true);) {
        System.out.println(session);
        //sql执行:获取UserDao接口的代理对象,
        UsersDao usersDaoImpl = session.getMapper(UsersDao.class);
        System.out.println(usersDaoImpl.getClass());
        //调用方法,获取执行结果
        List<Users> list = usersDaoImpl.selectAll("id");
        list.forEach(System.out::println);
    }
}
  • 将UserDao.xml中sql修改成#{}再次执行单元测试
<select id="selectAll" resultType="com.woniu.entity.Users">
    select * from wy_employee order by #{name} desc
</select>

观察执行结果可以发现:#{}带入参数时,查询结果没有排序。只有使用${}带入参数时,才有排序的效果

8 #{}带入参数的写法

#{}带入参数时,使用什么名称来引用值,分为三种场景区别:
1 方法有且只有一个参数,并参数是基本类型或String,#{随便写}
形如:Users selectById(Long id); 
配置sql:select * from wy_employee where id=#{随便写,一般见词知意形参名}

2 方法有且只有一个参数,并参数是对象,#{对象的属性名}
形如:insert(user  u) update(User u)

3 方法N个参数 #{参数} 借助注解@Param给参数设置引用名
形如:
int update(@Param("pkId") Long id, @Param("pwd") String password,@Param("username") String realName);
xml文件:update wy_employee set password=#{pwd},realname=#{username} where id=#{pkId}

案例:新增公告信息

  • NoticeDao.java定义新增方法
  • int insert(Notice notice);
    
  • NoticeDao.xml配置insert语句
  • <insert id="insert">
        insert wy_notice values(null,#{title},#{content},#{userId},#{createTime})
    </insert>
    
  • MyTester.java测试代码
  • @Test
    public void test02()throws Exception{
        //1 指定mybatis开发环境基于哪个配置文件来使用resource基于classpath
        String resource = "mybatis-config.xml";
        //2 基于配置文件构建IO输入流
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //SqlSession本质就是Connection   SqlSessionFactory是连接池
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //执行sql语句,验证执行结果,连接池获取连接对象时,其实需要指定事务提交方式,如果不指定默认不是自动提交模式
        try (SqlSession session = sqlSessionFactory.openSession(true)) {
            //获取dao实现类对象,mybatis依据JDK代理模式动态获取实现类型
            NoticeDao implProxy = session.getMapper(NoticeDao.class);
            int i = implProxy.insert(
                Notice.builder()
                .title("aaaaaaaaaaaa")
                .content("bbbbbbbbbbbbbbbbbbbbbbb")
                .userId(1)
                .createTime(LocalDateTime.now())
                .build()
            );
            System.out.println("本次新增的数据行数:"+i);
        }
    
  • 跟踪控制台输出的日志结果
    在这里插入图片描述

常见坑点

sql映射文件没有在核心配置文件中注册时:
在这里插入图片描述

Sql映射文件和所实现的接口文件不在同一个目录

如何确认接口文件和sql映射文件是否在一个目录呢?可以通过mvn:compile编译项目后,观察target中的classes目录。同一目录的现象如下所示:

UsersDao.java和UsersDao.xml“紧紧挨在一起“
在这里插入图片描述

i

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

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

相关文章

JavaScript中的this指向

1. 全局环境下的this 在全局环境中&#xff08;在浏览器中是window对象&#xff0c;在Node.js中是global对象&#xff09;&#xff0c;this指向全局对象。 console.log(this window); // 在浏览器中为true console.log(this.document ! undefined); // true&#xff0c;因为…

若依前后端分离 前端路由登录页 如何进行跳转

路由守卫&#xff0c;看这篇文章 http://t.csdnimg.cn/HkypThttp://t.csdnimg.cn/HkypT

LLM推理引擎性能评测对比:vllm、lmdeploy、tensorrt-llm

01 简介 在当今LLM时代&#xff0c;大模型的效果已经取得了长足的进步&#xff0c;逐渐成为业务流程中的重要部分&#xff0c;因此对性能进行评估变得至关重要&#xff0c;由于目前LLM推理都需要比较高级的GPU&#xff0c;使得LLM推理成本高&#xff0c;因此在不同使用场景下…

VS2019+QT VS tools:Debug下ok,relese下报错

报错界面 踩得坑&#xff1a; 尝试一下重装 QT VS tools&#xff0c;结果装不上。 尝试卸载原来的QT VS tools&#xff1a;卸载方法&#xff0c;到下面文件夹下可以看到有两个文件夹&#xff0c;分别是两个插件&#xff0c;找到QT的插件&#xff0c;删除文件夹即可。但是删除…

基于深度学习网络的USB摄像头实时视频采集与火焰检测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 将usb摄像头对准一个播放火焰的显示器&#xff0c;然后进行识别&#xff0c;识别结果如下&#xff1a; 本课题中&#x…

实验七 SQL数据更新和视图

题目 &#xff08;1&#xff09;向商品类别表category中插入一条记录&#xff08;801&#xff0c;‘座椅套’&#xff0c;‘各种品牌的汽车座套’&#xff09; &#xff08;2&#xff09;向商品表product中插入一条记录&#xff1a;商品编号80101&#xff0c;商品名称“四季通…

汽车免拆诊断案例 | 2021款路虎揽胜运动版车遥控及一键起动功能失效

故障现象 一辆2021款路虎揽胜运动版车&#xff0c;搭载AJ20-P6H3L发动机&#xff0c;累计行驶里程约为2.5万km。车主反映&#xff0c;使用智能钥匙无法解锁车门&#xff0c;使用机械钥匙打开车门&#xff0c;进入车内&#xff0c;发现一键起动功能也失效&#xff1b;根据组合…

电脑录制视频的软件,电脑录制,4款免费软件推荐

在数字化时代&#xff0c;电脑录制视频的软件已成为我们日常生活和工作中的得力助手&#xff0c;这些软件可以帮助我们轻松捕获到屏幕上的精彩瞬间。但同时市面上的录制视频软件也层出不穷&#xff0c;让人不知该如何选择。到底怎样才能选择到一款适合自己的录屏软件呢&#xf…

实验4 宏指令及子程序设计实验

从键盘输入10个无符号十进制数&#xff08;小于256&#xff09;&#xff0c;将其转换为二进制数并存放在NUM字节型变量中&#xff0c;找出其中的最大数&#xff0c;并将找出的最大数在屏幕上显示出来。 要求&#xff1a; 1&#xff09;在屏幕上显示字符串提示信息的功能由宏指…

基于单片机的出租车计价器实验教学案例设计

摘 要 为了让学生加深单片机的理解&#xff0c;加强学生的单片机技术应用、实践动手、创新能力的培养&#xff0c;根据单片机课程设计教学情况精心设计了基于单片机的出租车计价器实验教学案例。本教学案例的基本原理是速度的检测&#xff0c;里程、价格的计算和显示。学生通…

Pylons 和 Flex 3

“Pylons” 和 “Flex 3” 是两个不同的技术&#xff0c;各自有着不同的背景和应用场景&#xff1a; Pylons Pylons 是一个 Python Web 框架&#xff0c;用于快速开发 Web 应用程序。它强调简单性、灵活性和可扩展性&#xff0c;以便开发人员能够快速构建和部署功能强大的 We…

如何在Linux上删除Systemd服务

Systemd是Linux 操作系统的系统和服务管理器&#xff0c;提供控制系统启动时启动哪些服务的标准流程。 有时&#xff0c;您可能出于各种原因需要删除systemd服务&#xff0c;例如不再需要、与其他服务冲突&#xff0c;或者您只是想清理系统。 Systemd使用单元文件来管理服务&…

【Linux】虚拟机安装 openEuler 24.03 X86_64

目录 一、概述 1.1 openEuler 覆盖全场景的创新平台 1.2 系统框架 1.3 平台框架 二、安装详细步骤 一、概述 1.1 openEuler 覆盖全场景的创新平台 openEuler 已支持 x86、Arm、SW64、RISC-V、LoongArch 多处理器架构&#xff0c;逐步扩展 PowerPC 等更多芯片架构支持&…

行车记录打不开:故障深度解析、恢复策略与预防指南

一、行车记录打不开的困境概述 行车记录仪&#xff0c;作为现代驾驶安全的重要辅助工具&#xff0c;不仅记录着每一次出行的点滴&#xff0c;更在关键时刻成为维护权益的关键证据。然而&#xff0c;当车主满怀期待地想要回顾或分享这些记录时&#xff0c;却遭遇了行车记录打不…

Tomcat服务部署安装

一、Tomcat基础 1.Tomcat简介 Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;Tomcat虽然和Apache或者Nginx这些Web服务器一样&#xff0c;具有处理HTML页面的功能&#xff0c;然而由于其处理静态HTML的能力远不及Apache或者Nginx&#xff0c;所以Tomcat通常…

存储器类型介绍

存储器 ROM 我们一般把手机和电脑的硬盘当作ROM。ROM的全称是&#xff1a;Read Only Memery&#xff0c;只读存储器&#xff0c;就是只能读不能写的存储器。但是现在的ROM不仅可以读&#xff0c;还可以写数据&#xff0c;比如给手机下载APP&#xff0c;就是给手机上的ROM写数据…

《ClipCap》阅读笔记(上)

原文出处 [2111.09734] ClipCap: CLIP Prefix for Image Captioning (arxiv.org) 原文笔记 What ClipCap&#xff1a; CLIP Prefix for Image Captioning 一言以蔽之&#xff1a;使用 CLIP 编码作为标题的前缀&#xff0c;使用简单的映射网络&#xff0c;然后微调语言模型…

光伏电站数据采集方案(基于工业路由器部署)

​ 一、方案概述 本方案采用星创易联SR500工业路由器作为核心网关设备&#xff0c;实现对光伏电站现场数据的实时采集、安全传输和远程监控。SR500具备多接口、多功能、高可靠性等特点&#xff0c;能够满足光伏电站数据采集的各种需求。&#xff08;key-iot.com/iotlist/sr500…

完全理解C语言函数

文章目录 1.函数是什么2.C语言中的函数分类2.1 库函数2.1.1 如何使用库函数 2.2自定义函数 3.函数的参数3.1 实际参数&#xff08;实参&#xff09;3.2 形式参数&#xff08;形参&#xff09; 4.函数调用4.1传值调用4.2 传址调用4.3 练习 5.函数的嵌套调用和链式访问5.1 嵌套调…

LLMs之gpt_academic:gpt_academic的简介、安装和使用方法、案例应用之详细攻略

LLMs之gpt_academic&#xff1a;gpt_academic的简介、安装和使用方法、案例应用之详细攻略 目录 gpt_academic的简介 1、版本更新历史 版本: 1、新增功能及其描述 新界面&#xff08;修改config.py中的LAYOUT选项即可实现“左右布局”和“上下布局”的切换&#xff09; 所…