Mybatis 简介(一)

news2024/12/30 2:42:50

这里使用的是3.5.11版本

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

1、持久层框架对比

- JDBC
    - SQL 夹杂在Java代码中耦合度高,导致硬编码内伤
    - 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见
    - 代码冗长,开发效率低
- Hibernate 和 JPA
    - 操作简便,开发效率高
    - 程序中的长难复杂 SQL 需要绕过框架
    - 内部自动生成的 SQL,不容易做特殊优化
    - 基于全映射的全自动框架,大量字段的 POJO 进行部分映射时比较困难。
    - 反射操作太多,导致数据库性能下降
- MyBatis
    - 轻量级,性能出色
    - SQL 和 Java 编码分开,功能边界清晰。Java代码专注业务、SQL语句专注数据
    - 开发效率稍逊于 Hibernate,但是完全能够接收

开发效率:Hibernate>Mybatis>JDBC

运行效率:JDBC>Mybatis>Hibernate

封装越多,运行效率越慢

2、快速入门(案例)

有一个mybitas数据库,使用Mybaits框架来使用id查询数据。

之前Dao时我们都是创建一个Dao接口,然后自己实现该接口,将sql语句等都写在类里。

使用Mybstis之后,我们只用写一个xxxMapper接口,之后编写xxxMapper.xml配置信息,在xml文件中编写sql语句,之后再编写一个mabatis-config.xml配置文件(配置数据库信息,以及我们mapper接口的位置),最后使用mybatisapi来进行数据库操作即可。

步骤①导入依赖

<dependencies>
  <!-- mybatis依赖 -->
  <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.11</version>
  </dependency>

  <!-- MySQL驱动 mybatis底层依赖jdbc驱动实现,本次不需要导入连接池,mybatis自带! -->
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.25</version>
  </dependency>

  <!--junit5测试-->
  <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter-api</artifactId>
      <version>5.3.1</version>
  </dependency>
</dependencies>

②.准备实体类

public class Employee {

    private Integer empId;

    private String empName;

    private Double empSalary;
    
    //getter | setter
}

③准备mapper接口以及mapperxml文件

MyBatis 框架下,SQL语句编写位置发生改变,从原来的Java类,改成**XML**或者注解定义!

推荐在XML文件中编写SQL语句,让用户能更专注于 SQL 代码,不用关注其他的JDBC代码。

如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码!!

一般编写SQL语句的文件命名:XxxMapper.xml  Xxx一般取表名!!

Mybatis 中的 Mapper 接口相当于以前的 Dao。但是区别在于,Mapper 仅仅只是建接口即可,我们不需要提供实现类,具体的SQL写到对应的Mapper文件,该用法的思路如下图所示:

a.定义mapper接口

package com.cky.impl;

import com.cky.pojo.Employee;

public interface Mymapper {
   Employee queryByid(int id);
}

b.定义mapperxml文件

位置resources/mapper/Mymapper.xml 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.cky.impl.Mymapper">

    <!-- 查询使用 select标签
            id = 方法名
            resultType = 返回值类型
            标签内编写SQL语句
     -->
    <select id="queryByid" resultType="com.cky.pojo.Employee">
        <!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解 -->
        select emp_id empId,emp_name empName, emp_salary empSalary from
        t_emp where emp_id = #{empId}
    </select>
</mapper>

**注意:**
  - 方法名和SQL的id一致
  - 方法返回值和resultType一致
  - 方法的参数和SQL的参数一致
  - 接口的全类名和映射配置文件的名称空间一致 

④准备Mybatis配置文件

在Resource文件下

mybatis框架配置文件: 数据库连接信息,性能配置,mapper.xml配置等!

习惯上命名为 mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。将来整合 Spring 之后,这个配置文件可以省略,所以大家操作时可以直接复制、粘贴。

<?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>

    <!-- environments表示配置Mybatis的开发环境,可以配置多个环境,在众多具体环境中,使用default属性指定实际运行时使用的环境。default属性的取值是environment标签的id属性的值。 -->
    <environments default="development">
        <!-- environment表示配置Mybatis的一个具体的环境 -->
        <environment id="development">
            <!-- Mybatis的内置的事务管理器 -->
            <transactionManager type="JDBC"/>
            <!-- 配置数据源 -->
            <dataSource type="POOLED">
                <!-- 建立数据库连接的具体信息 -->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="cky"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- Mapper注册:指定Mybatis映射文件的具体位置 -->
        <!-- mapper标签:配置一个具体的Mapper映射文件 -->
        <!-- resource属性:指定Mapper映射文件的实际存储位置,这里需要使用一个以类路径根目录为基准的相对路径 -->
        <!--    对Maven工程的目录结构来说,resources目录下的内容会直接放入类路径,所以这里我们可以以resources目录为基准 -->
        <mapper resource="mapper/Mymapper.xml"/>
    </mappers>

</configuration>

⑤测试

import com.cky.impl.Mymapper;
import com.cky.pojo.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;

public class Mybatis_test {
    /**
     * projectName: com.atguigu.test
     *
     * description: 测试类
     */

        @Test
        public void testSelectEmployee() throws IOException {

            // 1.创建SqlSessionFactory对象
            // ①声明Mybatis全局配置文件的路径
            String mybatisConfigFilePath = "mybatis-config.xml";

            // ②以输入流的形式加载Mybatis配置文件
            InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);

            // ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

            // 2.使用SqlSessionFactory对象开启一个会话
            SqlSession session = sessionFactory.openSession();

            // 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
//使用的是jdk动态代理,底层仍然调用的是ibtsa的对应的方法。
//动态代理将namespce与方法名连接,之后将参数整合到一起。
            Mymapper employeeMapper = session.getMapper(Mymapper.class);

            // 4. 调用代理类方法既可以触发对应的SQL语句
            Employee employee = employeeMapper.queryByid(1);

            System.out.println("employee = " + employee);

            // 4.关闭SqlSession
            session.commit(); //提交事务 [DQL不需要,其他需要]
            session.close(); //关闭会话

        }
    }

注意:Mapper接口的抽象方法不能重载!!! 

3、Mybatis基本使用

3.1 向sql语句传参

 3.1.1 打开日志输出配置

通过日志输出配置,我们可以看到接下来我们要讲解的#{}和${}接收参数的区别。

mybatis配置文件中添加日志配置

日志配置:

<settings>
  <!-- SLF4J 选择slf4j输出! -->
  <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

3.1.2 #{} 接收参数

Mybatis会将SQL语句中的#{}转换为问号占位符。占位符+赋值

3.1.3 ${} 接收参数

直接赋值,字符串直接拼接

注意:

通常不会采用${}的方式传值,为了防止注入攻击。一个特定的适用场景是:通过Java程序动态生成数据库表,表名部分需要Java程序通过参数传入;而JDBC对于表名部分是不能使用问号占位符的,此时只能使用

结论:实际开发中,能用#{}实现的,肯定不用${}。

特殊情况: 动态的不是值,是列名或者关键字或者表名,需要使用${}拼接

3.2 传入参数类型

这里数据输入具体是指上层方法(例如Service方法)调用Mapper接口时,数据传入的形式。

- 简单类型:只包含一个值的数据类型
    - 基本数据类型:int、byte、short、double、……
    - 基本数据类型的包装类型:Integer、Character、Double、……
    - 字符串类型:String
- 复杂类型:包含多个值的数据类型
    - 实体类类型:Employee、Department、……
    - 集合类型:List、Set、Map、……
    - 数组类型:int[]、String[]、……
    - 复合类型:List<Employee>、实体类中包含集合……

根据不同的传入类型,我们有不同的规则

3.2.1 传入单个简单类型

mapper接口中抽象方法声明;

Employee selectEmployee(Integer empId);

mapperxml文件中sql语句

<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
  select emp_id empId,emp_name empName,emp_salary empSalary from t_emp where emp_id=#{empId}
</select> 

这里我们只需要传入一个简单的基本数据类型即可,因为参数只有一个,单个简单类型参数,

在#{}中可以随意命名,但是没有必要。通常还是使用和接口方法参数同名。

3.2.2 传入一个实体参数类型

mapper接口抽象类定义

int insertEmployee(Employee employee);

mapperxmlSQL语句

<insert id="insertEmployee">
  insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert> 

 对于实体类,我们需要传入的参数要与实体类对象的变量名相同,不能乱写。

3.2.3多个简单数据类型

mapper接口抽象方法

Employee querybyidandname(Integer id,String name);

mapperxmlSQL编写

//不可以随便写 也不能按照抽象方法中的参数名来取
//方法1 mybatis默认机制 参数默认从arg0...argx 开始
//方法2 @Param注解 写在接口的抽象方法中
<select id="querybyidandname" resultType="com.cky.pojo.Employee">
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${arg0} and emp_name=#{arg1}
</select>

 此时类方法这样写

Employee querybyidandname(@Param("a") Integer id, @Param("b") String name);

SQL语句这样写

<select id="querybyidandname" resultType="com.cky.pojo.Employee">
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${a} and emp_name=#{b}
</select>

3.2.4 Map参数数据类型

mapper接口方法

Employee querybyidandname(Map data);

Sql语句

<select id="querybyidandname" resultType="com.cky.pojo.Employee">
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${emp_id} and emp_name=#{emp_name}
</select>

 传入的是Map时,sql语句中接收根据我们传入map的参数名的key就可以.

3.3 输出数据类型

对于增删改 一般都只返回影响行数 用int或者long 接收即可。

但是对于查询,返回的类型就多种多样,那么sql语句的ResultType如何编写呢?

3.3.1 单个简单输出类型

ResultType 写法

 1、如果返回的是我们的实体类,直接写类的全限定符即可

2、别名简称

  java为我们提供了72中基本数据类型的简称

基本上可以分为:

 ①基本数据类型   int  double->_int _double

 ②包装数据类型  Integer Double ->int double

 ③基本组合数据类型  Map List->小写即可

3、自定义数据类型

  如何为我们自己的类自定义别名呢?可以在Mybatis配置文件中配置

官网别名解释

①挨个类配置

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

 ②批量给包下的类给别名,别名就是类的首字母小写

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

如果在批量给别名之后,我们仍想给某些类自己配置别名的话怎么办呢?

可以在类名上添加@Alias注解,注意该注解必须与批量给别名一起使用,否则不生效

@Alias("author")
public class Author {
    ...
}

3.3.2 单个实体类型输出

对于ResultType 我们可以①使用类的全限定符 ②起别名使用别名

注意:这里有个默认要求:

我们数据库的列名必须等于属性名 但是如果我们都配置别名的话,比如下方,就会比较麻烦。

<select id="querybyidandname" resultType="com.cky.pojo.Employee">
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${emp_id} and emp_name=#{emp_name}
</select>

这里,mybatis有个设置,开启该该驼峰式映射设置之后,框架会自动给我们起别名

但是规则是去掉数据库列名下划线,将下划线后的首字母变大写

比如 数据库列名 emp_id 会自动帮我们映射为 empId

如何开启驼峰式映射呢?

在settings中编写

<!-- 在全局范围内对Mybatis进行配置 -->
<settings>

  <!-- 具体配置 -->
  <!-- 从org.apache.ibatis.session.Configuration类中可以查看能使用的配置项 -->
  <!-- 将mapUnderscoreToCamelCase属性配置为true,表示开启自动映射驼峰式命名规则 -->
  <!-- 规则要求数据库表字段命名方式:单词_单词 -->
  <!-- 规则要求Java实体类属性名命名方式:首字母小写的驼峰式命名 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

3.3.3 返回map类型

如果返回的是实体类型,则ResultType直接写相应的实体类全限定符或者我们定义过的简写就行。

但是如果返回的不是实体类型呢?

我们可以用Map接收。

mapper接口抽象类方法

//根据id来查找姓名和工资,返回的不是一个实体类,我们可以用map来接收
Map<String,Double> querybyid(Integer id);

mapperXML文件

<select id="querybyid" resultType="map">
    select emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${emp_id}
</select>

3.3.4 返回集合类型

有时候,我们查找返回的是多条信息,这时候我们返回值类型就是一个集合类型

mapper接口

//返回的是一个集合
List<Employee> queryByname(String name);

mapperXML文件

<select id="queryByname" resultType="com.cky.pojo.Employee">
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_name = #{emp_name}
</select>

 这里需要注意:

我们resultType接收的是集合的泛型,而不需要写list

3.3.5 主键回显

a.对于自增长类型主键

int insertnew(Employee employee);
<insert id="insertnew" useGeneratedKeys="true" keyColumn="emp_id" keyProperty="empId">
        insert into t_emp(emp_name,emp_salary) values(#{empName},#{empSalary})
</insert>
<!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
<!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->
keyColumn 表示我们在数据库中的列名

如果我们不指定这三个值,之后我们便不会将id 赋给该实体的empId属性,我们就不到该值。

测试:

import com.cky.impl.Mymapper;
import com.cky.pojo.Employee;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

public class Mybatis_test {
    /**
     * projectName: com.atguigu.test
     *
     * description: 测试类
     */

        @Test
        public void testSelectEmployee() throws IOException {

            // 1.创建SqlSessionFactory对象
            // ①声明Mybatis全局配置文件的路径
            String mybatisConfigFilePath = "mybatis-config.xml";

            // ②以输入流的形式加载Mybatis配置文件
            InputStream inputStream = Resources.getResourceAsStream(mybatisConfigFilePath);

            // ③基于读取Mybatis配置文件的输入流创建SqlSessionFactory对象
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
           Employee employee1=new Employee();
           employee1.setEmpName("cui");
           employee1.setEmpSalary(20000.0);
            // 2.使用SqlSessionFactory对象开启一个会话
            SqlSession session = sessionFactory.openSession();

            // 3.根据EmployeeMapper接口的Class对象获取Mapper接口类型的对象(动态代理技术)
            Mymapper employeeMapper = session.getMapper(Mymapper.class);

            // 4. 调用代理类方法既可以触发对应的SQL语句
            int rows = employeeMapper.insertnew(employee1);
        System.out.println(employee1.getEmpId());
            System.out.println("rows = " +rows );

            // 4.关闭SqlSession
            session.commit(); //提交事务 [DQL不需要,其他需要]
            session.close(); //关闭会话

        }
    }

结果:

 

如果没有配置那三个参数,我们将获得null

注意:我们也可以在 这句代码里自动开启提交事务,填写ture表示开启,默认为false

 SqlSession session = sessionFactory.openSession(true);

b.对于非自增长主键

而对于不支持自增型主键的数据库(例如 Oracle)或者字符串类型主键,则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用!

使用 `selectKey` 帮助插入UUID作为字符串类型主键示例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace等于mapper接口类的全限定名,这样实现对应 -->
<mapper namespace="com.cky.impl.TeacherMapper">
<insert id="insertTeacher">
    <!--非自增长的主键,交给mybits帮助我们维护-->
    <selectKey order="BEFORE" resultType="string" keyProperty="tID">SELECT REPLACE(UUID(),'-','');</selectKey>
    insert into teacher(t_id,t_name) values(#{tID},#{tName})
</insert>

</mapper>

 通过 `keyProperty` 属性来指定查询到的 UUID 赋值给对象中的 `id` 属性,而 `resultType` 属性指定了 UUID 的类型为 `java.lang.String`。

order 有两个选值 BEFORE|AFTER 

before 表示在insert语句执行之前执行 selectkey 反之表示在之后执行。这里生成id,并把id配置给Teacher 属性,肯定是在之前执行。

通过这种方式,我们不必在自己维护给Teacher对象添加id属性,而是通过mybitas来维护生成id。

使用这种方式,我们可以方便地插入 UUID 作为字符串类型主键。当然,还有其他插入方式可以使用,如使用Java代码生成UUID并在类中显式设置值等。需要根据具体应用场景和需求选择合适的插入方式。  Java代码自己生成UUID来显示设置如下:

        //自己维护主键
//        String id= UUID.randomUUID().toString().replaceAll("-","");
        Teacher teacher=new Teacher();
        tearucher.settName("hhh");

//     teacher.settID(id);

3.3.6 当列名和属性名不一致时

(1)起别名

  我们可以在sql语句中为 列名起别名 别名与哦我们的属性名一致即可

<select id="queryByid" resultType="com.cky.pojo.Employee">
    <!-- #{empId}代表动态传入的参数,并且进行赋值!后面详细讲解 -->
    select emp_id empId,emp_name empName, emp_salary empSalary from
    t_emp where emp_id = ${empId}
</select>

(2)开启驼峰式映射

<!-- 使用settings对Mybatis全局进行设置 -->
<settings>

  <!-- 将xxx_xxx这样的列名自动映射到xxXxx这样驼峰式命名的属性名 -->
  <setting name="mapUnderscoreToCamelCase" value="true"/>

</settings>

 

(3)使用resultMap自定义映射

resultType与resultMap 二选一

resultType按照规则自动映射,如果开启了驼峰式映射,会自动映射属性名和列名,但是只能单层映射。多表查询时就无法映射。

resultMap自定义映射关系,可以深层次可以单层次。 

<!-- 专门声明一个resultMap设定column到property之间的对应关系 -->
<resultMap id="selectEmployeeByRMResultMap" type="com.atguigu.mybatis.entity.Employee">

  <!-- 使用id标签设置主键列和主键属性之间的对应关系 -->
  <!-- column属性用于指定字段名;property属性用于指定Java实体类属性名 -->
  <id column="emp_id" property="empId"/>

  <!-- 使用result标签设置普通字段和Java实体类属性之间的关系 -->
  <result column="emp_name" property="empName"/>

  <result column="emp_salary" property="empSalary"/>

</resultMap>

<!-- Employee selectEmployeeByRM(Integer empId); -->
resultMap=“id标识”
<select id="selectEmployeeByRM" resultMap="selectEmployeeByRMResultMap">

  select emp_id,emp_name,emp_salary from t_emp where emp_id=#{empId}

</select>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

非连续分配管理方式-基本分页存储管理

非连续分配-可为用户进程分配分散的内存空间 一、存储过程 1.将内存空间分成大小相等的分区&#xff0c;每个分区为一个页框/页帧(内存块/物理块/物理页面)&#xff0c;每个页框有一个编号(页框号/内存块号/物理块号)&#xff0c;从0开始 2.将进程的逻辑地址空间也分为与页框…

在NodeJS中使用npm包实现JS代码混淆加密

使用npm包&#xff0c;在NodeJS中实现JS代码混淆加密 在前后端JS开发过程中&#xff0c;JS代码保护&#xff08;JS代码混淆加密&#xff09;是非常重要的一环。 JShaman是一个云端的代码保护Saas平台&#xff0c;可以对JS代码进行混淆、加密、压缩等操作&#xff0c;从而增强…

[极客大挑战 2019]EasySQL

【解题思路】 1.打开靶机链接 2.输入数据进行尝试 输入1,1&#xff1a; 可以在导航栏里面看到username和password的变量。 3.使用万能密码 username&#xff1a;1 or 11# username&#xff1a;任意数据 password&#xff1a;任意数据 …

传统制造业如何转型?什么是智能工厂?

本文将为大家讲解&#xff1a;传统制造业如何转型&#xff1f;什么是智能工厂&#xff1f; 一、传统工业存在哪些痛点 相较于新兴工业&#xff0c;传统工业在当前发展放缓&#xff0c;并受到了一波互联网数字化智能化发展的冲击。 1、低效率和高成本 传统工业通常采用传统的…

C算法:写一个用于找出数组的最大值和最小值的函数

需求&#xff1a; 写一个用于找出数组的最大值和最小值的函数。 示例&#xff1a;int array[9] {5, 9, 3, 1, 2, 8, 4, 7, 6}; 该数组最大值的下标为1&#xff0c;最小值的小标为3。 代码实现&#xff1a; #include <stdio.h>int getNum(int *array,int len,int (*…

【JAVA学习笔记】39 - final关键字

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter10/src/com/yinhai/final_ 一、final关键字基本介绍 final可以修饰类、属性、方法和局部变量&#xff0c; 在某些情况下&#xff0c;程序员可能有以下需求&#xff0c;就会使用到final 1)当…

C算法:米m 转化 英尺foot和英寸inch

需求&#xff1a; 已知1英尺等于12英寸&#xff0c;如果已知英制长度的英尺foot和英寸inch的值&#xff0c;那么对应的米是(footinch/12)*0.3048&#xff0c;现在&#xff0c;用户输入的是厘米数&#xff0c;那么对应英制长度的英尺和英寸是多少呢? 输入样例&#xff1a; 1…

ITSource 分享 第4期【简洁的问卷调查系统】

项目介绍 本期给大家介绍一个 简洁的问卷的调查系统。 一 业务介绍 本系统分为以下几个模块: 1.登录注册 2.新建问卷 注册登录完成后,即可进入首页 可以创建问卷 目前只有单选&#xff0c;多选&#xff0c;简答三种问题类型&#xff0c;并且可以选择手动结束和自动结束模式。…

【强化学习】07——规划与学习(Dyna-Q)

文章目录 前置知识回顾策略值函数估计&#xff08;Policy Evaluation&#xff09;策略提升&#xff08;Policy Improvement&#xff09; 模型&#xff08;Model&#xff09;规划(Planning)规划与学习(Planning and Learning)Dyna (集成规划、决策和学习&#xff09;Dyna的框架D…

企业使用微信管理系统更安全更高效更智能

. 想快速处理纠纷&#xff0c;不知道员工和客户孰对孰错&#xff1f; 想提高客户满意度&#xff0c;不清楚客服沟通全过程&#xff1f; 想维护公司利益&#xff0c;不了解销售聊了哪些事&#xff1f; 想知道客户流失原因&#xff0c;不确定沟通话术是否专业&#xff1f; …

第56篇-某度旋转验证码v1分析-旋转验证码【2023-10-24】

声明&#xff1a;该专栏涉及的所有案例均为学习使用&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;如有侵权&#xff0c;请私信联系本人删帖&#xff01; 一、网站分析 网址&#xff1a; aHR0cHM6Ly93YXBwYXNzLmJhaWR1Lm…

栈和队列相关的OJ题

1.栈的压入、弹出序列 题目链接 栈的压入、弹出序列_牛客题霸_牛客网 (nowcoder.com) 题目描述 题目给出两个序列&#xff0c;一个是入序列pushV&#xff0c;一个是出序列popV&#xff0c;要求判断是否匹配入栈出栈的规则顺序。 解题思路 可以用数据模拟入栈出栈&#xf…

基于樽海鞘群算法的无人机航迹规划-附代码

基于樽海鞘群算法的无人机航迹规划 文章目录 基于樽海鞘群算法的无人机航迹规划1.樽海鞘群搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用樽海鞘群算法来优化无人机航迹规划。 …

一文讲清楚检索增强生成(RAG)

文章目录 什么是检索增强生成&#xff1f;逆向工作&#xff1a;为大语言模型提供额外的知识来回答问题通过系统提示给出LLM自定义指令为LLM提供特定的知识来源将所有内容放在一起并提出问题检索步骤&#xff1a;从您的知识库中获取正确的信息什么是嵌入&#xff1f;它们与知识检…

【第四天]C++高级类和对象:运算符重载、string类和智能指针的深度解析

一、运算符重载 运算符重载 是对已有的运算符 指定新功能&#xff0c;不能创建新运算符。 运算符重载关键字operator 语法&#xff1a;operator &#xff08;表示被重载的运算符&#xff09; 思路&#xff1a; 1、弄懂 函数的参数中参数个数取决于运算符是一元还是二元…

如何高效地给视频批量添加logo水印?

如果你想给大量的视频添加图片水印&#xff0c;那么固乔剪辑助手软件是一个非常不错的选择。通过这个软件&#xff0c;你可以轻松地批量添加图片水印&#xff0c;提高视频的质量和识别度。以下是如何使用固乔剪辑助手软件给视频批量添加图片水印的步骤&#xff1a; 步骤1&#…

Qt+树莓派4B 窗口半透明效果实现

文章目录 前言一、窗口半透明&#xff0c;窗口部件不透明1、构造函数中的设置2、paintEvent3、效果4、树莓派4B配置5、最终效果 前言 在树莓派4B下&#xff0c;使用Qt开发窗口半透明而窗口部件不透明效果时,发现窗口没能正常实现半透明效果,而是显示纯黑色背景。同样的代码在wi…

PLC 学习day03 PLC软件安装 PLC软件的介绍和对应的知识

1.资料来源 链接&#xff1a;7.PLC编程学习入门视频教程全集-三菱GX-Works2编程软件安装_哔哩哔哩_bilibili 链接&#xff1a;8.三菱plc视频教程全集之编程语言及软元件介绍_哔哩哔哩_bilibili 2. PLC软件的安装 三菱的PLC软件安装视屏的链接&#xff1a; 7.PLC编程学习入门视频…

Gymnasium的基本用法

目录 1.初始化环境 2.与环境交互 3.动作和观测空间 4.修改环境 Gymnasium是一个为所有单智能体强化学习环境提供API的项目&#xff0c;包括常见环境的实现:cartpole、pendulum、mountain-car、mujoco、atari等。 该API包含四个关键功能:make、reset、step和render&#xf…

对称加密操作

#常用密码技术 ##1 密码 1.1 发送者、接收者和窃听者 请想象一个Alice向Bob发送电子邮件的场景。在这个场景中&#xff0c;发出邮件的Alice称为 发送者&#xff08;sender&#xff09;&#xff0c;而收到邮件的Bob则称为 接收者&#xff08;receiver&#xff09;。 在讲解发送…