当前位置: 首页 > news >正文

Mybatis 复习

1 什么是MyBatis

MyBatis是一个优秀的持久层框架,它对JDBC操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、 结果集检索等JDBC繁杂的过程代码 。

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

1.2 MyBatis的优点

  1. 简单易、 没有任何第三方依赖,最简单安装只要两个jar文件 + 配置几个sql映射文件,
  2. Mybatis不会对应用程序或者数据库的现有设计强加任何影响,sql写在xml里,便于统一管理和优 化。 通过sql语句可以满足操作数据库的所有需求。
  3. 解除sql与程序代码的耦合: 通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测 试。 sql和代码的分离,提高了可维护性 。
  4. 提供丰富且强大的标签 。

1.3 为什么要学Mybatis

当使用java代码操作数据库时,需要用到 JDBC编程 ,但JDBC在使用时存在问题:

1. 数据库连接使用时就创建,不使用时便立即释放,从而对数据库进行频繁的操作,导致资源的浪  

费、影响性能。
2. sql都是硬编码到Java程序中,如果改变sql,那么得重新编译Java代码,不利于系统后期的维护。
3. 向PreparedStatement设置参数,也是硬编码到Java程序中,不利于后期的维护。
4. 从resultset遍历结果集数据时,也存在硬编码,不利于后期系统的维护。

1.4 MyBatis整体架构

  1. MyBatis配置: mybatis-config.xml(名称不固定),此文件作为MyBatis的全局(核心)配置文件,配置了 MyBatis的运行环境等信息。 mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。
  2. 通过MyBatis环境等配置信息构造SqlSessionFactory,即会话工厂。
  3. 由会话工厂创建SqlSession即会话,操作数据库需要通过SqlSession进行。
  4. MyBatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行 器、一个是缓存执行器。
  5. MappedStatement也是MyBatis一个底层封装对象,Mybatis将SQL的配置信息加载成为一个个 MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存 中。mapper.xml文件中一个sql对应一个MappedStatement对象,sql的id即是MappedStatement的 id。
  6. MappedStatement对sql执行输入参数进行定义,包括HashMap、基本类型、字符串类型、实体类 类型,Executor通过MappedStatement在执行sql前将输入的Java对象映射至sql中,输入参数映射就是 JDBC编程中对PreparedStatement设置参数。
  7. MappedStatement对sql执行输出结果进行定义,包括HashMap、基本类型、字符串类型、实体类 类型,Executor通过MappedStatement在执行sql后将输出结果映射至Java对象中,输出结果映射过程 相当于JDBC编程中对结果的解析处理过程。

1.5 vo、po、dto、bo、pojo、entity 等层的解释。

  • VO:值对象 ,由new创建,由GC回收,存放指定的数据,可以和表数据不一致。
  • PO:是 ORM 框架中Entity,PO属性和数据库中表的字段形成一一对应关系 加上get和set方法 ;
  • entity :和PO的功能类似,和数据表一 一对应,一个实体一张表 。
  • dto: 数据传输对象 ,存放页面需要的表的部分字段。
  • bo: BO是封装业务逻辑的Java对象,封装了多个po,vo,通过调用DAO方法,进行业务操作。
  • pojo:简单来说可以理解成不包含业务逻辑的单纯用来存储数据的Java类 , 可以转化为PO、DTO、VO。
    • 一个POJO持久化以后就是PO; 直接用它传递、传递过程中就是DTO; 直接用来对应表示层就是VO;

2 建立MyBatis项目

2.1新建一个java项目,导入maven包

<dependencies><!-- mybatis --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.6</version></dependency><!-- oracle:大家在引入oracle依赖的时候肯定出错 --><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>11.2.0.1.0</version></dependency><!--  mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.49</version></dependency><!-- log4j Mybatis的日志输出组件 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency>
</dependencies>

2.2 编写MyBatis中全局配置文件 mybatis-config.xml

 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><!-- configuration 文件的根节点 -->
<!-- MyBatis配置文件报错:
在编写xml配置文件引入DTD约束时,可能会出现这个错误提示 URI is not registered(Settings | 
Languages & Frameworks | Schemas and DTDs),此时使用快捷键,选择Fetch external 
resource 或 Ignore external resource选项。或者直接在设置settings -> languages&frameworks -> schemas and dtds 中添加出问题的路径。 -->
<configuration><!--properties 用于引入外部的properties配置文件resource:引入类路径下的文件url:引入磁盘或网路--><properties/><!-- environments:多个配置环境;通过default属性可以对多个环境快速切换。environments default属性的值必须和某个environment的id值一致。--><!-- 和spring整合后 environments配置将废除,了解即可 --><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=utf8&amp;useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments></configuration>

2.3 导入一个数据库SQL

CREATE TABLE `dept`  (`deptno` int PRIMARY KEY AUTO_INCREMENT,`dname` varchar(20),`loc` varchar(40)
);INSERT INTO `dept` VALUES (10, 'ACCOUNTING', 'NEW YORK');INSERT INTO `dept` VALUES (20, 'RESEARCH', 'DALLAS');INSERT INTO `dept` VALUES (30, 'SALES', 'CHICAGO');INSERT INTO `dept` VALUES (40, 'OPERATIONS', 'BOSTON');CREATE TABLE `emp`  (`empno` int PRIMARY KEY AUTO_INCREMENT,`ename` varchar(20),`job` varchar(20),`mgr` int,`hiredate` date,`sal` double,`comm` double,`deptno` int,CONSTRAINT `FK_EMP_DEPTNO` FOREIGN KEY (`deptno`) REFERENCES `dept` (`deptno`));INSERT INTO `emp` VALUES (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 1300, NULL, 20);INSERT INTO `emp` VALUES (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 2100, 300, 30);INSERT INTO `emp` VALUES (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1750, 500, 30);INSERT INTO `emp` VALUES (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 3475, NULL, 20);INSERT INTO `emp` VALUES (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1750, 1400, 30);INSERT INTO `emp` VALUES (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 3350, NULL, 30);INSERT INTO `emp` VALUES (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2950, NULL, 10);INSERT INTO `emp` VALUES (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3500, NULL, 20);INSERT INTO `emp` VALUES (7839, 'KING', 'PRESIDENT', NULL, '1981-11-17', 5500, NULL, 10);INSERT INTO `emp` VALUES (7844, 'TURNER', 'SALESMAN', 7698, '1981-09-08', 2000, 0, 30);INSERT INTO `emp` VALUES (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1600, NULL, 20);INSERT INTO `emp` VALUES (7900, 'JAMES', 'CLERK', 7698, '0198-12-31', 1450, NULL, 30);INSERT INTO `emp` VALUES (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3500, NULL, 20);INSERT INTO `emp` VALUES (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1800, NULL, 10);

2.4 编写实体类

import java.util.Date;public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;// 省略set,get方法}

2.5 编写映射文件

在src/main/resources下创建mapper目录,在该目录下创建sql映射文件Emp.xml。  
<?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">
<!--
namespace: 命名空间,作用是mapper文件进行分类管理,用于隔离sql语句。
注意:如果使用mapper代理的方式进行开发,namespace有特殊的作用。-->
<mapper namespace="emp"><!-- 通过员工编号查询员工信息 --><!--通过<select>标签编写查询语句id: 映射文件中SQL语句的唯一标识。mybatis会将SQL语句封装到MappedStatement对象中,所以此处的id也可以标识MappedStatement对象的id;注意:同一个mapper文件中id不能重复,而且id在mapper代理模式下有着重要作用;parameterType: 输入参数的类型。sql语句的占位符:#{};#{empno}:其中empno表示接收输入的参数值,参数名称为empno;但是如果参数的类型为简单类型(基本数据类型、包装类、字符串类型),参数名称可以任意指定;resultType: 输出参数的类型。需要指定输出数据为Java中的数据类型(实体类的全限定名);--><select id="selectById" parameterType="java.lang.Integer" resultType="com.gs.entity.Emp">select empno, ename, job, hiredate, mgr, sal, comm, deptno from emp where empno=#{empno}</select>
</mapper>

将这个mapper文件都丢到全局配置文件中。

<!-- 加载映射文件的位置 --><mappers><mapper resource="mapper/Emp.xml"/></mappers>

2.6 log4j配置 (在控制台可查看sql语句)

Mybatis日志输出:log4j.properties配置文件。

#井号表示注释,配置内容为键值对格式,每行只能有一个键值对,键值对之间以=连接
#指定logger#设定log4j的日志级别和输出的目的地
#INFO日志级别,Console和logfile输出的目的地
#等级 OFF,ERROR,WARN,INFO,DEBUG,TRACE,ALLlog4j.rootLogger=DEBUG,Console#指定appender#设定Logger的Console,其中Console为自定义名称,类型为控制台输出
log4j.appender.Console=org.apache.log4j.ConsoleAppender#设定Logger的logfile,其中logfile为自定义名称,类型为文件
#org.apache.log4j.FileAppender文件
#org.apache.log4j.RollingFileAppender文件大小到达指定尺寸后产生一个新的文件
#org.apache.log4j.DailyRollingFileAppender每天产生一个日志文件
log4j.appender.logfile=org.apache.log4j.RollingFileAppender#设定文件的输出路径
log4j.appender.logfile.File=d:/log/test.log#设定文件最大尺寸  单位可以使KB,MB,GBlog4j.appender.logfile.MaxFileSize=2048KB#输出格式
#设定appender布局Layout#   
%d 输出日志的日期和时间,指定格式:%d{yyyy-MM-dd HH:mm:ss SSS}#   
#   
#   
#   
#   
%p 输出的日志级别
%c 输出所属类的全类名
%M 方法名
%m 输出代码中指定消息
%n 一个换行符
log4j.appender.Console.layout=org.apache.log4j.PatternLayoutlog4j.appender.Console.layout.ConversionPattern=%d %p %c.%M() --%m%nlog4j.appender.logfile.layout=org.apache.log4j.PatternLayoutlog4j.appender.logfile.layout.ConversionPattern=%d %p %c.%M() --%m%n

2.7 编写测试程序 (在test路径下)

运行测试类;

/*** 测试程序*/
public class MybatisTest {@Testpublic void test() throws IOException {//1.创建读取全局配置文件的流InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();//2.通过配置文件流创建会话工厂SqlSessionFactory factory = builder.build(in);//3.通过会话工厂创建会话对象(SqlSession)SqlSession session = factory.openSession();//4.通过会话对象操作数据/*** 查询单条记录* selectOne(String statementId, Object param)* 参数1:映射文件中的statementId,命名空间名.statementId* 参数2:向sql语句中传入的数据,注意:传入的数据类型必须与映射文件中配置的
parameterType保持一致* 返回值:就是映射文件中配置的resultType的类型* 查询多条记录* selectList()*/Emp emp = session.selectOne("emp.selectById", 7369);System.out.println(emp);//5.关闭资源session.close();}
}

3 增删改查的基本操作的实现

实现以下功能: 1. 查询所有员工信息; 2. 添加员工; 3. 更新员工; 4. 删除员工; 5. 根据员工名模糊查询。

3.1 查询所有员工信息

编写mapper文件

<!--
查询到数据返回多条记录,每一条封装在一个实体类对象中,所有的实体类对象封装在List集合中
resultType:指定的并不是集合的类型,而是单条数据所对应实体类类型
resultType="java.util.List" 错误的配置方式-->
<select id="select" resultType="com.gs.entity.Emp">select empno, ename, job, mgr, hiredate, sal, comm, deptno from emp order by empno desc
</select>

在测试类编写

public class CURDTest {@Testpublic void testSelect() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();}
}
/*** 查询多条记录
* selectList(statement-sql语句的id, parameter-参数)* 表示将单条记录都存储输出映射对象中,每条记录的映射对象存放在List集合中
*/
List<Emp> list = session.selectList("emp.select");
for (Emp emp : list) {System.out.println(emp);
}

3.2 添加员工

编写mapper文件

<!--
添加操作使用insert标签;
增删改操作没有resultType,只有查询有resultType;
因为增删改操作返回值都是int类型,所以我们不需要指明;
注意:给占位符赋值,#{}中编写的内容为实体类型参数中的成员变量名称;#{empno}    
Mybatis会从传递过来的参数对象里面得到emono字段的值--><insert id="insert" parameterType="com.gs.entity.Emp">insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})</insert>

在测试类编写

public class CURDTest {@Testpublic void testSelect() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();}
}Emp emp = new Emp();emp.setEname("TOM");emp.setJob("CLARK");emp.setMgr(1);emp.setHiredate(new Date());emp.setSal(6500.0);emp.setComm(1200.0);System.out.println("新增之前的主键值为:" + emp.getEmpno());int result = session.insert("emp.insert", emp);}System.out.println("影响数据库的条数为:" + result);/*** mybatis中的事务是jdbc的事务机制,mybatis里面默认是手动提交
*/session.commit();System.out.println("新增之后的主键值为:" + emp.getEmpno());session.close();

3.3 更新员工

编写mapper文件

<update id="update" parameterType="com.gs.entity.Emp">update emp set ename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno} where empno=#{empno}</update>

在测试类编写

public class CURDTest {@Testpublic void testSelect() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();}
}Emp emp = new Emp();emp.setEmpno(7936);emp.setEname("JERRY");emp.setJob("MANAGER");emp.setMgr(7698);emp.setHiredate(new Date(new Date().getTime() + 1000*60*60*24));
emp.setSal(7800.0);emp.setComm(800.0);}int result = session.update("emp.update", emp);System.out.println("影响数据库的条数为:" + result);session.commit();session.close();
}

3.4 删除员工

编写mapper文件

<delete id="delete" parameterType="java.lang.Integer">delete from emp where empno=#{empno}</delete>

在测试类编写

public class CURDTest {@Testpublic void testSelect() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();}
}int result = session.delete("emp.delete", 7935);System.out.println("影响数据库的条数为:" + result);session.commit();}session.close();
}

3.4 根据员工名模糊查询

编写mapper文件

<!--
条件查询:模糊查询
1、#{}占位符,防止sql注入
需要在Java中将传入数据的前后拼接%符号
where ename like #{ename}2、使用字符串拼接函数
where ename like concat('%',#{ename},'%')3、${}拼接符号,实现sql的拼接
where ename like '%${value}%'
注意:${}不是占位符,如果输入参数为简单类型,${}中的内容必须为value-->
<select id="selectByEname1" parameterType="java.lang.String" 
resultType="com.gs.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from empwhere ename like #{ename}</select>

在测试类编写

public class CURDTest {@Testpublic void testSelect() throws IOException {InputStream in = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();}
}String ename = "S";List<Emp> list = session.selectList("emp.selectByEname1", "%"+ename+"%");for (Emp emp : list) {System.out.println(emp);}session.close();
}

4 总结

4.1 parameterType和resultType

  1. parameterType:指定输入参数类型,MyBatis通过OGNL从输入对象中获取参数值设置在Sql中。
  2. resultType:指定输出结果类型,MyBatis将Sql查询结果的一行记录数据映射为resultType指定类型的 对象。

4.2 #{} 和 ${}

  1. #{}:
    1. #{}表示一个占位符号,#{}接收输入参数,类型可以是简单类型、实体类类型、HashMap;
    2. #{}接收简单类型,#{}中可以写成value或其它名称;
    3. #{}接收实体类对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性…的方式获取对象属 性值。
  2. ${}:
    1. 表示一个拼接符号,有 S q l 注入风险,所以不建议使用 {}表示一个拼接符号,有Sql注入风险,所以不建议使用 表示一个拼接符号,有Sql注入风险,所以不建议使用{};
    2. ${}接收输入参数,类型可以是简单类型、实体类类型、HashMap;
    3. 接收简单类型, {}接收简单类型, 接收简单类型,{}中只能写成value;
    4. ${}接收实体类对象值,通过OGNL读取对象中的属性值,通过属性.属性.属性…的方式获取对象属 性值。

4.2 selectOne和selectList

  1. selectOne表示查询出一条记录进行映射; 如果使用selectOne可以实现使用selectList也可以实现(list中只有一个对象)。
  2. selectList表示查询出一个列表(多条记录)进行映射; 如果使用selectList查询多条记录,不能使用selectOne。
  3. 如果使用selectOne报错:org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 4

4.3 MyBatis和Hibernate区别

  1. Hibernate:是一个标准ORM框架(对象关系映射)。 入门门槛较高的,不需要程序写Sql,Sql语句自动生成,对Sql语句进行优化、修改比较困难的; 应用场景:适用与需求变化不多的中小型项目,比如:后台管理系统,erp、crm、oa…;
  2. MyBatis:专注于Sql本身,需要程序员自己编写Sql语句,Sql修改、优化比较方便。 MyBatis是一个不完全的ORM框架,虽然程序员自己写Sql,MyBatis也可以实现映射(输入映射、 输出映射); 应用场景:适用与需求变化较多的项目,比如:互联网项目;

4.4 Mybatis解决JDBC编程的问题

    1. 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问 题。
    2. 解决:在mybatis-config.xml中配置数据链接池,使用连接池管理数据库链接。
  1. Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变Java代码。
    1. 解决:将 Sql语句配置在XXXXmapper.xml文件中与Java代码分离。
  2. 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一 一 对应
    1. 解决:Mybatis自动将Java对象映射至sql语句,通过statement中的parameterType定义输入参数 的类型。
  3. 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成 pojo对象解析比较方便。
    1. 解决:Mybatis自动将sql执行结果映射至Java对象,通过statement中的resultType定义输出结果 的类型

5 Mybatis 开发 方式

5.1 DAO开发

  1. 原始DAO开发方式 : 编写Dao接口和Dao实现类,无非就是Dao实现类里面调用映射文件里面定 义的sql而已。
  2. 原始DAO开发问题 :
    1. Dao接口实现类方法中存在大量模板方法。每次都要创建。
    2. 由于SqlSession方法使用泛型,即使变量类型传入错误,在编 译阶段也不报错
    3. sqlSession的数据库操作方法需要指定statement的id,这里存在硬编码,不利于开发维护。
 public class DeptDaoImpl implements DeptDao {@Overridepublic List<Dept> select() {SqlSession sqlSession = MybatisUtil.getSession();List<Dept> list = sqlSession.selectList("dept.select");sqlSession.close();return list;}@Overridepublic Dept selectById(Integer deptno) {SqlSession sqlSession = MybatisUtil.getSession();Dept dept = sqlSession.selectOne("dept.selectById", deptno);sqlSession.close();return dept;}}

5.2 Mybatis API

  1. SqlSessionFactoryBuilder: SqlSessionFactoryBuilder用于创建SqlSessionFacoty。
  2. SqlSessionFactory: SqlSessionFactory是一个接口,接口中定义了openSession的不同重载方法。
  3. SqlSession: SqlSession是一个面向用户(程序员)的接口,其中提供了很多操作数据库的方法。如: selectOne(返回单个对象)、selectList(返回单个或多个对象)、insert、update、delete。
    1. 但是 SqlSession的实现类不能共享,每次使用都要创建新的。

5.3 Mapper代理方式

  1. 只需要程序员编写Mapper接口(相当于Dao接口),由MyBatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同上边Dao接口实现类方法。
  2. 写Mapper接口遵循开发规范 , MyBatis可以自动生成Mapper接口实现类代理对象。
    1. Mapper.xml文件中的namespace与mapper接口的类路径相同。
    2. Mapper.xml中定义的每个标签的id与Mapper接口方法名相同。
    3. Mapper.xml中定义的每个sql的parameterType的类型与Mapper接口方法的参数类型相同。
    4. Mapper.xml中定义的每个sql的resultType的类型与Mapper接口方法返回值类型相同
  3. 新建一个实体类:
import java.util.Date;/*** Emp实体类
*/public class Emp {private Integer empno;private String ename;private String job;private Integer mgr;private Date hiredate;private Double sal;private Double comm;private Integer deptno;}

创建mapper接口:

package com.gs.mapper;* Mapper接口相当于我们之前写的Dao接口,只是在Mybatis里面我们习惯这么写而已。*/
public interface EmpMapper {List<Emp> select();Emp selectById(Integer empno);void insert(Emp emp);int update(Emp emp);boolean delete(Integer empno);}
1.  批量查询:方法返回值为List类型,表示SqlSession对象将调用selectList()方法。
2. 单条查询:方法返回值为单个实体对象,表示SqlSession对象将调用selectOne()方法。
3.  增删改: 1. 方法返回值为void,表示SqlSession对象中insert,update,delete方法的返回值不做任何处 理。 2. 方法返回值为int类型,表示SqlSession对象中insert,update,delete方法的返回值直接返 回3. 方法返回值为boolean类型,表示根据SqlSession对象中的insert,update,delete方法返回 值(影响数据库的条数)判断操作是否成功,如果影响数据库的条数大于0条,表示成功,否 则表示失败。  

编写mapper文件:

<?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">
<!--namespace:与Mapper接口的全限定名保持一致-->
<mapper namespace="com.gs.mapper.EmpMapper"><!--每个标签id与Mapper接口的方法名称保持一致;parameterType的类型必须与方法的参数类型保持一致;resultType的类型必须与方法的返回值类型保持一致;--><select id="select" resultType="com.gs.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp</select><select id="selectById" parameterType="java.lang.Integer" resultType="com.gs.entity.Emp">select empno,ename,job,hiredate,mgr,sal,comm,deptno from emp where empno=#{empno}</select><insert id="insert" parameterType="com.gs.entity.Emp">insert into emp(ename,job,mgr,hiredate,sal,comm,deptno)values(#{ename},#{job},#{mgr},#{hiredate},#{sal},#{comm},#{deptno})</insert><update id="update" parameterType="com.gs.entity.Emp">update emp setename=#{ename},job=#{job},mgr=#{mgr},hiredate=#{hiredate},sal=#{sal},comm=#{comm},deptno=#{deptno}where empno=#{empno}</update><delete id="delete" parameterType="java.lang.Integer">delete from emp where empno=#{empno}</delete>
</mapper>

在全局配置中加载该mapper文件

<!-- 加载映射文件的位置 --><mappers><mapper resource="mapper/EmpMapper.xml"/></mappers>

编写测试类:

public class MapperTest {private SqlSession sqlSession;private EmpMapper empMapper;@Before  //类加载之前执行的方法注解public void before() {sqlSession = MybatisUtil.getSession();//获取Mapper接口的代理对象empMapper = sqlSession.getMapper(EmpMapper.class);}@After //类加载之结束后执行的方法注解public void after() {sqlSession.commit();sqlSession.close();}@Testpublic void testSelect() {List<Emp> list = empMapper.select();for (Emp emp : list) {System.out.println(emp);}}@Testpublic void testSelectById() {Emp emp = empMapper.selectById(7938);System.out.println(emp);}@Testpublic void testInsert() {Emp emp = new Emp();emp.setEname("小明");emp.setJob("职员");emp.setSal(4500.0);emp.setComm(1000.0);emp.setMgr(1);emp.setHiredate(new Date());empMapper.insert(emp);}@Testpublic void testUpdate() {Emp emp = new Emp();emp.setEmpno(7940);emp.setEname("小李");emp.setJob("秘书");emp.setSal(5300.0);emp.setComm(1300.0);emp.setMgr(1);emp.setHiredate(new Date());int result = empMapper.update(emp);System.out.println("方法的返回值:" + result);}@Testpublic void testDelete() {boolean result = empMapper.delete(7940);System.out.println("方法的返回值:" + result);}
}

Mybatis官方推荐使用mapper代理方式开发mapper接口,程序员不用编写mapper接口实现类,使用 mapper代理方法时,输入参数可以使用pojo包装对象或map对象,保证dao的通用性。

6 Mybatis 全局配置文件 mybatis-config.xml

6.1 配置内容如下

  1. properties(属性)
  2. settings(全局配置参数)
  3. typeAliases(类型别名)
  4. typeHandlers(类型处理器)
  5. objectFactory(对象工厂)
  6. plugins(插件)
  7. environments(环境集合属性对象)
  8. environment(环境子属性对象)
  9. transactionManager(事务管理)
  10. dataSource(数据源)
  11. mappers(映射器)

**上述的配置中各个标签可以不写,但顺序不能错!!! 具体可以参考 ****http://mybatis.org/dtd/mybatis-3-config.dtd ****文件 **

6.2 properties属性

将数据库连接参数单独配置在db.properties文件中,只需要在mybatis-config.xml中加载db.properties的属 性值。在mybatis-config.xml中就不需要对数据库连接参数硬编码。

d**b.properties**文件:

# Oracle相关配置
jdbc.oracle.driver=oracle.jdbc.driver.OracleDriver
jdbc.oracle.url=jdbc:oracle:thin:@localhost:1521:orcl
jdbc.oracle.username=scott
jdbc.oracle.password=tiger
# Mysql相关配置
jdbc.mysql.driver=com.mysql.jdbc.Driver
jdbc.mysql.url=jdbc:mysql://localhost:3306/ssm?
characterEncoding=utf8&useSSL=false
jdbc.mysql.username=root
jdbc.mysql.password=root

mybatis-config.xml中加载:

<!-- 加载外部资源文件 -->
<properties resource="db.properties"><!--properties中还可以配置一些属性--><!--<property name="mysql.url" value="jdbc:mysql://localhost:3306/ssm"/>--><environments default="mysql"><environment id="mysql"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${jdbc.mysql.driver}"/><property name="url" value="${jdbc.mysql.url}"/><property name="username" value="${jdbc.mysql.username}"/><property name="password" value="${jdbc.mysql.password}"/></dataSource></environment></environments>
</properties>

MyBatis将按照下面的顺序来加载属性。

  1. 在properties标签体内定义的属性首先被读取;
  2. 然后会读取properties标签中resource或url加载的属性,它会覆盖已读取的同名属性;
  3. 最后读取parameterType传递的属性,它会覆盖已读取的同名属性;

6.3 settings全局配置参数

  1. 可配置参数如下:
  2. 开启下划线与驼峰命名的转换:
settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>

6.4 typeAliases类型别名

  1. MyBatis默认支持别名

  1. 自定义别名 :
<typeAliases><typeAlias type="com.gs.entity.Dept" alias="dd"/> //alias:自定义的别名</typeAliases>
<typeAliases><package name="com.gs.entity"/>//package:批量设置别名 "com.gs.entity" 该包下的所有类的别名</typeAliases>
  1. 注解起别名 :
//使用注解@Alias("depart") 为类起别名。
@Alias("depart")
public class Dept {//...
}

注解和配置只能使用一种。

6.5 typeHandlers类型处理器

  1. MyBatis支持的类型处理器:

MyBatis中通过typeHandlers完成JDBC类型和Java类型的转换,MyBatis自带的类型处理器基本上满足 日常需求,不需要单独定义。

6.6 mappers映射器

  1. 单个加载映射文件
<mappers><!--<mapper>单个加载映射文件;resource:通过相对路径加载文件(mapper目录);url:通过绝对路径加载文件(文件系统中文件);--><mapper resource="mapper/DeptMapper.xml"/><mapper resource="mapper/EmpMapper.xml"/><!-- 通过类的全名 --><mapper class="com.gs.mapper.EmpMapper"/>
</mappers>

要求:

1. 必须使用mapper代理的开发方式;
2. mapper.xml文件的名称必须与dao接口的名称保持一致;
3. mapper.xml文件必须与dao接口放在同一个目录下;
1.  批量加载映射文件  
  1. 批量加载映射文件 :
<mappers><!--<package>批量加载映射文件
name:存放Mapper接口与mapper.xml文件的包名--><package name="com.gs.mapper"/></mappers>

此种配置使mapper扫描指定包,并在此包下获取所有的接口以及与接口名称相同mapper文件, 并加载;

7 Mybatis mapper配置文件 mapper.xml

mapper.xml映射文件中定义了操作数据库的Sql,每个Sql是一个statement(陈述),映射文件是MyBatis的核 心

7.1 输入映射

  1. resultType输出映射 : 配置输入参数的类型 。
  2. resultType输出映射 :配置输出参数的类型 。
<?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 namespace="com.gs.mapper.UsersMapper"><select id="selectByRealname" parameterType="java.lang.String" resultType="com.gs.entity.Users">select id,username,password,realname from users where realname like concat('%',#{realname},'%')</select></mapper>

7.2 通过实体类或pojo类型传递查询条件

  1. 自定义创建的类,或者复合类。
  2. 在mapper接口实现方法类:
List<Users> selectByPage(Page page);
// 符合类
List<Users> selectByRealnameAndPage(UsersQuery usersQuery);
// 多个参数输入
Users login(@Param("uname") String username, @Param("pwd") String password);
// map集合类
List<Users> selectUseMap(Map<String, Object> map);
  1. 编写mapper.xml文件
<select id="selectByPage" parameterType="com.gs.entity.Page" resultType="com.gs.entity.Users">select id,username,password,realname from users order by id limit #{offset}, #{pageSize}
</select><select id="selectByRealnameAndPage" parameterType="com.gs.entity.UsersQuery" resultType="com.gs.entity.Users">select id,username,password,realname from userswhere realname like concat('%',#{users.realname},'%')order by id limit #{page.offset}, #{page.pageSize}
</select><select id="selectUseMap" parameterType="java.util.HashMap" resultType="com.gs.entity.Users">select id,username,password,realname from userswhere realname like concat('%',#{name},'%')order by id limit #{begin}, #{size}</select><select id="login" parameterType="java.util.HashMap" resultType="com.gs.entity.Users">select id,username,password,realname from userswhere username=#{uname} and password=#{pwd}</select>

7.3 resultMap 与 resultType

  • resultType: 自动映射。
  • resultMap: 手动映射。1.可以实现将查询结果映射为复合型的实体类,比如在查询结果映射对象中包括实体类和 list实现一对一查询和一对多查询。 2. 果SQL查询字段名和实体类的属性名不一致,可以通过resultMap将字段名和属性名作一个对应 关系,resultMap实质上还会将查询结果映射到实体类对象中。
    • id: 唯一标识,名称; type: 手动映射的java类型;
    • 子标签 配置数据库表中的主键和实体类中属性的对应关系;
    • 子标签 配置数据库表中的普通字段和实体类中属性的对应关系;
      • property:实体类中的成员变量名;
      • column:结果集中的字段名称;
      • javaType:实体类成员变量的类型,由mybaits自动识别,可不配置;
      • jdbcType:表字段的类型,由mybaits自动识别,可不配置;
      • typeHandler:自定义类型处理器,用的相对比较少;
<resultMap id="selectResultMap" type="com.gs.entity.Person"><id property="id" column="id"/><result property="personName" column="person_name"/><result property="personAge" column="person_age"/><result property="personAddress" column="person_address"/></resultMap><select id="select" resultMap="selectResultMap">select id,person_name,person_age,person_address from person</select>

7.4 动态SQL

简单来说。就是对sql语句添加动态的条件。

  1. if标签
 <select id="selectUseIf" parameterType="com.gs.entity.Emp" resultType="com.gs.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from empwhere<!--注意:判断条件中使用的变量为实体类或输入参数的属性空字符串的判断仅能使用在字符串类型的属性中--><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></select>
  1. where标签
 <select id="selectUseWhere" parameterType="com.gs.entity.Emp"  resultType="com.gs.entity.Emp">select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp<where><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></where></select>
  1. set标签
    1. 当set标签内所有的条件都不成立,不会拼接set关键字,只要有一个条件成立就会在SQL语句中拼
      接set关键字。注意:如果set包含的内容为空SQL语句会出错。
    2. set标签会自动剔除条件末尾的任何不相关的逗号。
<update id="updateUseSet" parameterType="com.gs.entity.Emp">update emp<set><if test="ename != null">ename=#{ename},</if><if test="hiredate != null">hiredate=#{hiredate},</if><if test="sal != null">sal=#{sal},</if><if test="comm != null">comm=#{comm},</if><if test="deptno != null">deptno=#{deptno},</if></set>where empno=#{empno}</update>
  1. foreach标签 : 向SQL传递数组或list,MyBatis使用foreach解析。
    1. collection: 遍历的数组或集合对象名称。
      1. SQL只接收一个数组参数,这时SQL解析参数的名称MyBatis固定为array。
      2. SQL只接收一个List参数,这时SQL解析参数的名称MyBatis固定为list。
      3. 如果是通过一个实体类或自定义类型的属性传递到SQL的数组或List集合,则参数的名称为实 体类或自定义类型中的属性名。
    2. index: 为数组的下标。
    3. item: 每次遍历生成的对象。
    4. open: 开始遍历时拼接的串。
    5. close: 结束遍历时拼接的串。
    6. separator: 遍历的两个对象中需要拼接的串。
<delete id="deleteUseForeach" parameterType="java.lang.Integer"><!--delete from emp where empno in (1,2,3,4)-->delete from emp where empno in<foreach collection="array" open="(" close=")" separator="," item="id">#{id}</foreach></delete><insert id="insertUseForeach" parameterType="com.gs.entity.Emp">insert into emp(ename,job,mgr,hiredate,sal,comm,deptno) values<foreach collection="list" separator="," item="emp">(#{emp.ename},#{emp.job},#{emp.mgr},#{emp.hiredate},#{emp.sal},# {emp.comm},#{emp.deptno})</foreach></insert>
  1. choose标签 : choose标签、when标签、otherwise标签的组合,类似于if-else-if判断。
<select id="">select...<choose><when test=""></when><when test=""></when><otherwise></otherwise></choose></select>
  1. SQL片段 :将重复的sql语句封装起来给其他语句使用。片段, 通过 签就可以引用SQL片段
<sql id="feildSql">empno,ename,job,mgr,hiredate,sal,comm,deptno</sql><include><sql id="whereSql"><if test="ename != null and ename != ''">ename like concat('%',#{ename},'%')</if><if test="sal != null">and sal=#{sal}</if><if test="deptno != null">and deptno=#{deptno}</if></sql><select id="selectUseSql" parameterType="com.gs.entity.Emp" resultType="com.gs.entity.Emp">select<include refid="feildSql"></include>from emp<where><include refid="whereSql"></include></where></select>

7.5 Map输入和输出类型

  1. Mapper接口:
public interface DeptMapper {//查询List<Map<String, Object>> queryAllDept();//插入int insertDept(Map<String, Object> map);
}
  1. Mapper文件:
<!--
查询,输出参数是Map
Mybatis会把查询结果给我们封装成List<Map>
因为一行数据就是一个Map-->
<select id="queryAllDept" resultType="hashmap">select * from dept
</select>
<!--插入,输入参数是Map-->
<!--输入参数是hashmap,那么#{map中的key}-->
<insert id="insertDept" parameterType="hashmap">insert into dept values (#{id},#{name},#{address})
</insert>

相关文章:

Mybatis 复习

1 什么是MyBatis MyBatis是一个优秀的持久层框架&#xff0c;它对JDBC操作数据库的过程进行封装&#xff0c;使开发者只需要关注 SQL 本身&#xff0c;而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、 结果集检索等JDBC繁杂的过程代码 。…...

BurpSuite安装教程(详细!!附带下载链接)

声明 学习内容来自 B 站UP主泷羽sec&#xff0c;如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识&#xff0c;以下网站只涉及学习内容&#xff0c;其他的都与本人无关&#xff0c;切莫逾越法律红线&#xff0c;否则后果自负。 ✍&#x1f3fb;作者简介&#xff1a;致…...

Istio_05_Istio架构

Istio_05_Istio架构 ArchitectureControl PlanePilotCitadelGalley Data PlaneSidecarIstio-proxyPilot-agentMetadta Exchange Ambient Architecture 如: Istio的架构(控制面、数据面) Gateway: Istio数据面的出/入口网关 Gateway分为: Ingress-gateway、Egress-gateway外部访…...

R语言结构方程模型(SEM)在生态学领域中的应用

目录 专题一、R/Rstudio简介及入门 专题二、结构方程模型&#xff08;SEM&#xff09;介绍 专题三&#xff1a;R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 专题四&#xff1a;SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 专题五&#xff1…...

node.js基础学习-fs模块-文件操作(六)

一、前言 fs模块是 Node.js 内置的文件系统&#xff08;File System&#xff09;模块&#xff0c;它提供了一系列用于与文件系统进行交互的方法。通过fs模块&#xff0c;可以对文件或目录进行读取、写入、删除、重命名、查询状态等操作&#xff0c;这使得 Node.js 能够很好地处…...

EXCEL截取某一列从第一个字符开始到特定字符结束的字符串到新的一列

使用EXCEL中的公式进行特定截取 假设列A是一组产品的编码&#xff0c;我们需要的数据是“-”之前的字段。 我们需要在B1单元格输入公式“LEFT(A1,SEARCH("-",A1)-1)”然后选中B1至B4单元格&#xff0c;按“CTRLD”向下填充&#xff0c;就可以得出其它几行“-”之前的…...

JVM的垃圾回收算法有哪些

标记清除算法 标记清除算法&#xff0c;是将垃圾回收分为2个阶段&#xff0c;分别是标记和清除 根据可达性分析算法得出的垃圾进行标记对这些标记为可回收的内容进行垃圾回收 优点:标记和清除速度较快缺点:碎片化较为严重&#xff0c;内存不连贯的 标记整理算法 优缺点同标记…...

看华为,引入IPD的正确路径

目录 前言 引发重视 作者简介 前言 华为将 IPD 的引入过程归结为三步&#xff1a; 先僵化、后优化、再固化。 如果只是单纯模仿&#xff0c;在不清楚底层逻辑的情况下&#xff0c; 就开始走先僵化的流程&#xff0c;去搞削足适履式的引入。 开始执行后&#xff0c;你就…...

2024142读书笔记|《别无归处是归处》——一壶酒,一竿身,世上如侬有几人

2024142读书笔记|《别无归处是归处》——一壶酒&#xff0c;一竿身&#xff0c;世上如侬有几人 《别无归处是归处&#xff1a;吴镇的“渔父”画题&#xff08;文人画的真性&#xff09;》作者朱良志。诗词与古画并存的一本书&#xff0c;古画是比较偏复古黯淡微黄及墨色的&…...

think php处理 异步 url 请求 记录

1、需求 某网站 需要 AI生成音乐&#xff0c;生成mp3文件的时候需要等待&#xff0c;需要程序中实时监听mp3文件是否生成 2、用的开发框架 为php 3、文件结构 配置路由设置 Route::group(/music, function () {Route::post(/musicLyrics, AiMusic/musicLyrics);//Ai生成歌词流式…...

PostgreSQL详细安装教程

#安装PostgreSQL的yum仓库 sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm#安装PostgreSQL 15版本 sudo yum install -y postgresql15-server#初始化数据库&#xff08;若要自定义数据库存储目录…...

电子电气架构 --- 车载网关GW连接外部IP Tester

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

开发一套ERP 第八弹 RUst 插入数据

更全面的报错,方便检查错误在哪里,现代高级语言越来越智能 还是得看下原文档怎么操作的 src 目录为crate 的根目录 想在crate 中模块相互引入需要在 main 中声明,各个模块,然后才能在各个模块中相互引入和使用 原始工程引入,避免直接使用 lib.rs 回合cargo 中的一些 工程管理出…...

RFdiffusion Diffuser类解读

Diffuser 类是一个封装类,调用EuclideanDiffuser和IGSO3类,用于执行扩散模型的核心功能,主要针对分子或蛋白质结构的旋转(SO(3) 群上的扩散)和位移(欧几里得空间中的扩散)。 源代码: class Diffuser:# wrapper for yielding diffused coordinatesdef __init__(self,T…...

【pdf密码】为什么我的PDF文件不能复制文字?

大家现在接触PDF文件越来越多&#xff0c;有的时候在网上下载的PDF文件打开之后&#xff0c;发现选中文字之后无法复制。甚至其他功能也都无法使用&#xff0c;这是怎么回事&#xff1f;该怎么办&#xff1f; 当我们发现文件打开之后&#xff0c;编辑功能无法使用&#xff0c;很…...

C#学写了一个程序记录日志的方法(Log类)

1.错误和警告信息单独生产文本进行记录&#xff1b; 2.日志到一定内存阈值可以打包压缩&#xff0c;单独存储起来&#xff0c;修改字段MaxLogFileSizeForCompress的值即可&#xff1b; 3.Log类调用举例&#xff1a;Log.Txt(JB.信息,“日志记录内容”,"通道1"); usi…...

Android Framework禁止弹出当前VOLTE不可用的提示窗口

文章目录 VoLTE简介VoLTE 的优势 当前VOLTE不可用的弹窗弹窗代码定位屏蔽弹出窗口 VoLTE简介 VoLTE&#xff08;Voice over LTE&#xff09;是一种基于4G LTE网络的语音通话技术。它允许用户在4G网络上进行高质量的语音通话和视频通话&#xff0c;而不需要回落到2G或3G网络。V…...

Maven Surefire 插件简介

Maven Surefire 插件是 Maven 构建系统中的一个关键组件&#xff0c;专门用于在构建生命周期中执行单元测试。 它通常与 Maven 构建生命周期的测试阶段绑定&#xff0c;确保所有单元测试在项目编译后和打包前被执行。 最新版本 Maven Surefire 插件的最新版本为 3.5.2。 使…...

vue3-新增API组件

shallowRef 创建一个响应式数据&#xff0c;但只对顶层属性进行响应式处理,只跟踪引用值的变化&#xff0c;不关心值内部的属性变化 import {shallowRef} from "vue" import UserInfo from "/components/UserInfo.vue";let name shallowRef("vue&quo…...

Linux随记(十三)

一、jstack随记 运行cmd cd C:\icp-agent\jdk_min\bin 执行 jstack PID > thread_dump.txt &#xff08;查看PID&#xff1a;tasklist |findstr javaw 查看第二列&#xff09; thread_dump.txt 取给研发二、让普通用户test&#xff0c;有权限使用docker指令 1、 查看当前用…...

AI数据分析工具(一)

Looker Studio&#xff08;谷歌&#xff09;-免费 优点 免费使用&#xff1a;对于中小型企业和个人用户来说&#xff0c;没有任何费用压力&#xff0c;可以免费享受到数据可视化和报表创建的功能。与Google服务集成&#xff1a;特别适合使用Google产品生态的企业&#xff0c;…...

dhcp服务

安装dhcp-libs和dhcp-common软件包是配置DHCP服务器的前提&#xff0c;但仅仅安装这两个软件包并不能直接开启DHCP服务器。您还需要进行以下步骤来完整配置和启动DHCP服务器&#xff1a; 安装DHCP服务器软件包&#xff1a; 除了dhcp-libs和dhcp-common&#xff0c;您还需要安装…...

RSA算法和AES算法,哪种更安全

目录 一、RSA (非对称加密算法) 二、AES (对称加密算法) 三、对比总结 四、更安全的选择 五、结合使用&#xff1a;RSA AES RSA 和 AES 是两种不同类型的加密算法&#xff0c;适用于不同的场景&#xff0c;因此它们的安全性不能直接比较&#xff0c;而是取决于具体的应用…...

反向代理模块开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…...

(微信小程序)基于Spring Boot的校园失物招领平台的设计与实现(vue3+uniapp+mysql)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

1-7 GD32函数指针应用

前言&#xff1a; 本博客仅在应用函数指针与回调函数相关的知识&#xff0c;通过实践巩固所学知识&#xff0c;也是对相关知识点的回顾。 函数指针与回调函数&#xff1a;1-6 GD32函数指针与回调函数-CSDN博客 目录 前言&#xff1a; 1.0 程序架构思想 2.0 构建串口结构体 …...

前端js面试知识点思维导图(脑图)

如果看着不清晰可以去https://download.csdn.net/download/m0_73761441/90058523访问下载&#xff0c;无需积分 使用百度脑图制作&#xff0c;可以一键导入下面的文本生成自己的脑图 js相关面试题、知识点 数据类型 1. 数据类型分类&#xff1f;分别包含&#xff…...

使用 F5 TTS 文字转音频

F5 TTS 支持 ZeroShot 音频克隆&#xff0c;只有将需要音频传给模型&#xff0c;模型既可以生成以对应声音生成的音频&#xff0c;F5 最强大的地方就是可以使用定制的人声。F5 使用了 DIT 架构进行训练&#xff0c;结构如下&#xff1a; 本地使用 F5 TTS F5 使用很简单&#x…...

【笔记】自动驾驶预测与决策规划_Part8_数据驱动的规划方法

文章目录 0. 前言1.生成模型1.1 Diffusion-ES1. Diffusion-ES算法介绍2. Diffusion-ES算法具体流程Diffusion Model 是什么&#xff1f;Diffusion-ES: Evolutionary StrategiesDiffusion-ES MethodDiffusion-ES Mapping Language instructions to reward functions with LLM pr…...

多视图几何中向量叉乘的矩阵转换 Matrix Transformation for Cross Product in MVG

Title: 多视图几何中向量叉乘的矩阵转换 Matrix Transformation for Cross Product in MVG 文章目录 I. 向量叉乘的矩阵转换恒等式II. 符号计算 Maxima 程序推导III. 推论和关联公式的说明1. 推论2. 应用于对极几何中基本矩阵推导3. 应用于基本矩阵与单应矩阵关系4. 与刚体运动…...

面向多用户场景的恢复机制驱动的无线组密钥生成协议

中文标题&#xff1a;面向多用户场景的恢复机制驱动的无线组密钥生成协议 英文标题&#xff1a;A Recovery Mechanism-driven Wireless Group Key Generation Protocol for Multi-User Scenarios 作者信息&#xff1a; Huaicong Zhang, Yawen Huang, Jiabao Yu, Boqian Liu, …...

ROS2教程 - 2 环境安装

更好的阅读体验&#xff1a;https://www.foooor.com 2 环境安装 下面以 ROS2 的 humble 版本为例&#xff0c;介绍 ROS2 的安装。 ROS1 只能在 ubuntu 系统上安装&#xff0c;ROS2全面支持三种平台&#xff1a;Ubuntu、MAC OS X、Windows10&#xff0c;下面在 Ubuntu22.04 …...

力扣200 岛屿数量 Java版本

文章目录 题目描述代码 题目描述 给你一个由 ‘1’&#xff08;陆地&#xff09;和 ‘0’&#xff08;水&#xff09;组成的的二维网格&#xff0c;请你计算网格中岛屿的数量。 岛屿总是被水包围&#xff0c;并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。 …...

每日速记10道java面试题03

其他资料 每日速记10道java面试题01-CSDN博客 每日速记10道java面试题02-CSDN博客 目录 一、你使用过java的反射机制吗&#xff1f;如何应用反射&#xff1f; 二、什么是泛型&#xff1f;泛型的作用是什么&#xff1f; 三、java的泛型擦除是什么&#xff1f; 四、Java 中…...

力扣刷题TOP101:6.BM7 链表中环的入口结点

目录&#xff1a; 目的 思路 复杂度 记忆秘诀 python代码 目的 {1,2},{3,4,5}, 3 是环入口。 思路 这个任务是找到带环链表的环入口。可以看作是上一题龟兔赛跑&#xff08;Floyd 判圈算法&#xff09;的延续版&#xff1a;乌龟愤愤不平地举报兔子跑得太快&#xff0c;偷偷…...

智慧防汛平台在城市生命线安全建设中的应用

随着城市化进程的加快&#xff0c;城市基础设施的复杂性和互联性不断增强&#xff0c;城市生命线的安全管理面临前所未有的挑战。智慧防汛平台作为城市生命线安全建设的重要组成部分&#xff0c;通过现代信息技术提升城市防汛应急管理的智能化水平&#xff0c;保障城市安全。 …...

高德应用OceanBase云数据库的升级选型与迁移干货

业务背景 高德&#xff0c;DAU已在亿级&#xff0c;时时刻刻都持续不断地产生着庞大的数据。随着数据量的迅猛增长&#xff0c;对现有的业务数据存储能力构成日益严峻的挑战。 以我所在部门中的某一大型服务为例&#xff0c;其存储在XDB中的数据量往往达到数百TB之巨&#xf…...

Flink cdc同步增量数据timestamp字段相差八小时(分析|解决)不是粘贴复制的!

问题 我使用flink cdc同步mysql到mysql遇到了timestamp字段缺少八小时的问题。很少无语&#xff0c;flink ,cdc,debezium时区都设置了&#xff0c;没有任何效果&#xff01; 分析 问题出现在mysql binlog身上&#xff01;&#xff01;&#xff01; 因为默认mysql会使用UTC来…...

用shell脚本写一个通用的监听程序异常并重启脚本

进来服务器的程序php-fpm时常在并发下时常挂掉&#xff0c;而且时常在凌晨2点以后&#xff0c;通过排查是因为php配置需要调整并发&#xff0c;同时&#xff0c;为了不影响我休息&#xff08;以前老师说&#xff1a;能用机器和程序解决问题的坚决不用人去操作&#xff0c;这样才…...

使用 Go 语言中的 Context 取消协程执行

使用 Go 语言中的 Context 取消协程执行 在 Go 语言中&#xff0c;协程&#xff08;goroutine&#xff09;是一种轻量级的线程&#xff0c;非常适合处理并发任务。然而&#xff0c;如何优雅地取消正在运行的协程是一个常见的问题。本文将通过一个具体的例子来展示如何使用 con…...

使用经典的Java,还是拥抱新兴的Rust?

在当代互联网时代的企业级开发中&#xff0c;技术栈的选择往往牵动着每个团队的神经。随着Rust语言的崛起&#xff0c;许多开发团队开始重新思考&#xff1a;是继续坚持使用经典的Java&#xff0c;还是拥抱新兴的Rust&#xff1f;这个问题背后&#xff0c;折射出的是对技术演进…...

《算法导论》英文版前言To the teacher第3段研习录:题海战术有没有?

【英文版】 We have included 957 exercises and 158 problems. Each section ends with exercises, and each chapter ends with problems. The exercises are generally short questions that test basic mastery of the material. Some are simple self-check thought exer…...

XELA - uSkin 三轴触觉传感器:为机器人赋予敏锐触感

XELA Robotics 的 uSkin 触觉传感器以其创新性在机器人技术中备受关注。它凭借高密度设计和三轴力测量能力&#xff0c;大幅提升了机器人的触觉感知能力&#xff0c;这种技术不但增强了机器人的智能化和柔性&#xff0c;还为不同行业的应用创造了广泛的可能性。其中在机器人灵巧…...

k8s常用命令总结

以下是 Kubernetes 所有常用命令的详细总结&#xff0c;涵盖了 kubectl 的各个方面&#xff0c;包括基本操作、资源管理、调试、监控等。每个命令都附有简要说明和示例。 1. 基本命令 查看 Kubernetes 版本 kubectl version 查看集群信息 kubectl cluster-info 查看当前上…...

即时通讯| IM+RTC在AI技术加持下的社交体验

即时通讯作为互联网的重要应用之一&#xff0c;见证了中国互联网30年发展的辉煌历程。 它从最初的文字交流&#xff0c;发展到如今的语音、视频通话&#xff0c;甚至是虚拟现实社交&#xff0c;已经渗透到生活的社交、娱乐、商务等方方面面&#xff0c;成为现代社会不可或缺的一…...

评估人工智能生成答案准确性

目录 评估人工智能生成答案准确性 评估人工智能生成答案准确性 在评估人工智能(AI)系统生成的答案准确性时,我们主要关注两个方面:事实相似性和语义相似性。这两个方面的加权平均分数被用来衡量系统回答的准确性。 事实相似性: 事实相似性通过F1分数来计算。F1分数是精确…...

scala的守卫语句格式

import scala.io.StdIn object test49{//从控制台读入一个数字a,使用&#xff08;StdIn.readInt&#xff09;//如果a>0并且a<3,打印[0-3]//如果a>4并且a<8,打印[4-8]//否则:打印未匹配 // def main(args: Array[String]): Unit { // val aStdIn.readInt()//等…...

结构型模式-组合模式

组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过将对象组合成树形结构来表示“部分-整体”的层次结构&#xff0c;从而使客户端对单个对象和组合对象的使用具有一致性。 适用场景 需要表示对象的层次结构&#xff1a;如文件系统、组…...

(超详细图文)PLSQL Developer 配置连接远程 Oracle 服务

1、下载配置文件 &#xff08;超详细图文详情&#xff09;Navicat 配置连接 Oracle-CSDN博客 将下载的文件解压到单独文件夹&#xff0c;如&#xff1a;D:\App\App_Java\Oracle\instantclient-basic-windows.x64-19.25.0.0.0dbru 2、配置 打开 PLSQL Developer&#xff0c;登…...

【AI系统】昇腾 AI 架构介绍

昇腾 AI 架构介绍 昇腾计算的基础软硬件是产业的核⼼&#xff0c;也是 AI 计算能⼒的来源。华为&#xff0c;作为昇腾计算产业⽣态的⼀员&#xff0c;是基础软硬件系统的核⼼贡献者。昇腾计算软硬件包括硬件系统、基础软件和应⽤使能等。 而本书介绍的 AI 系统整体架构&#…...