MyBatis 操作数据库(入门)

一:MyBatis概念

(1)MyBatis

💗MyBatis是一款优秀的持久层框架,用于简化JDBC的开发

(2)持久层

1.持久层

💜持久层:持久化操作的层,通常指数据访问层(dao),是用来操作数据库的

2.持久层的规范

①包规范:一般取名叫mapper


②接口规范:XxxMapper

(3)MyBatis的开发方式

💗①注解

(目录三)


💗②XML

(目录四)

二:MyBatis入门

(1)准备工作

1.核心步骤

💗创建springboot工程,并导入mybatis的起步依赖、mysql的驱动包

2.创建工程并导入依赖

🌟步骤:File➜New Project➜Spring Initializr➜按照下面的选,然后一路next即可


(2)数据准备

1.在数据库创建用户表

①数据以及SQL代码

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`username` VARCHAR ( 127 ) NOT NULL,
`password` VARCHAR ( 127 ) NOT NULL,
`age` TINYINT ( 4 ) NOT NULL,
`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
`phone` VARCHAR ( 15 ) DEFAULT NULL,
`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

②在Navicat中创建数据表

2.创建对应的实体类

①先创建一个model包,里面用来放实体类,然后创建对应的实体类UserInfo


②在UserInfo中完善代码

(注意:实体类的属性名与表中的字段名需要⼀⼀对应)

package com.hlizoo.demo.model;
import lombok.Data;
import java.util.Date;

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

(3)数据库配置文件

1.相关的配置文件和配置项

💗Mybatis中要连接数据库,需要数据库相关参数配置


①URL

②登录名

③密码

④MySQL驱动类


🌟关于MySQL驱动类的注意事项:

(1)如果使用MySQL是5.x之前版本则MySQL驱动类使用的是"com.mysql.jdbc.Driver"

(2)如果使用MySQL是5.x之后版本则MySQL驱动类使用的是“com.mysql.cj.jdbc.Driver”

2.application.yml配置
# 数据库连接配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver


//用户名和密码根据你的数据库而定
//mybatis_test就是你自己的数据库名,你的可能是别的名
3.application.properties配置
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url= jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
#连接数据库的⽤⼾名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=root

//用户名和密码根据你的数据库而定
//mybatis_test就是你自己的数据库名

(4)@Mapper注解

1.注解含义

🌟表示是MyBatis中的Mapper接口

2.功能

💗程序运行时, 框架会自动生成接口的实现类对象(代理对象),并交给Spring的IOC容器管理


💚与五大注解功能一样;但因为这里用的是MyBatis,所以要用它的注解而不用五大注解

(5)写持久层代码

1.回顾持久层的规范

①包规范:一般取名叫mapper


②接口规范:XxxMapper

2.创建包以及接口代码

①创建的包和接口


②UserInfoMapper接口代码

(@Select注解:代表的就是select查询,也就是注解对应方法的具体实现内容)

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo")
    public List<UserInfo> selectAll();
}

(6)IDEA自动生成测试类

1. 在需要测试的Mapper接口中,右键➜Generate➜Test


2. 选择要测试的方法,点击OK


3.编写代码

(记得加@SpringBootTest注解, 加载Spring运行环境)

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectAll() {
        List<UserInfo> userInfoList = userInfoMapper.selectAll();
        System.out.println(userInfoList);
    }
}

4.运行结果

三:MyBatis注解的基础操作

(1)打印日志

1.作用

🌟Mybatis当中我们可以借助日志,查看到sql语句的执行、执行传递的参数以及执行的结果

2.方法

💗在配置文件中进行配置即可


①application.properties配置

#指定mybatis输出⽇志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

②application.yml配置

# 配置打印 MyBatis⽇志
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.观察效果

💚重新运行程序之后,观察效果


①查询语句

②传递的参数以及类型

③SQL执行结果

(2)参数传递

1.作用

🌟为了解决限制字段条件的语句

(比如查询id=4的用户数据,那么id该怎么传?)

2.方法
💜两个步骤

💗①先在注解修饰的方法形参中加入你需要限制条件的字段名


💗②然后再给注解中查询语句限制条件的字段名加上#{ }


💚此时传过去的限制条件就是动态的了;比如我想查询id=3的用户数据,那么我就传入参数id为3,如果我突然又想查询id=4的用户数据,那就传入参数id为4,就很方便,动态的输入,而不是写死

3.代码及运行结果

①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id=#{id}")
    List<UserInfo> selectOne(Integer id);
}

②UserInfoMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectOne() {
        //查询id=4的用户数据
        List<UserInfo> userInfoList1 = userInfoMapper.selectOne(4);
        System.out.println(userInfoList1);
    }
}

③运行结果


④比如我突然想查询id=3的用户数据,那么我只需要将参数改成3即可

4.注意事项

①如果SQL查询只需要一个参数,那么参数字段名是可以任意的

(但还是建议和参数名保持⼀致,两个是一样最好!!!)


②如果SQL查询需要的参数超过一个,那么参数字段名不可以任意


③通过@Param设置参数的别名,如果使用@Param设置别名, #{...}里面的属性名必须和 @Param设置的⼀样

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id=#{userid}")
    List<UserInfo> selectOne2(@Param("userid") Integer id);
}
package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectOne2() {
        List<UserInfo> userInfoList2 = userInfoMapper.selectOne2(1);
        System.out.println(userInfoList2);
    }
}

(3)增(Insert)

1.方法

💜两个步骤;使用@Insert注解


💗①先在@Insert注解修饰的方法形参中加入需要添加的实体类对象

(方法形参传的是对象)


💗②然后再在@Insert注解中写上insert语句,values后面的参数加上#{}

(这些参数名要与实体类的属性名相一致)


💙@Insert语句返回的是Integer类型,即返回的是有多少行受影响

2.代码及运行结果

①UserInfo实体类的代码

package com.hlizoo.demo.model;
import lombok.Data;
import java.util.Date;

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

②UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Insert("insert into userinfo(username,password,age,gender,phone) "+
            "values(#{username},#{password},#{age},#{gender},#{phone})")
    Integer insert(UserInfo userInfo);
}

③UserInfoMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("zhaoliu");
        userInfo.setAge(18);
        userInfo.setGender(0);
        userInfo.setPhone("123456666");
        Integer result = userInfoMapper.insert(userInfo);
        log.info("inset方法的执行结果:"+result);
    }
}

④观察结果

3.返回主键
1.作用

🌟Insert语句默认返回的是受影响的行数,但有些情况下,数据插插入之后,还需要有后续的关联操作,需要获取到新插入数据的id,即要拿到自增id


2.方法

💗在Mapper接口的方法上添加⼀个Options的注解


@Options注解有两个参数

①useGeneratedKeys:是否使用自动生成的key;默认值为false

②keyProperty:将这个自动生成的key赋值给谁;默认是未设置

3.代码

①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into userinfo(username,password,age,gender,phone) "+
            "values(#{username},#{password},#{age},#{gender},#{phone})")
    Integer insert(UserInfo userInfo);
}

②UserInfoMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("zhaoliu");
        userInfo.setAge(18);
        userInfo.setGender(0);
        userInfo.setPhone("123456666");
        Integer result = userInfoMapper.insert(userInfo);
        log.info("inset方法的执行结果:"+result);
    }
}

③测试效果

4.重命名特殊情况

🌟@Insert注解修饰的方法同样可以用@Param进行重命名


💗如果使用@Param将对象进行重命名,#{}需要使用重命名的对象名字.属性来获取


(4)删(Delete)

1.方法

💜两个步骤;使用@Delete注解


💗①先在@Delete注解修饰的方法形参中加入你需要删除哪些限制条件的字段名数据


💗②然后再给@Delete注解中删除语句限制条件的字段名加上#{ }

2.代码及运行结果

①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Delete("delete from userinfo where id=#{id}")
    Integer delete(Integer id); 
}

②UserInfoMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void delete() {
        userInfoMapper.delete(6);
        log.info("删除完毕");
    }
}

③运行结果

(5)改(Update)

1.方法

💜两个步骤;使用@Update注解


💗①先在@Update注解修饰的方法形参中加入你需要修改哪些限制条件的字段名数据


💗②然后再给@Update注解中修改语句限制条件的字段名加上#{ }

2.代码及运行结果

①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Update("update usernifo set age=#{age} where id=#{id}")
    Integer update(UserInfo userInfo);
}

②UserInfoMapperTest测试代码

import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(55);
        userInfo.setId(5);
        Integer result = userInfoMapper.update(userInfo);
        if(result>0){
            log.info("数据修改成功!");
        }
    }
}

③运行结果

(6)查(Select)

1.方法

💜两个步骤;使用@Select注解


💗①先在@Select注解修饰的方法形参中加入你需要修改哪些限制条件的字段名数据


💗②然后再给@Select注解中修改语句限制条件的字段名加上#{ }

2.字段起别名方式

🌟在SQL语句中,给列名起别名,保持别名和实体类属性名一样


💚原因:结果映射;MyBatis会自动的根据数据库的字段名和Java对象的属性名进行映射;如果名称一样就进行赋值


①比如我现在UserInfo实体类的属性名如下

②那我在@Select注解中的查询语句字段保持跟上述一样

③运行结果

3.使用@Results注解方式

💗方法:使用@Results和@Result注解完成起别名,实现结果映射

(1)column:列名;表示要给哪一个字段起别名

(数据库字段)

(2)property:表示起的别名叫什么

(java属性字段)


①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Results({
         @Result(column = "delete_flag",property = "deleteFlag"),
         @Result(column = "create_time",property = "createTime"),
         @Result(column = "update_time",property = "updateTime")
    })
    @Select("select * from userinfo")
    List<UserInfo> selectAll2();
}

②UserInfoMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectAll2() {
        List<UserInfo> userInfoList = userInfoMapper.selectAll2();
        System.out.println(userInfoList);
    }
}

③运行结果

🌟如果其他SQL,也希望可以复用这个映射关系,可以给这个Results定义一个名称

(好处:避免写了太多的@Results,代码可读性差)


💗方法

①给@Results加上一个id属性,表示定义一个名称;再加个value

②再在需要复用Results的方法加个@ResultsMapper注解,然后写value属性为定义的名称


4.驼峰命名(推荐)

💗方法:使用配置文件;使得这两种方式自动进行映射,而不用进行重命名

(原因:通常数据库列使用蛇形命名法进行命名(下划线分割各个单词),而Java属性⼀般遵循驼峰命名法约定)


①application.yml文件

mybatis:
 configuration:
     map-underscore-to-camel-case: true

②application.properties文件

mybatis.configuration.map-underscore-to-camel-case=true

四:MyBatis XML配置文件

(1)准备工作

1.配置数据库

🌟参考《目录二MyBatis入门的(3)数据库配置文件》

2.配置xml的文件路径

💗classpath后面跟的就是resources里所在的目录

比如下面我放的是mapper,那么我就要在resources目录下创建一个mapper目录


①application.yml文件

# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis:
 mapper-locations: classpath:mapper/**Mapper.xml

②application.properties文件

# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
mybatis.mapper-locations=classpath:mapper/**Mapper.xml
3.XML的实现

🌟注意:XML和注解是可以共存的

第一步:创建接口

💗如图,创建一个名为UserInfoXMLMapper的接口,然后声明一个方法


package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface UserInfoXMLMapper {
    List<UserInfo> selectAll();
}
第二步:创建一个XML文件

💗在classpath后面跟的目录底下创建一个XML文件,在这里写XML代码

(建议这个XML文件名字跟你的接口名字是一样的)


💙比如我的classpath后面是mapper,那我就在mapper目录下添加一个XML文件

第三步:编写XML声明代码

💗注:<mapper namespace>指的是你要实现的是哪个接口

①接口必须是全限定类名

②全限定类名:包+类名

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

</mapper>

🌟比如我的包是package com.hlizoo.demo.mapper,类名是UserInfoXMLMapper,那么我的mapper namespace如下图所示

4.查询所有用户的实现

🌟代码的实现都在mapper标签里

(1)id:接口定义的方法名

(2)resultType:定义的实体类;实体类也必须是全限定类名


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">
<mapper namespace="com.hlizoo.demo.mapper.UserInfoXMLMapper">

    <select id="selectAll" resultType="com.hlizoo.demo.model.UserInfo">
        select * from userinfo
    </select>

</mapper>

测试代码:

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void selectAll() {
        List<UserInfo> userInfoList = userInfoXMLMapper.selectAll();
        log.info(userInfoList.toString());
    }
}

结果:

(2)增(Insert)

1.方法

💗使用<insert></insert>标签;id依旧是接口定义的方法名


💚属性声明和注解一样,使用#{ }


🌟除了select查询需要resultType,其他的增删改查只需要写id即可

2.代码

①UserInfo接口的方法代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface UserInfoXMLMapper {
    Integer insert(UserInfo userInfo);
}

②UserInfoXMLMapper的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">
<mapper namespace="com.hlizoo.demo.mapper.UserInfoXMLMapper">

    <insert id="insert">
        insert into userinfo(username,password,age,gender,phone)
        values(#{username},#{password},#{age},#{gender},#{phone})
    </insert>

</mapper>

③UserInfoXMLMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("love");
        userInfo.setPassword("java");
        userInfo.setAge(8);
        userInfo.setGender(1);
        userInfo.setPhone("1589666666");
        Integer result = userInfoXMLMapper.insert(userInfo);
        log.info("影响的行数:"+result);
    }
}

④运行结果

3.返回主键

💗在insert标签中设置useGeneratedKeys和keyProperty属性,和注解一模一样


4.关于重命名

如果在接口方法中形参中对象使用@Param重命名,那么#{}需要使用重命名的名字.属性来获取


💙和注解一模一样

(3)删(Delete)

1.方法

💗使用<delete></delete>标签;id依旧是接口定义的方法名


💚属性声明和注解一样,使用#{ }


🌟除了select查询需要resultType,其他的增删改查只需要写id即可

2.代码

①UserInfo接口的方法代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface UserInfoXMLMapper {
     Integer delete(Integer id);
}

②UserInfoXMLMapper的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">
<mapper namespace="com.hlizoo.demo.mapper.UserInfoXMLMapper">

    <delete id="delete">
        delete from userinfo where id=#{id}
    </delete>

</mapper>

③UserInfoXMLMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void delete() {
        Integer result = userInfoXMLMapper.delete(8);
        log.info("成功影响的行数:"+result);
    }
}

④运行结果

(4)改(Update)

1.方法

💗使用<update></update>标签;id依旧是接口定义的方法名


💚属性声明和注解一样,使用#{ }


🌟除了select查询需要resultType,其他的增删改查只需要写id即可

2.代码

①UserInfo接口的方法代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;

@Mapper
public interface UserInfoXMLMapper {
     Integer update(UserInfo userInfo);
}

②UserInfoXMLMapper的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">
<mapper namespace="com.hlizoo.demo.mapper.UserInfoXMLMapper">

    <update id="update">
        update userinfo set gendar=#{} where id=#{id}
    </update>

</mapper>

③UserInfoXMLMapperTest测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;

    @Test
    void update() {
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(555);
        userInfo.setId(9);
        userInfoXMLMapper.update(userInfo);
    }
}

④运行结果

(5)查(Select)

1.方法

💗使用<select></select>标签;id是接口定义的方法名,resultType是实体类的全限定类名


💚属性声明和注解一样,使用#{ }

2.结果映射

💗和注解的三种方法一样,还是比较推荐驼峰命名

(只有和第二种的略微不一样,下面我们详细说第二种)

3.使用ResultMap和Result标签

五:多表查询

(1)准备工作

1.思路

①创建一个数据库mybatis_test,在库中创建一张用户表,一张文章表

(用户表的id对应文章表的uid)


②创建一个model包,包中创建两个实体类,一个表示用户实体类,一个表示文章实体类

2.用户表的SQL代码和实体类

①SQL代码

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`username` VARCHAR ( 127 ) NOT NULL,
`password` VARCHAR ( 127 ) NOT NULL,
`age` TINYINT ( 4 ) NOT NULL,
`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
`phone` VARCHAR ( 15 ) DEFAULT NULL,
`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

②实体类

package com.hlizoo.demo.model;
import lombok.Data;
import java.util.Date;

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}
3.文章表的SQL代码和实体类

①SQL代码

-- 创建文章表
DROP TABLE IF EXISTS articleinfo;

CREATE TABLE articleinfo (
 id INT PRIMARY KEY auto_increment,
 title VARCHAR ( 100 ) NOT NULL,
 content TEXT NOT NULL,
 uid INT NOT NULL,
 delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
 create_time DATETIME DEFAULT now(),
 update_time DATETIME DEFAULT now() 
) DEFAULT charset 'utf8mb4';

-- 插入测试数据
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1);

②实体类

package com.hlizoo.demo.model;
import lombok.Data;
import java.util.Date;

@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

(2)根据文章的uid查找用户信息

💗SQL语句:

select ta.*,tb.username,tb.age from articleinfo ta left join userinfo tb on ta.uid=tb.id where ta.uid=1;

(3)MyBatis实现多表查询

🌟关键点:和普通查询一样,只不过需要在你映射对象的实体类加多几个属性

①先在mapper目录下创建一个ArticleInfoMapper接口


②在ArticleInfoMapper接口中实现对应的方法

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.ArticleInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface ArticleInfoMapper {
    @Select("select ta.*,tb.username,tb.age from articleinfo ta left join userinfo tb on ta.uid=tb.id where ta.uid=1")
    ArticleInfo selectArticleAndUserById(Integer articleId);
}

③在ArticleInfoMapperTest完成测试代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.ArticleInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;

@Slf4j
@SpringBootTest
class ArticleInfoMapperTest {
    @Autowired
    private ArticleInfoMapper articleInfoMapper;

    @Test
    void selectArticleAndUserById() {
        ArticleInfo articleInfo = articleInfoMapper.selectArticleAndUserById(1);
        log.info(articleInfo.toString());
    }
}

④补充ArticleInfo实体类信息

(因为select查询语句还用到username和age,如果ArticleInfo没有写就无法显示)

package com.hlizoo.demo.model;
import lombok.Data;
import java.util.Date;

@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

    //补充用户相关信息
    private String username;
    private Integer age;
}

⑤运行结果

六:#{} 和 ${}

(1)#{}的使用

1.Integer类型的变量

🌟观察日志可得:id的值是使用?进行占位的


2.String类型的变量

🌟①#{username}没有使用拼接引号' '


🌟②观察日志可得:username的值是使用?进行占位的


(2)${}的使用

1.Integer类型的变量

🌟观察日志可得:id的值是直接拼接在字符串当中


2.String类型的变量

🌟①'${username}'必须要使用拼接引号' '


🌟②观察日志可得:username的值是直接拼接在字符串当中


(3)#{} 和 ${}的共同之处

💗#{} 和 ${}都是为了去获取变量的值

(4)#{} 和 ${}的区别

1.SQL名称不同

①#{}:使用的是预编译SQL

(用?作为占用符,提前对SQL进行编译, 然后把参数填充到SQL语句中)


②${}:使用的是即时SQL

(直接把变量拼接上去,一起对SQL进行编译)

2.String类型变量的处理不同

①#{}:如果参数类型为String,会自动的加上引号' '


②${}:如果参数类型为String,必须手动加上引号' '

3.性能高低不同

①#{}:属于预编译SQL;性能比较高


②${}:属于即时SQL;性能比较低

4.SQL注入不同

①#{}:不存在SQL注入的安全漏洞问题


②${}:存在SQL注入的安全漏洞问题

(由于${}是手动添加引号,在用户输⼊参数时,在参数中添加⼀些 SQL关键字,达到改变SQL运行结果的目的,也可以完成恶意攻击)


🌟例如下图这个代码,当你的查询条件加入这个,就会查询到所有的数据

5.使用场景

①#{}:实际开发中,能使用#{}就尽量使用


②${}:用于排序查询和模糊查询;除了这两个,其他查询如果用${},必须考虑SQL注入安全问题

(5)排序功能

1.使用场景

💗当使用到SQL语句排序的时候,使用${}


🌟原因:当我使用#{}的时候,它会自动的帮我加上引号,但降序和升序是不需要引号的

2.排序使用#{}的弊端

💗前面说过,#{}会自动的添加上引号,通过下面的例子,来看看为什么排序不建议用#{}


①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    //sort表示是按升序还是降序排,一会我们给sort参数传入desc或者asc
    @Select("select * from userinfo order by id #{sort}")
    List<UserInfo> selectUserBySort(String sort);
}

②UserInfoMapperTest代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectUserBySort() {
        log.info(userInfoMapper.selectUserBySort("asc").toString());
    }
}

③运行结果

💚注意:asc和desc在SQL语句中是不需要添加引号的

3.排序使用${}的好处

 ①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    //sort表示是按升序还是降序排,一会我们给sort参数传入desc或者asc
    @Select("select * from userinfo order by id ${sort}")
    List<UserInfo> selectUserBySort(String sort);
}

②UserInfoMapperTest代码
package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectUserBySort() {
        log.info(userInfoMapper.selectUserBySort("asc").toString());
    }
}

③运行结果

(6)模糊查询

1.使用场景

💗当使用到SQL语句模糊查询的时候,使用${}


🌟原因:当我使用#{}的时候,它会自动的帮我加上引号

2.模糊查询使用#{}的弊端

 ①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.catalina.User;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where username like '%#{username}%'")
    List<UserInfo> selectUserByLike(String username);
}

②UserInfoMapperTest代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectUserByLike() {
        log.info(userInfoMapper.selectUserByLike("java").toString());
    }
}

③运行结果

3.模糊查询使用${}的好处

 ①UserInfoMapper代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import org.apache.catalina.User;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where username like '%${username}%'")
    List<UserInfo> selectUserByLike(String username);
}

②UserInfoMapperTest代码

package com.hlizoo.demo.mapper;
import com.hlizoo.demo.model.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;

@Slf4j
//切记一定要加@SpringBootTest
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    UserInfoMapper userInfoMapper;

    @Test
    void selectUserByLike() {
        log.info(userInfoMapper.selectUserByLike("java").toString());
    }
}

③运行结果

七:数据库连接池

(1)介绍

💗概念:数据库连接池负责分配、管理和释放数据库连接


💗特点:它允许应用程序重复使用⼀个现有的数据库连接, 而不是再重新创立一个


💗优点:

①减少了网络开销

②资源重用

③提升了系统的性能

(2)无连接池和有连接池的区别

💙①无连接池:每次执行SQL语句,要先创建⼀个新的连接对象,然后执行SQL语句,SQL语句执行完,再关闭连接对象释放资源;这种重复的创建连接,销毁连接比较消耗资源


💙②有连接池:程序启动时,会在数据库连接池中创建⼀定数量的Connection对象,当客户请求数据库连接池,会从数据库连接池中获取Connection对象,然后执行SQL,SQL语句执行完,再把Connection归还给连接池


(3)常见的数据库连接池

①C3P0

②DBCP

③Druid

④Hikari


💜目前比较流行的是Hikari和Druid

(4)HiKari

💗Hikari : SpringBoot默认使用的数据库连接池


(5)Druid

💛如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要引入相关依赖即可


dependency>
 <groupId>com.alibaba</groupId>
 <artifactId>druid-spring-boot-starter</artifactId>
 <version>1.1.17</version>
</dependency>

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

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

相关文章

4D Gaussian Splatting:用于实时的动态场景渲染

Wu G, Yi T, Fang J, et al. 4d gaussian splatting for real-time dynamic scene rendering[J]. arXiv preprint arXiv:2310.08528, 2023. 更多参考资料如下&#xff1a; 文章总结&#xff1a;4D Gaussian Splatting for Real-Time Dynamic Scene Rendering&#xff1b;疑难问…

蓝桥杯每日一题2023.11.26

题目描述 奖券数目 - 蓝桥云课 (lanqiao.cn) 将每一个数字进行一一枚举&#xff0c;如果检查时不带有数字4则答案可以加1 #include<bits/stdc.h> using namespace std; int ans; bool check(int n) {while(n){if(n % 10 4)return false;n / 10; }return true; } int m…

线性分组码的奇偶校验矩阵均匀性分析

回顾信道编解码知识&#xff0c;我们知道信道编码要求编码具有检纠错能力&#xff0c;作为FEC&#xff08;forward error correction&#xff09;前向纠错编码的一类&#xff0c;线性分组码表示校验位与信息位的关系能够线性表示。 在这篇文章中&#xff0c;并不是要讨论信道编…

NX二次开发UF_CURVE_ask_isocline 函数介绍

文章作者&#xff1a;里海 来源网站&#xff1a;https://blog.csdn.net/WangPaiFeiXingYuan UF_CURVE_ask_isocline Defined in: uf_curve.h int UF_CURVE_ask_isocline(tag_t isocline_feat, int * face_cnt, tag_p_t * faces, double direction [ 3 ] , char * * start_ang…

plotneuralnet和netron结合绘制模型架构图

plotneuralnet和netron结合绘制模型架构图 一、plotneuralnet 本身的操作 模型结构图的可视化&#xff0c;能直观展示模型的结构以及各个模块之间的关系。最近借助plotneuralnet python库&#xff08;windows版&#xff09;绘制了一个网络结构图&#xff0c;有一些经验和心得…

使用Pytorch从零开始构建Normalizing Flow

归一化流 (Normalizing Flow) &#xff08;Rezende & Mohamed&#xff0c;2015&#xff09;学习可逆映射 f : X → Z f: X \rightarrow Z f:X→Z, 在这里X是我们的数据分布&#xff0c;Z是选定的潜在分布。 归一化流是生成模型家族的一部分&#xff0c;其中包括变分自动编…

手摸手Element-Plus组件化开发

前端环境准备 编码工具: VSCode 依赖管理:NPM 项目构建: Vuecli NPM的全称是Node Package Manager&#xff0c;是一个NodeJS包管理和分发工具&#xff0c;已经成为了非官方的发布Node模块&#xff08;包&#xff09;的标准。2020年3月17日&#xff0c;Github宣布收购npm&am…

扫码点餐小程序的效果如何

扫码点餐是餐饮商家常用的方式&#xff0c;其可以帮助商家更好更快的服务到店客户及节省商家点餐、加菜、汇总结算的时间及人力成本。 通过【雨科】平台搭建餐饮扫码点餐小程序&#xff0c;客户进店用小程序扫描桌码即可开始点餐&#xff0c;确认菜单信息后打印小票提交到厨房…

C# WPF上位机开发(开篇)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 之前很少用到c#语言&#xff0c;大部分时间都用c/c&#xff0c;主要是它可以兼顾上位机qt开发以及嵌入式开发。所以&#xff0c;用c/c是比较合理的…

flex布局实战之自动填充剩余

案例目标 文字部分自适应并且居中 图中是一个弹窗&#xff0c;我现在使用flex的布局来实现&#xff0c;标题和关闭按钮。因为是uni-app,所以标签是view 。你可以自行替换为 代码 <view class"popup-box"><view class"title"><view class&…

CSS特效019:图标图片悬浮旋转一周

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧&#xff0c;主要包含CSS布局&#xff0c;CSS特效&#xff0c;CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点&#xff0c;CSS特效主要是一些动画示例&#xff0c;CSS花边是描述了一些CSS…

Java新建项目如何整理项目结构,没有src文件夹

现在IDEA2023中新建项目时, 不会有src文件夹。这时需要自己创建一个src的包&#xff0c;然后将这个包设置为source root。 可能出现没有这个选项的情况&#xff0c;这是需要把设置的当前项目首先Unmark了&#xff0c;然后再对src文件夹mark一下。 src: 这是源代码的根目录。 …

rsyslog出现Unit rsyslog.service is masked不可用问题解决

博主在测试将日志发送到日志服务器的功能时遇到了rsyslog服务不可用的问题&#xff0c;具体来说&#xff0c;就是执行systemctl restart rsyslog或者 service rsyslog restart命令时&#xff0c;出现了标题中所述的Unit rsyslog.service is masked问题。网上查找了很多资料&…

【Linux学习笔记】protobuf 基本数据编码

https://zhuanlan.zhihu.com/p/557457644https://zhuanlan.zhihu.com/p/557457644 [新文导读] 从Base64到Protobuf&#xff0c;详解Protobuf的数据编码原理本篇将从Base64再到Base128编码&#xff0c;带你一起从底层来理解Protobuf的数据编码原理。本文结构总体与 Protobuf 官…

基于opencv+ImageAI+tensorflow的智能动漫人物识别系统——深度学习算法应用(含python、JS、模型源码)+数据集(四)

目录 前言总体设计系统整体结构图系统流程图 运行环境爬虫模型训练实际应用 模块实现1. 数据准备1&#xff09;爬虫下载原始图片2&#xff09;手动筛选图片 2. 数据处理3. 模型训练及保存4. 模型测试1&#xff09;前端2&#xff09;后端 系统测试1. 测试效果2. 模型应用1&#…

CSP认证2023-09:坐标变换(其一)、坐标变换(其二)、梯度求解,python满分代码解答

CSP认证2023-09&#xff1a;坐标变换(其一)、坐标变换&#xff08;其二&#xff09;、梯度求解&#xff0c;python满分代码解答 目录 一、坐标变换&#xff08;其一&#xff09; 问题描述 输入和输出 思路 代码和结果 c代码 python代码 二、坐标变换&#xff08;其二&am…

从零开始搭建博客网站-----构建项目

构建项目 视频参考链接 构建一个项目文件&#xff08;node为17.16.0版本&#xff09; 构建的过程中可能会出现一个选项&#xff0c;选择vueJavaScript npm init vitelatest easyblog-front-admin安装相关依赖 cd easyblog-front-admin npm install3. 运行 npm run dev好了…

卷积神经网络(CNN)识别验证码

文章目录 一、前言二、前期工作1. 设置GPU&#xff08;如果使用的是CPU可以忽略这步&#xff09;2. 导入数据3. 查看数据4.标签数字化 二、构建一个tf.data.Dataset1.预处理函数2.加载数据3.配置数据 三、搭建网络模型四、编译五、训练六、模型评估七、保存和加载模型八、预测 …

2023年网络安全比赛--综合渗透测试②(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将扫描开放的所有端口当作flag提交(例:21,22,23); 2.通过 PC 中的渗透测试平台 Kali 对服务器场景进行渗透测试,将初…

Linux内核--内存管理(一)任务空间管理

目录 一、引言 二、基本概念梳理 三、用户态进程内存管理 ------>3.1、用户态 ------>3.2、内核态 ------>3.3、内存管理结构 ------>3.4、mm_struct ------>4.5、vm_area_struct 四、内核态结构 ------>4.1、32位内核态结构 ------>4.2、64位…