MyBatis 一文基础总结

news2024/12/23 2:04:00

1266315d6edc77fab66d2142faa6726e.jpeg

MyBatis 一文基础总结
老师的随堂上课笔记, 供参考~
1.框架概述

1.1 软件开发常用结构
1.1.1三层架构
三层的处理请求的交互:

用户---> 界面层--->业务逻辑层--->数据访问层--->DB 数据库

1.1.2 常用框架
常见的 J2EE 中开发框架:

MyBatis 框架

MyBatis 是一个优秀的基于 java 的持久层框架,内部封装了 jdbc,开发者只需要关注 sql 语句本身,而不需要处理加载驱动、创建连接、创建 statement、关闭连接,资源等繁杂的过程。MyBatis 通过 xml 或注解两种方式将要执行的各种 sql 语句配置起来,并通过 java 对象和 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

Spring 框架:

Spring 框架为了解决软件开发的复杂性而创建的。Spring 使用的是基本的 JavaBean 来完成以前,非常复杂的企业级开发。Spring 解决了业务对象,功能模块之间的耦合,不仅在 javase,web 中使用,大部分 Java 应用都可以从 Spring 中受益。Spring 是一个轻量级控制反转(IoC)和面向切面(AOP)的容器。

SpringMVC 框架:

Spring MVC 属于 SpringFrameWork 3.0 版本加入的一个模块,为 Spring 框架提供了构建 Web 应用程序的能力。现在可以 Spring 框架提供的 SpringMVC 模块实现 web 应用开发,在 web 项目中可以无缝使用 Spring 和 Spring MVC 框架。

1.2 框架
1.2.1 框架定义
框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种认为,框架是可被应用开发者定制的应用骨架、模板。在框架基础上加入你要完成的功能。框架安全的,可复用的,不断升级的软件。

2.MyBatis框架入门
2.1MyBatis能做什么
一个框架,早期叫做ibatis, 代码在github

mybatis是 MyBatis SQL Mapper Framework for Java (sql映射框架)
1)sql mapper :sql映射 可以把数据库表中的一行数据 映射为 一个java对象。 一行数据可以看做是一个java对象。操作这个对象,就相当于操作表中的数据

2) Data Access Objects(DAOs) : 数据访问 , 对数据库执行增删改查。

mybatis提供了哪些功能:

提供了创建Connection ,Statement, ResultSet的能力 ,不用开发人员创建这些对象了
提供了执行sql语句的能力, 不用你执行sql
提供了循环sql, 把sql的结果转为java对象, List集合的能力
while (rs.next()) {
Student stu = new Student();
stu.setId(rs.getInt("id"));
stu.setName(rs.getString("name"));
stu.setAge(rs.getInt("age"));
//从数据库取出数据转为 Student 对象,封装到 List 集合
stuList.add(stu);
}
4.关闭资源

提供了关闭资源的能力,不用你关闭Connection, Statement, ResultSet

开发人员做的是: 提供sql语句 最后是: 开发人员提供sql语句--mybatis处理sql---开发人员得到List集合或java对象(表中的数据)

总结: mybatis是一个sql映射框架,提供的数据库的操作能力。增强的JDBC, 使用mybatis让开发人员集中精神写sql就可以了,不必关心Connection,Statement,ResultSet 的创建,销毁,sql的执行。

2.2MyBaits的使用步骤
2.2.1 搭建MyBatis开发环境
1.下载MyBatis

https://github.com/mybatis/mybatis-3/releases
2.把MyBatis的jar包放入maven的本地仓库

2.2.2Mybatis的使用步骤
1.新建的student表

2.加入maven的mybatis坐标, mysql驱动的坐标

<!-- 加入mybatis的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.3</version>
</dependency>

<!-- mysql的依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
3.创建实体类,student--保存表中的一行数据的

4.创建持久层的dao接口,定义操作数据库的方法

5.创建一个mybatis使用的配置文件叫做sql映射文件:写sql语句的。一般一个表一个sql映射文件。这个文件是xml文件。 6.创建mybatis的主配置文件:一个项目就一个主配置文件。主配置文件提供了数据库的连接信息和sql映射文件的位置信息

7.创建使用mybatis类,通过mybatis访问数据库

1、创建maven工程
2、创建Student表
3、创建Student类
4、创建接口StudentDao
5、创建StudentDao接口的映射文件(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">
<!--一般使用接口的全限定类名-->
<mapper namespace="net.zhenghou.dao.StudentDao">

<!--
select表示查询
id:你要执行的sql语法的唯一标识,mybatis会使用这个值来找到要执行的的sql语句
可以自定义,但是要求你使用接口中方法名称
-->
<select id="selectStudents" resultType="net.zhenghou.domain.Student">
select * from student
</select>
<!-- #{属性名},这个必须和类的属性一致-->
<insert id="insertStudent">
insert into student values(#{id},#{name},#{birthday},#{address})

</insert>
<update id="updateStudent">
update student set name=#{name},birthday=#{birthday},address=#{address} where id=#{id}
</update>
<delete id="deleteStudent">
delete from student where id=#{id}
</delete>
</mapper>
<!--

<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
1. 指定约束文件
2.约束文件的作用:
检查当前文件中出现的标签,属性必须符合mybatis的要求
3.mapper是当前文件的根标签,必须的
namespace:叫做命名空间,唯一值,,可以自定义一个字符串,
一般我们要求是接口的全限定类名
4. 在当前文件中,可以使用特定的标签,标识数据库的特定操作
select的标签 :表示的是查询,selec语句
update标签:表示更新数据库的操作
insert标签:表示插入
delete标签,表示删除

-->


6.创建主配置文件
7.创建sqlSession执行sql语句
2.2.3 插入操作
1. StudentDao 的接口中加入一个抽象方法
2. 在StudentDao对应的映射文件StudentDao.xml中 插入操作
2.2.4 配置日志功能


2.2.5修改操作
2.2.6删除操作
2.3MyBatis对象分析
2.3.1Resources类
Resources 类,顾名思义就是资源,用于读取资源文件。其有很多方法通过加载并解析资源文件,返回不同类型的 IO 流对象。

2.3.2 SqlSessionFactoryBuilder 类
SqlSessionFactory 的 创 建 , 需 要 使 用 SqlSessionFactoryBuilder 对 象 的 build() 方 法 。 由 于

SqlSessionFactoryBuilder 对象在创建完工厂对象后,就完成了其历史使命,即可被销毁。所以,一般会将

该 SqlSessionFactoryBuilder 对象创建为一个方法内的局部对象,方法结束,对象销毁。

2.3.3 SqlSessionFactory 接口
SqlSessionFactory 接口对象是一个重量级对象(系统开销大的对象),是线程安全的,所以一个应用

只需要一个该对象即可。创建 SqlSession 需要使用 SqlSessionFactory 接口的的 openSession()方法。

➢ openSession(true):创建一个有自动提交功能的 SqlSession

➢ openSession(false):创建一个非自动提交功能的 SqlSession,需手动提交

➢ openSession():同 openSession(false)

2.3.4 SqlSession接口
SqlSession 接口对象用于执行持久化操作。一个 SqlSession 对应着一次数据库会话,一次会话以

SqlSession 对象的创建开始,以 SqlSession 对象的关闭结束。

SqlSession 接口对象是线程不安全的,所以每次数据库会话结束前,需要马上调用其 close()方法,将

其关闭。再次需要会话,再次创建。 SqlSession 在方法内部创建,使用完毕后关闭。

2.3.5 创建工具类
public class MyBatisUtils {
private static SqlSessionFactory factory;
static{
try {
String config="mybatis.xml";
InputStream is = Resources.getResourceAsStream(config);
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}

//获取sqlSession的方法
public static SqlSession getSqlSession(){
SqlSession sqlSession=null;
if(factory !=null){
sqlSession= factory.openSession();//非自动提交
}
return sqlSession;
}



}



3 MyBatis使用Dao 开发方式


3.1Dao开发
3.1.1传统Dao开发方式的分析
SqlSession的API方法定位到映射文件mapper中相应的sql语句,从而对数据库进行操作。

所以把这种由动态代理方式实现。

Mapper动态代理方式无需程序员实现Dao接口,接口是由MyBatis结合映射文件自动生成的动态代理实现的。

3.2 MyBatis框架Dao代理
3.2.1Dao代理实现CRUD
步骤:
去掉Dao接口的实现类

getMapper获取代理对象
接口 接口对象=sqlSession.getMapper(接口的class对象)
3.2.2原理

org.apache.ibatis.binding.MapperProxy@4d95d2a2
MapperProxy类的定义:

public class MapperProxy<T> implements InvocationHandler, Serializable {
......

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
....
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
}
重点的方法:

mapperMethod.execute(this.sqlSession, args);
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
Object param;
switch(this.command.getType()) {
case INSERT:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
break;
case UPDATE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
break;
case DELETE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
break;
case SELECT:
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
} else if (this.method.returnsMap()) {
result = this.executeForMap(sqlSession, args);
} else if (this.method.returnsCursor()) {
result = this.executeForCursor(sqlSession, args);
} else {
param = this.method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(this.command.getName(), param);
if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + this.command.getName());
}

if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
} else {
return result;
}
}

3.3 深入理解参数
1.parameterType
接口中方法参数的类型,类型是全限定类名。它是可选的。

因为mybatis可以推断出具体传入语句的参数,默认值为unset(不设置)

<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from student where id=#{id}
</delete>
2.MyBatis传递参数
从java代码中把参数传递到mapper.xml文件

一个简单参数:
Dao接口中方法的参数只有一个简单类型(java基本类型+String),占位符#{任意字符},和方法的参数名无关

接口中的方法:

int deleteStudent(int id);
mapper文件

<delete id="deleteStudent" parameterType="java.lang.Integer">
delete from student where id=#{studentId}
</delete>
#{studentId}:studentId是自定义的变量名称,和方法参数名无关

多个参数--使用@param(重点)
当dao接口方法有多个参数,需要通过名称是使用参数。在方法的形参前面加入

@Param("自定义参数名")
在mapper文件使用#{自定义参数名}

接口

List<Student> selectMultiParam(@Param("studentName") String name, @Param("studentAddress") String address );
mapper文件

<select id="selectMultiParam" resultType="net.zhenghou.domain.Student">
select * from student where name=#{studentName} or address=#{studentAddress}
</select>
测试

@Test
public void testSelectMultiParam(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectMultiParam("丁凯", "南京市");
studentList.forEach(student-> System.out.println(student));
}

多个参数--使用对象(重点)
使用java对象传递参数,java的属性值就是sql需要的参数值。每一个属性就是一个参数。

#{property}
创建 QueryParam对象

public class QueryParam {
private String queryName;
private String queryAddress;

public QueryParam() {
}

public String getQueryName() {
return queryName;
}

public void setQueryName(String queryName) {
this.queryName = queryName;
}

public String getQueryAddress() {
return queryAddress;
}

public void setQueryAddress(String queryAddress) {
this.queryAddress = queryAddress;
}
}

接口

List<Student> selectMultiObject(QueryParam queryParam);
mapper文件


<select id="selectMultiObject" resultType="net.zhenghou.domain.Student">
select * from student where name=#{queryName} or address=#{queryAddress}
</select>
测试

@Test
public void testSelectMultiObject(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
QueryParam qp=new QueryParam();
qp.setQueryAddress("南京市");
qp.setQueryName("毕浪");
studentDao.selectMultiObject(qp);
}
多个参数--按位置(了解)
参数位置从0开始,引用参数语法#{arg位置}。第一个参数是#{arg0 } 第二个参数是#{arg1}

接口方法

List<Student> selectByNameAndAddess(String name,String address);
mapper文件

<select id="selectByNameAndAddess" resultType="net.zhenghou.domain.Student">
select * from student where name=#{arg0} or address=#{arg1}
</select>
测试方法:

@Test
public void testSelectByNameAndAddress(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectByNameAndAddess("毕浪", "南京市");
studentList.forEach(student -> System.out.println(studentList));
}

多个参数-使用Map(了解)
Map集合可以存储多个值,使用Map向mapper文件一次传入多个参数。Map集合使用String的key,Object类型的值存储参数

#{key} 来引用
接口方法

List<Student> selectMultiMap(Map<String,Object> map);
mapper文件

<select id="selectMultiMap" resultType="net.zhenghou.domain.Student">
select * from student where name=#{myname} or address=#{myaddress}
</select>
测试方法

@Test
public void testSelectMap(){
Map<String,Object> map=new HashMap<String,Object>();
map.put("myname","唐雨鑫");
map.put("myaddress","无锡市");
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectMultiMap(map);
studentList.forEach(student -> System.out.println(studentList));
}
3.4#和$ 的区别
#:占位符。告诉mybatis使用实际的参数值代替。并使用PreparedStatement对象执行sql语句,#{...}代替了sql语句中?。这样做更安全,也是首选做法。

:字符串的替换。告诉mybatis使用包含的“字符串"替换所在位置。使用Statement把sql语句和${}的内容连接起来。主要用在替换表名,列名,不同列排序等操作。

3.5 封装mybatis输出结果
1.resultType
执行sql得到的ResultSet转换的类型

a. 简单类型

接口

int countStudent();
mapper文件

<!-- resultType="java.lang.Integer"-->
<select id="countStudent" resultType="int">
select count(*) from student
</select>
测试

@Test
public void testReturnInt(){
SqlSession sqlSession=MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
int count = studentDao.countStudent();
System.out.println("学生的总数是:"+count);
}
b.对象类型

mybatis框架的处理:使用构造方法创建对象。调用setXXX给属性赋值

Class.forName(全限定类名): 类的Class对象

类名 对象= class对象.newInstance()

Student对象

sql语句列 java对象方法 调用对应set方法
id setId(rs.getInt("id")) id列--->setId()
name setName(rs.getString("name")) name--->setName()
birthday setBirthday(rs.getString("birthday")) birthday-->setBirthday()
address setAddress(rs.getString("address")) address-->setAddress()
注意点:

dao接口方法返回的是集合类型,需要指定集合中的类型,而不是集合本身的类型。

c.Map

sql的查询结果作为Map的key和value,推荐使用Map<Object,Object>

注意点: Map作为接口返回值,sql语句的查询结果最多只能有一条记录,大于一条记录就会报错

接口

Map<Object,Object> selectReturnMap(int id);
mapper文件

<select id="selectReturnMap" resultType="java.util.HashMap">
select name,birthday,address from student where id=#{studentId}

</select>
测试

@Test
public void testReturnMap() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Map<Object, Object> returnMap = studentDao.selectReturnMap(4);
System.out.println("查询的结果是:"+returnMap);
}
2.resultMap
可以自定义sql的结果和java对象的映射关系,更灵活的把列值赋值给指定的属性

通常用于列名和java对象属性名不一样的情况。

使用方式:

1.先定义resultMap,指定列名和属性的对应关系

2.在select标签中把resultType替换为resultMap



接口

List<Student> selectUseResultMap(QueryParam queryParam);
mapper文件

<!-- 创建resultMap
id:自定义的唯一名称,在select使用
type:期望转换为java对象的全限定类名或者别名

主键字段使用id column:列名property:属性名
-->
<resultMap id="studentMap" type="net.zhenghou.domain.Student">

<!-- 主键字段使用id -->
<id column="id" property="id"/>
<!-- 非主键字段使用result-->
<result column="name" property="name"/>
<result column="address" property="address" />
<result column="birthday" property="birthday" />

</resultMap>

<!-- resultMap: resultMap标签中的id属性值 -->
<select id="selectUseResultMap" resultMap="studentMap">
select id,name,birthday,address from student where name= #{queryName} or address=#{queryAddress}
</select>
测试

@Test
public void testSelectUseResultMap(){
QueryParam qp=new QueryParam();
qp.setQueryName("李四");
qp.setQueryAddress("无锡市");
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectUseResultMap(qp);
studentList.forEach(student -> System.out.println(student));
}
3. 实体类属性名和列名不同的处理
1.给列名取别名和resultType

接口

List<PrimaryStudent> selectUseFieldAlias(QueryParam queryParam);
mapper文件

<select id="selectUseFieldAlias" resultType="net.zhenghou.domain.PrimaryStudent">
select id as stuId,name stuName,birthday stuBirthday,address stuAddress from student where name= #{queryName} or address=#{queryAddress}
</select>
测试

@Test
public void testSelectUseFieldAlias(){
QueryParam qp=new QueryParam();
qp.setQueryName("李四");
qp.setQueryAddress("无锡市");
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<PrimaryStudent> primaryStudents = studentDao.selectUseFieldAlias(qp);
primaryStudents.forEach(stu-> System.out.println(stu));
}
2.使用resultMap

接口方法

List<PrimaryStudent> selectUsedDiffResultMap(QueryParam queryParam);
mapper文件

<resultMap id="primaryStudentMap" type="net.zhenghou.domain.PrimaryStudent">
<!-- 主键字段 id-->
<id column="id" property="stuId"/>
<!-- 非主键字段 result-->
<result column="name" property="stuName"/>
<result column="address" property="stuAddress"/>
<result column="birthday" property="stuBirthday"/>

</resultMap>
<select id="selectUsedDiffResultMap" resultMap="primaryStudentMap">
select id,name,birthday,address from student where name= #{queryName} or address=#{queryAddress}
</select>
测试方法

@Test
public void testSelectDiffResultMap(){
QueryParam qp=new QueryParam();
qp.setQueryName("李四");
qp.setQueryAddress("无锡市");
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<PrimaryStudent> studentList = studentDao.selectUsedDiffResultMap(qp);
studentList.forEach(stu-> System.out.println(stu));
}
3.6模糊查询 like
模糊查询的实现方式一种有两种:

1.java代码中给查询的数据加上”%“

2.在mapper文件的sql语句的条件中加上“%”

接口方法

List<Student> selectLikeFirst(String name);
List<Student> selectLikeSecond(String name);
mapper文件

<select id="selectLikeFirst" resultType="net.zhenghou.domain.Student">
select id,name,birthday,address from student where name like #{studentName}
</select>

<!-- like name #{}"%"-->
<select id="selectLikeSecond" resultType="net.zhenghou.domain.Student">
select id,name,birthday,address from student where name like #{name} "%"
</select>
测试方法

@Test
public void testSelectLikeJava(){
String name="丁%";
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectLikeFirst(name);
studentList.forEach(stu-> System.out.println(stu));
}
@Test
public void testSelectLikeMapper(){
String name="丁";
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectLikeSecond(name);
studentList.forEach(stu-> System.out.println(stu));
}
4.MyBatis--动态SQL
动态SQL。通过mybatis提供的各种标签对条件判断以实现动态拼接sql语句。

常用的动态标签:

<if/> <where> < choose/> <foreach>
在mapper的动态SQL中如果出现大于号,小于号,大于等于号,小于等于号 等,最好将其转换为实体符号,否则xml可能会出现解析出错问题

特别是对于小于号(<),在xml中是绝对不能出现的。否则解析mapper文件会出错

符号 含义 实体符号
> 大于 >;
< 小于 < ;
>= 大于等于 > ;=
<= 小于等于 < ;=


4.1动态SQL if标签
语法

<if test="条件">sql语句的部分</if>//当test的值为true,会将包含的sql的片段拼接到其所在的SQL语句中
接口方法

public interface StudentDao {
List<Student> selectStudentIf(Student student);
}
mapper文件

<select id="selectStudentIf" resultType="net.zhenghou.domain.Student">
select id,name,birthday,address from student where 1=1
<if test=" name !=null and name !=''">
and name=#{name}
</if>
<if test="id>10">
and id >#{id}
</if>

</select>
测试

@Test
public void testSelectIf(){
Student student=new Student();
student.setName("");
student.setId(87);
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectStudentIf(student);
studentList.forEach(stu-> System.out.println(stu));
}


4.2动态SQL where标签
语法

<where> 其它动态sqln </where> //如果有查询条件,会自动添加where语句;没有查询时候不会添加where子句
4.3 动态SQL foreach标签
foreach标签用于实现对于数组与集合的遍历。对其使用,需要注意

collection 表示要遍历的集合类型 list array等
open close separator 为对遍历内容的SQL拼接
语法:

<foreach collection="集合类型" open=”开始的字符" close="结束的字符" item=“集合中的成员" separator="集合成员之间的分隔符">


</foreach>


4.4 动态SQL--代码片段
sql标签用于定义SQL的片段,以便其它SQL标签复用。如果其它的标签需要用到该SQL的片段

<sql> </sql> 复用的sql
<include/> //引用sql的片段


<sql id="studentSql">
select id,name,birthday,address from student
</sql>

<select id="selectStudentSqlFragment" resultType="net.zhenghou.domain.Student">
-- 引用sql片段
<include refid="studentSql"/>
<if test="list !=null and list.size()>0">
where id in
-- collectionL类型 list array open:开始的字符 close 结束的字符
<foreach collection="list" open="(" close=")" item="stuObject" separator=",">
#{stuObject.id}
</foreach>
</if>
</select>
总结:

可以将一些重复性的SQL语句进行抽取,以达到复用的效果

小结:

动态sql主要对映射文件配置:

<select>:查询
id:和接口中的方法保持一致
resultType:
resultMap:
<insert>插入
id:和接口中的方法保持一致
<update> 修改
id:和接口中的方法保持一致
<delete>删除
<where>:where条件
<if>:判断
<foreach>: 循环
<sql> :sql片段的抽取
id;
<include>
refid=“sql的id保持一致"



5.MyBatis的配置文件
5.1 主配置文件
5.5.1特点:
1.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">
2.根标签
<configuration>
3.主要包含内容
定义别名

数据源

mapper文件



5.5.2 dataSource标签
<dataSource type="POOLED">
1.连接的类型
POOLED:使用连接池的数据源

UNPOOLED:不使用连接池的数据源

JNDI:采用JNDI实现的数据源
2.dataSource的配置

<dataSource type="POOLED">
<!-- 连接数据库的四个要素 -->
<!-- 连接数据库驱动的名 -->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<!-- 连接数据库的url的字符串 -->
<property name="url" value="jdbc:mysql://localhost:3306/chenxp"/>
<!-- 访问数据库的用户名-->
<property name="username" value="root"/>
<!-- 访问数据库的密码-->
<property name="password" value="root"/>
</dataSource>


5.5.3事务
<transactionManager type="JDBC"/> //指定mybatis使用的事务管理器,mybatis支持两种事务类型JDBC和MANAGED
MANAGED:由容器来管理事务的整个生命周期(Spring 容器)

JDBC默认是手动提交,如需自动提交 openSession(true)

5.5.4 使用数据库属性配置文件中读取这些数据
mybatis主配置文件需要从这个属性配置文件

步骤:

1.在resurces目录创建jdbc.properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/chenxp
jdbc.username=root
jdbc.password=root
2.在主配置文件,文件configuration开始位置加入

<properties resource="jdbc.properties"/>
3.使用key指定值

<dataSource type="POOLED">
<!-- 连接数据库驱动的名 -->
<property name="driver" value="${jdbc.driver}"/>
<!-- 连接数据库的url的字符串 -->
<property name="url" value="${jdbc.url}"/>
<!-- 访问数据库的用户名-->
<property name="username" value="${jdbc.username"/>
<!-- 访问数据库的密码-->
<property name="username" value="${jdbc.password}"/>
</dataSource>
5.5.5 typeAliases(类型别名)
mybatis支持默认别名,但我们也可以采用自定义别名方式来开发,主要使用在<select resultType="别名">

定义settings标签的后面

<typeAliases>
<typeAliase type=”“ alias=” "/>

</typeAliases>
6.分页插件--PageHelper
Mybatis分页插件:

1.在企业级开发中,目前使用mybatis是不带分页的。如果想实现分页,我们可以手动编写limit语句来实现分页(mysql).不同的数据库实现分页的sql语句有所不同,所以手写分页成本脚本。所以此时可以借助分页插件来实现分页功能

2.PageHelper插件:第三方分页插件。将复杂的分页操作进行封装,从而让分页功能变得非常简单

pageHelper的使用:

1.jar包拷贝上本地仓库

2.pom.xml中加入依赖

<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.10</version>
</dependency>
3 .在mybatis.xml中

<!-- 指定插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
4.测试

@Test
public void testPageHelper(){
//设置分页参数
PageHelper.startPage(3,2);
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
List<Student> studentList = studentDao.selectStudents();
studentList.forEach(stu-> System.out.println(stu));
PageInfo<Student> pageInfo=new PageInfo<Student>(studentList);
System.out.println("总条数:"+pageInfo.getTotal());
System.out.println("总页数:"+pageInfo.getPages());
System.out.println("当前页:"+pageInfo.getPageNum());
System.out.println("每页显示的长度:"+pageInfo.getPageSize());
System.out.println("是否第一页"+pageInfo.isIsFirstPage());
System.out.println("是否是最后一页:"+pageInfo.isIsLastPage());
}


分页插件总结:

' 分页助手相关的API

PageHelper;分页助手功能类

PageInfo:分页相关参数功能类
new PageInfo(输入当页的数据list)

页助手相关的API
PageHelper.startPage() 设置分页参数
PageInfo对象.getTotal() 获取总条数
PageInfo对象.getPageSize() 获取每页显示的条数
PageInfo对象.getPrePage() 获取上一页
PageInfo对象.getNextPage() 获取下一页
PageInfo对象.isIsFirstPage() 获取是否是第一页
PageInfo对象.isIslastPage() 获取是否是最后一页
7.MyBatis的多表操作
7.1多表的模型
一对一:

在任意一方建立外键,关联对方的主键

一对多:

在任意一方建立外键,关联对方的主键

多对多:借助中间表,中间表至少两个字段,分别关联的两张表的主键

7.2一对一的模型:
1.人和身份证:一个人只有一个身份证。

2.代码实现

步骤一:数据库sql语句的准备

create table person(
id int primary key auto_increment,
name varchar(20),
age int);

insert into person values(null,'汤雨轩',22);
insert into person values(null,'周雨童',22);
insert into person values(null,'李阳',22);

create table card(
id int primary key auto_increment,
number varchar(30),
pid int,
CONSTRAINT person_card_pid FOREIGN KEY (pid) REFERENCES person(id));
insert into card values(null,'1233',1);
insert into card values(null,'5633',2);
insert into card values(null,'4356',3);

步骤二:实体类

public class Person {
private Integer id;//主键id
private String name;//人的姓名
private Integer age;//人的年龄


public class Card {
private Integer id;
private String number;//身份证号
private Person p;//所属人的对象
...........
}
步骤三:

接口方法


public interface PersonCardDao {
List<Card> queryAll();
}

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">
<!--一般使用接口的全限定类名-->
<mapper namespace="net.zhenghou.dao.PersonCardDao">

<!-- 配置字段和实体对象属性的映射关系-->
<resultMap id="oneToOne" type="card">
<!-- 主键 id-->
<id column="cid" property="id"/>
<!-- 非主键 reuslt-->
<result column="number" property="number" />
<!-- association 配置被包含对象的映射关系-->
<association property="p" javaType="person">
<id column="pid" property="id"/>
<result column="name" property="name" />
<result column="age" property="age" />
</association>

</resultMap>
<select id="queryAll" resultMap="oneToOne">
SELECT c.id cid,c.number,c.pid,p.id,p.name,p.age
from card c,person p
where c.pid=p.id
</select>

</mapper>

步骤四:主配置文件中加入mapper的路径

<mapper resource="net/zhenghou/dao/PersonCardDao.xml"/>
步骤五: 测试

@Test
public void testOneToOne(){
SqlSession sqlSession= MyBatisUtils.getSqlSession();
PersonCardDao personCardDao = sqlSession.getMapper(PersonCardDao.class);
List<Card> cards = personCardDao.queryAll();
cards.forEach(card-> System.out.println(card));
}
练习题:

查询一个订单,同时查询出该订单所属的用户(一个订单只属于一个用户)
订单order(id,ordertime,total,uid)
用户user(id,username,password,birthday)

create table user(id int primary key auto_increment,
username varchar(30),
password varchar(30),
birthday varchar(20));

create table orders(id int primary key auto_increment,
ordertime varchar(255),
total double,
uid int,
CONSTRAINT user_orders_id FOREIGN KEY(uid) REFERENCES user(id));

insert into user values(null,'闫云光','123','2000-12-12');
insert into user values(null,'谢志青','123','1999-12-12');
insert into user values(null,'李明耀','123','1998-12-12');

insert into orders values(null,'2022-5-15',2000,1);
insert into orders values(null,'2022-5-15',3000,2);
insert into orders values(null,'2022-5-15',2000,3);

7.3一对多的模型:
1.班级和学生,一个班级有多个学生

2.代码实现

步骤一:数据库的sql语句


create table classes(
id int primary key auto_increment,
name varchar(20));

create table student(
id int primary key auto_increment,
name varchar(30),
age int,
cid int,
CONSTRAINT class_student_id FOREIGN KEY(cid) REFERENCES classes(id));

insert into classes values(null,'开发08');
insert into classes values(null,'开发09');


insert into student values(null,'喻宏波',22,1);
insert into student values(null,'毕浪',22,1);
insert into student values(null,'张三',22,2);
insert into student values(null,'李四',22,2);

步骤二:实体类

public class Student {
private Integer id;
private String name;
private Integer age;
public Student() {
}
........
}

public class Classes {
// 主键id
private Integer id;
// 班级名称
private String name;
// 班级中所有学生对象
private List<Student> students;

public Classes() {
}

步骤三:接口方法


public interface ClassStudent {
List<Classes> queryAll();
}

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">
<!--一般使用接口的全限定类名-->
<mapper namespace="net.zhenghou.dao.ClassStudent">
<resultMap id="oneToMany" type="classes">
<id column="cid" property="id" />
<result column="cname" property="name" />
<!--
collection:配置包含的集合对象的映射关系
property: 被包含对象的变量明
ofType: 被包含对象的实际数据类型
-->
<collection property="students" ofType="student">
<id column="sid" property="id" />
<result column="sname" property="name"/>
<result column="sage" property="age"/>
</collection>
</resultMap>
<select id="queryAll" resultMap="oneToMany">
select c.id cid,c.name cname,s.id sid,s.name sname,s.age sage
from classes c,student s
where c.id=s.cid
</select>
</mapper>
步骤四:测试


@Test
public void testOneToMany(){
SqlSession sqlSession= MyBatisUtils.getSqlSession();
ClassStudent classStudentDao = sqlSession.getMapper(ClassStudent.class);
List<Classes> classes = classStudentDao.queryAll();
classes.forEach(c-> System.out.println(c));
}
练习题:

用户表和订单表的关系:一个用户有多个订单
7.4 多对多的关系
1.学生和课程 :一个学生可以选择多门课程,一个课程也可以被多个学生所选择

2.代码实现

步骤一:数据库sql语句

create table course(
id int primary key auto_increment,
name varchar(20)
);

create table student_course(
id int primary key auto_increment,
sid int,
cid int,
CONSTRAINT sc_student_fk FOREIGN KEY(sid) REFERENCES student(id),
CONSTRAINT sc_course_fk FOREIGN KEY(cid) REFERENCES classes(id)
);

insert into course values(null,"java基础");
insert into course values(null,"javaweb");
insert into student_course values(null,1,1);
insert into student_course values(null,1,2);

insert into student_course values(null,2,1);
insert into student_course values(null,2,2);

步骤二:实体类

需改学生表
public class Student {
private Integer id;
private String name;
private Integer age;
private List<Course> course;//学生所轩的课程集合
...
}
public class Course {
private Integer id;//主键id
private String name;//课程名
....
}
步骤三:

接口方法


public interface CourseStudent {
List<Student> queryAll();
}

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">
<!--一般使用接口的全限定类名-->
<mapper namespace="net.zhenghou.dao.CourseStudent">

<resultMap id="manyToMany" type="student">
<id column="id" property="id"/>
<result column="sname" property="name"/>
<result column="sage" property="age" />
<collection property="course" ofType="course">
<id column="cid" property="id"/>
<result column="cname" property="name" />
</collection>
</resultMap>
<select id="queryAll" resultMap="manyToMany">

</select>
</mapper>

步骤四:

主配置文件

<mapper resource="net/zhenghou/dao/CourseStudent.xml"/>
步骤五:测试

@Test
public void manyToMany(){
SqlSession sqlSession= MyBatisUtils.getSqlSession();
CourseStudent courseStudentDao = sqlSession.getMapper(CourseStudent.class);
List<Student> students = courseStudentDao.queryAll();
students.forEach(c-> System.out.println(c));
}
练习题:

用户表和角色表的关系:一个用户有多个角色,一个角色被多个用户使用
user_role(id,user_id,role_id);
role(id,rolename)


7.5多表模型的总结
<resultMap id="resultMap的id">
//主键
<id column="数据库中表的列名" property="实体类中的属性名">
//非主键
<result column="数据库中表的列名" property="实体类中的属性名">

//一对一的关系
<association property="被包含的对象的变量名" javaType="被包含对象的数据类型" >
<id column="数据库中表的列名" property="实体类中的属性名">
//非主键
<result column="数据库中表的列名" property="实体类中的属性名">
</association>

//一对多,多对多的关系
<collection propety="被包含集合对象的变量名" ofType="集合中保存对象的数据类型">
<id column="数据库中表的列名" property="实体类中的属性名">
//非主键
<result column="数据库中表的列名" property="实体类中的属性名">
</collection>

</resultMap>

<select id="" resultMap="resultMap的id">
</select>

8.MyBatis注解开发-单表操作
使用注解开发,可以减少Mapper映射文件。

8.1Mybatis常用的注解
注解 含义
@Select 实现查询
@Insert 实现新增
@Delete 实现删除
@Update 实现修改
@Reuslt 实现结果集封装
@Reuslts 可以与result一起使用,封装多个结果集
@One 实现一对一结果集封装
@Many 实现一对多结果集封装
8.2MyBatis注解的CRUD
步骤一:创建Mapper接口

public interface StudentMapper {
//查询全部
@Select("SELECT * FROM student")
List<Student> queryAll();
// 新增操作
@Insert("INSERT INTO student( name,age,sex)VALUES (#{name},#{age},#{sex})")
Integer insert(Student student);
//修改操作
@Update("UPDATE student SET name=#{name},age=#{age},sex=#{sex} WHERE id=#{id}")
Integer update(Student student);
//删除操作
@Delete("DELETE FROM student WHERE id=#{id}")
Integer delete(Integer id);

}

步骤二:主配置文件mybatis.xml中增加

!-- sql mapper(sql映射文件)的位置-->
<mappers>
<!-- 扫描使用注解类-->
<mapper class="net.zhenghou.mapper.StudentMapper"></mapper>

<!-- 指定扫描使用注解的类所在的包-->
<!-- <package name="net.zhenghou.mapper"/>-->
</mappers>
步骤三:测试类

public class TestStudent {
@Test
public void insert(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student=new Student();
student.setName("tom");
student.setAge(21);
student.setSex("male");
mapper.insert(student);
sqlSession.commit();
sqlSession.close();
}
@Test
public void update() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
student.setId(2);
student.setName("jerry");
student.setAge(20);
student.setSex("male");
mapper.update(student);
sqlSession.commit();
sqlSession.close();
}
@Test
public void select() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
List<Student> studentList = mapper.queryAll();
for (Student student : studentList) {
System.out.println(student);
}
sqlSession.close();
}
@Test
public void delete() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
int id=2;
mapper.delete(2);
sqlSession.commit();
sqlSession.close();
}

}



8.3注解开发总结
注解可以简化开发操作,省略映射文件的编写

常用注解:
@Select ("查询的sql语句")

@Insert ("新增的sql语句")

@Update ("修改的sql语句")

@Delete("删除的sql语句")

配置映射关系:
<!-- 扫描使用注解类-->
<mapper class="net.zhenghou.mapper.StudentMapper"></mapper>
//或者
<!-- 指定扫描使用注解的类所在的包-->
<package name="net.zhenghou.mapper"/>


9.MyBatis注解开发-多表操作
9.1MyBatis注解实现复杂映射开发
使用@Results @Reuslt @One @Many注解组合完成复杂关系的配置

注解 说明
@Results 代替的是标签<resultMap>,这个注解中也可以使用单个@Result注解,也可以使用多个@Result集合,使用格式:
@Results({@Result(),@Result(),.......})或者@Results(@Result())
@Result 代替<id>标签和<result>标签
@Result中属性介绍:
column :数据库的列名
property:属性名
one:需要使用@One注解(@Result(one=@One)()))
many: 需要使用@Many注解(@Result(many=@Many)())
注解 含义
@One(一对一) 代替了<assocation>标签,是多表查询的关键,在注解中用来指定子查询的返回单一对象。
@One注解属性介绍:
select:指定用来多表查询的sqlmapper
使用格式:
@Result(column="",property="",one=@One(select=""))
@Many(一对多) 代替了<collection>标签,是多表查询的关键,在注解中用来指定子查询返回对象的集合。
使用格式:@Result(column="",property="",many=@Many(select=""))
9.2一对一查询
9.2.1步骤


public interface CardMpper {
//查询全部
@Select("select * from card")
@Results(
{
@Result(column="id",property = "id"),
@Result(column="number",property = "number"),
@Result(
property = "p",//被包含对象的变量名
javaType = Person.class,//被包含对象的实际数据类型
column="pid",//根据查询出的card表中pid字段来查询
//one=@One() 一对一固定写法
//select属性,指定调用哪个接口中的哪个方法
one = @One(select="net.zhenghou.mapper.PersonMapper.selectById")

)
}
)
List<Card> selectAll();
}


9.3一对多查询
9.3.1步骤
1.查询一个班级,同时查询出该班级对应的学生信息

2.对应的查询语句

select * from classes
select * from student where cid=#{id}
3.创建接口

public interface Student1Mapper {
//根据cid班级号查询student表
@Select("select * from student where cid=#{cid}")
List<Student> selectByCid(Integer cid);
}



public interface ClassMapper {
//查询所有的班级信息
@Select("select * from classes")
@Results(
{

@Result(
property = "students",//被包含的对象的变量名
javaType = List.class,//被包含对象的实际数据类型
column="id",//根据查询的classes表中的id字段来查询
//student many=@Many一对多固定的写法
// select属性表示指定调用哪个接口中的哪个方法
many = @Many(select = "net.zhenghou.mapper.Student1Mapper.selectByCid")
)
}

)
List<Classes> selectAll();
}
4.测试


@Test
public void selectAllClasses(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
ClassMapper mapper = sqlSession.getMapper(ClassMapper.class);
List<Classes> classes = mapper.selectAll();
classes.forEach(c-> System.out.println(c));
sqlSession.close();
}








9.4多对多查询
9.4.1步骤
1.查询学生以及所对应的课程信息

2.对应的sql语句

select distinct s.id,s.name,s.age
from student s,student_course sc
where s.id=sc.sid;


select c.id,c.name
from course c,student_course sc
where c.id=sc.id and sc.sid=#{sid}
3.mapper接口


public interface CourseMapper {
//根据学生的id,查询所选的课程
@Select("select c.id,c.name from course c,student_course sc where c.id=sc.id and sc.sid=#{id}")
List<Course> selectById(Integer id);
}



public interface Student1Mapper {
//根据cid班级号查询student表
@Select("select * from student where cid=#{cid}")
List<Student> selectByCid(Integer cid);
@Select("select distinct s.id,s.name,s.age from student s,student_course sc where s.id=sc.sid")
@Results({
@Result(column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(column = "age",property = "age"),
@Result(
property = "course",
javaType = List.class,
column = "id",
many=@Many(select="net.zhenghou.mapper.CourseMapper.selectById")
)
})

List<Student> selectByCourse();
}
4.测试

@Test
public void selectAllStudentCourse(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
Student1Mapper mapper = sqlSession.getMapper(Student1Mapper.class);
List<Student> studentList = mapper.selectByCourse();
studentList.forEach(c-> System.out.println(c));
sqlSession.close();
}
9.4.2多对多总结

参考一:对多总结

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

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

相关文章

adworld-web-inget-20221226

inget 题目来源: 宜兴网信办 题目描述: 无 题目场景: http://61.147.171.105:51222 http://61.147.171.105:51222/?id1%27%20%20or%2011%20– Please enter ID,and Try to bypass nice : congratulations Flag Is : cyberpeace{3df1eecfb5f794d6a94eba429f7e2846} ┌…

【NI Multisim 14.0编辑环境——菜单栏】

目录 序言 一、菜单栏 &#x1f349;1.文件 &#x1f349;2.编辑 &#x1f349;3.视图 &#x1f349; 4.绘制 &#x1f349;5.MCU&#xff08;微控制器&#xff09;菜单 &#x1f349; 6.仿真 &#x1f349; 7.转移 &#x1f349; 8.工具 &#x1f349; 9.报告 &…

录屏有声音吗?电脑如何录屏有声音?图文教程来了!

无论是学习、办公还是娱乐&#xff0c;都需要屏幕录制。许多人在录制视频后发现视频没有发出声音。录屏有声音吗&#xff1f;电脑如何录屏有声音&#xff1f;一个相对简单的方法是在使用电脑的屏幕录制功能时检查是否打开录制屏幕的声音。此外&#xff0c;如果您担心每次都需要…

这应该是全网最全的MySQL数据库的常用命令了吧

目录 前言 数据库的创建 数据表的操作 表数据的增删查改 分组与函数查询 分组与函数查询 运算符&#xff1a;数学运算符 连接查询 前言 今天给大家点来MySQL数据库的常用命令总结&#xff0c;这应该是全网最详细&#xff0c;最实用的数据库命令总结了&#xff0c;因为命…

addr2line

1、符号表 1.1什么是符号表 符号表是内存地址与函数名、文件名、行号的映射表。符号表元素如下所示&#xff1a; <起始地址> <结束地址> <函数> [<文件名:行号>] 1.2为什么要配置符号表 为了能快速并准确地定位引擎发生Crash的代码位置 举个例子…

【UE4 第一人称射击游戏】16-重新装弹

上一篇&#xff1a; 【UE4 第一人称射击游戏】15-修复蹲伏和冲刺同时执行的bug 本章效果&#xff1a; 步骤&#xff1a; 1.打开“Weapon_Base”&#xff0c;添加两个整数类型变量&#xff0c;分别命名为“MaxAmmo”和“ClipSize”&#xff0c;表示最大载弹量和每次重新装弹的…

MATLAB多项式符号运算

符号计算是指在运算时&#xff0c;无须事先对变量进行赋值&#xff0c;而是将所有得到的结果以标准的符 号形式表示出来。符号计算是以符号对象和符号表达式作为运算对象的表达形式&#xff0c;最终给出 的是解析解;在运算过程中不会受到计算误差累积问题的影响&#xff0c;其计…

信息安全编码标准:使用SAST实施安全编码实践

信息安全编码标准:使用SAST实施安全编码实践 当开发团队使用信息安全编码标准来开发软件时&#xff0c;通常希望更少的安全Bug和更好的代码质量&#xff0c;从而给用户带来健壮性更好的产品。在本篇文章中&#xff0c;我们将介绍信息安全编码标准的基础知识、最佳实践、如何以…

【swaggo】swaggo使用详解

一、swagger简介 swagger是一套基于OpenAPI规范构建的开源工具&#xff0c;使用RestApi。swagger-ui 呈现出来的是一份可交互式的API文档&#xff0c;可以直接在文档页面尝试API的调用。     gin-swagger 是基于注释生成 API 文档&#xff0c;项目地址:https://github.com/…

vulfocus复现:log4j2-rce-2021-12-09

文章目录一、漏洞影响二、复现过程一、漏洞影响 Apache Log4j 是一个基于Java的日志记录工具。经过多年的开发迭代&#xff0c;Log4j 1.x的维护已经变得非常困难&#xff0c;因为它需要与非常旧的 Java 版本兼容&#xff0c;所以于 2015 年 8 月正式升级为Log4j2。黑客可以恶意…

【C++】堆与二叉树(非常详细,附带堆排哦)

之前学习了很多的数据结构 有顺序表&#xff0c;堆&#xff0c;栈... 今天学习一种新的逻辑结构二叉树&#xff0c;他的物理结构是堆 让我们先简单回顾一下堆吧堆的简单介绍和一些简单功能的实现 1. 二叉树 其实堆就是一种特殊的数组&#xff0c;他的逻辑结构是二叉树 &#…

汽车OTA概述

文章目录 前言一、软件更新二、ECU刷写包复用 1.引入库2.读入数据总结前言 掌握OTA&#xff08;Over-The-Air&#xff0c;无线技术&#xff09;&#xff0c;汽车领域与IT领域正在技术融合&#xff01; 技术更新&#xff0c;也增加了车载应用场景&#xff0c;软件更新、实时诊…

内存管理的关键技术——反向映射机制

Cheetah&#xff0c;曾为U-boot社区和Linux内核社区提交过若干补丁&#xff0c;主要从事Linux相关系统软件开发工作&#xff0c;负责Soc芯片BringUp及系统软件开发&#xff0c;喜欢阅读内核源代码&#xff0c;在不断的学习和工作中深入理解内存管理&#xff0c;进程调度&#x…

大数据技术——Flume实战案例

实战案例目录1. 复制和多路复用1.1 案例需求1.2 需求分析1.3 实现操作2. 负载均衡和故障转移2.1 案例需求2.2 需求分析2.3 实现操作3. 聚合操作3.1 案例需求3.2 需求分析3.3 实现操作1. 复制和多路复用 1.1 案例需求 使用 Flume-1 监控文件变动&#xff0c;Flume-1 将变动内容…

图文详解二维差分

目录 前言 一、 二维差分的定义 二、二维差分的使用 三、计算二维差分 四、ACWing 798. 差分矩阵 前言 一维二维前缀和详解 图文详解一维差分 一、 二维差分的定义 对于一个给定的二维数组 arr&#xff0c;它的二维差分数组 d 中 d[i][j] 可以用如下公式计算&#xff1a;…

命令执行-无字母数字webshell

命令执行-无字母数字webshell 我们看如下代码&#xff1a; <?php if(!preg_match(/[a-z0-9]/is,$_GET[shell])) {eval($_GET[shell]); }在命令执行中&#xff0c;我们经常会碰到过滤了字母和数字的情况&#xff0c;那如何才能绕过呢&#xff1f; 我的想法&#xff1a;通…

【数据结构】ArrayList的简单使用

文章目录ArrayList一些ArrayList常用的方法杨辉三角打扑克时的洗牌与摸牌ArrayList 上一次我们自己模拟实现了一下数据结构中的顺序表&#xff0c;当然在我们日常使用时不需要每次使用都自己模拟实现一遍&#xff0c;Java中提供了ArrayList类&#xff0c;我们直接导包就可以使…

如何使用 Delphi / Lazarus / C++ Builder 从 FastReport VCL 创建 Code 11 条码?

Fastreport是目前世界上主流的图表控件&#xff0c;具有超高性价比&#xff0c;以更具成本优势的价格&#xff0c;便能提供功能齐全的报表解决方案&#xff0c;连续三年蝉联全球文档创建组件和库的“ Top 50 Publishers”奖。 FastReport.VCL官方版下载https://www.evget.com/…

黑客动态播报 | 这种勒索方式,让付赎金毫无用处

入侵→加密→要赎金 黑客凭这套商业模式横行多年 受害者之所以前赴后继付赎金 是因为他们相信 给钱就能如愿拿到密钥 尽快恢复业务 可有的时候 自系统被加密的那一刻起 数据就拿不回来了 今年10月,网上出现了一种名为Cryptonite的开源勒索软件包。它使用Python编码,利…

SpringBoot 整合 Shiro 实现动态权限加载更新+ Session 共享 + 单点登录

一.说明 二.项目环境 二.编写项目基础类 三.编写Shiro核心类 四.实现权限控制 五.POSTMAN测试 六.项目源码 一.说明 Shiro是一个安全框架,项目中主要用它做认证,授权,加密,以及用户的会话管理,虽然Shiro没有SpringSecurity功能更丰富,但是它轻量,简单,在项目中通常业务…