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=falseusername: rootpassword: rootdriver-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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@Autowiredprivate UserInfoXMLMapper userInfoXMLMapper;@Testvoid 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 {@Autowiredprivate UserInfoXMLMapper userInfoXMLMapper;@Testvoid 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 {@Autowiredprivate UserInfoXMLMapper userInfoXMLMapper;@Testvoid 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 {@Autowiredprivate UserInfoXMLMapper userInfoXMLMapper;@Testvoid 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 {@Autowiredprivate ArticleInfoMapper articleInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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 {@AutowiredUserInfoMapper userInfoMapper;@Testvoid 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>
相关文章:
MyBatis 操作数据库(入门)
一:MyBatis概念 (1)MyBatis 💗MyBatis是一款优秀的持久层框架,用于简化JDBC的开发 (2)持久层 1.持久层 💜持久层:持久化操作的层,通常指数据访问层(dao),是用来操作数据库的 2.持久层的规范 ①…...
JVM——垃圾回收器(G1,JDK9默认为G1垃圾回收器)
1.G1垃圾回收器 JDK9之后默认的垃圾回收器是G1(Garbage First)垃圾回收器。 Parallel Scavenge关注吞吐量,允许用户设置最大暂停时间 ,但是会减少年轻代可用空间的大小。 CMS关注暂停时间,但是吞吐量方面会下降。 而G1…...
多模态——使用stable-video-diffusion将图片生成视频
多模态——使用stable-video-diffusion将图片生成视频 0. 内容简介1. 运行环境2. 模型下载3. 代码梳理3.1 修改yaml文件中的svd路径3.2 修改DeepFloyDataFiltering的vit路径3.3 修改open_clip的clip路径3.4 代码总体结构 4. 资源消耗5. 效果预览 0. 内容简介 近期,…...
springboot(ssm网络相册 在线相册管理系统Java(codeLW)
springboot(ssm网络相册 在线相册管理系统Java(code&LW) 开发语言:Java 框架:ssm/springboot vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7(或8.0)…...
邮箱发送短信的多种方式
第一种:邮箱验证方法: 导入依赖: <!-- mail依赖(发送短信的依赖) --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> &l…...
R语言——taxize(第五部分)
taxize(第五部分) 3. taxize 文档中译3.71. nbn_synonyms(从 NBN 返回具有给定 id 的分类群名称的所有同义词)3.72. ncbi_children(在 NCBI 中搜索类群的子类群)3.73. ncbi_downstream(检索 NCB…...
负载均衡lvs
简介 ipvsadm 是 Linux 内核中的 IP 虚拟服务器(IPVS)管理工具。IPVS是 Linux 内核提供的一种负载均衡解决方案,它允许将入站的网络流量分发到多个后端服务器,以实现负载均衡和高可用性。IPVS通过在内核中维护一个虚拟服务器表&a…...
【腾讯云云上实验室】探索向量数据库背后的安全监控机制
当今数字化时代,数据安全成为了企业和个人最为关注的重要议题之一。随着数据规模的不断增长和数据应用的广泛普及,如何保护数据的安全性和隐私性成为了迫切的需求。 今天,我将带领大家一起探索腾讯云云上实验室所推出的向量数据库,…...
阅读笔记——《Removing RLHF Protections in GPT-4 via Fine-Tuning》
【参考文献】Zhan Q, Fang R, Bindu R, et al. Removing RLHF Protections in GPT-4 via Fine-Tuning[J]. arXiv preprint arXiv:2311.05553, 2023.【注】本文仅为作者个人学习笔记,如有冒犯,请联系作者删除。 目录 摘要 一、介绍 二、背景 三、方法…...
electron实现截图的功能
Electron是一种跨平台的桌面应用程序开发框架,可以使用HTML、CSS和JavaScript等Web技术构建桌面应用程序。下面是一种使用Electron实现截图的简单方法: 安装Electron和截图库 首先,需要安装Electron和一个截图库,例如electron-sc…...
11、动态数码管显示
数码管驱动方式 1、单片机直接扫描:硬件设备简单,但会消耗大量的单片机CPU时间 2、专用驱动芯片:内部自带显存、扫描电路,单片机只需告诉他显示什么即可 #include <REGX52.H> //数组代表显示亮灯的内容0、1、2、3、4、5、…...
Linux的基本指令(三)
目录 前言 echo指令(简述) Linux的设计理念 输出重定向操作符 > 追加输出重定向操作符 >> 输入重定向操作符 < 补充知识 学前补充 more指令 less指令 head指令 tail指令 查看文件中间的内容 利用输出重定向实现 利用管道“ |…...
使用python 实现华为设备的SFTP文件传输
实验目的: 公司有一台CE12800的设备,管理地址位172.16.1.2,现在需要编写自动化脚本,通过SFTP实现简单的上传下载操作。 实验拓扑: 实验步骤: 步骤1:将本地电脑和ensp的设备进行桥接ÿ…...
高防cdn防护原理是什么,是否可以防护服务器吗
随着互联网业务的迅速发展,网络安全问题日益凸显。在这样的背景下,高防CDN作为一种有效的网络安全解决方案,受到了越来越多的关注。那么高防CDN的防护原理是什么呢?接下来就跟小德一起深入了解下吧! 1. 高防CDN的基本概念 我们要明确什么是…...
SELinux零知识学习三十五、SELinux策略语言之角色和用户(6)
接前一篇文章:SELinux零知识学习三十四、SELinux策略语言之角色和用户(5) 三、SELinux策略语言之角色和用户 SELinux提供了一种依赖于类型强制(类型增强,TE)的基于角色的访问控制(Role-Based Access Control),角色用于组域类型和限制域类型与用户之间的关系,SELinux…...
初学Flink 学后总结
最近开始学习Flink,一边学习一边记录,以下是基于【尚硅谷】Flink1.13实战教程总结的笔记,方便后面温习 目录 初始 Flink 一:基础概念 1.Flink是什么 2.Flink主要应用场景...
CSS新手入门笔记整理:CSS基本介绍
CSS,指的是“Cascading Style Sheet(层叠样式表)”,用于控制网页外观。 CSS引入方式 外部样式表 独立建立一个.CSS文件,在HTML中使用 link标签 来引用CSS文件。link标签放置在head标签内部。 语法 <link rel&qu…...
【华为OD】B\C卷真题 100%通过:需要打开多少监控器 C/C++实现
【华为OD】B\C卷真题 100%通过:需要打开多少监控器 C/C实现 目录 题目描述: 示例1 代码实现: 题目描述: 某长方形停车场,每个车位上方都有对应监控器,当且仅当在当前车位或者前后左右四个方向任意一个…...
HarmonyOS开发(七):构建丰富页面
1、组件状态管理 1.1、概述 在应用中,界面一般都是动态的。界面会根据不同状态展示不一样的效果。 ArkUI作为一种声明式UI,具有状态驱动UI更新的特点,当用户进行界面交互或有外部事件引起状态改变时,状态的变会会触发组件的自动…...
LuatOS-SOC接口文档(air780E)--rsa - RSA加密解密
示例 -- 请在电脑上生成私钥和公钥, 当前最高支持4096bit, 一般来说2048bit就够用了 -- openssl genrsa -out privkey.pem 2048 -- openssl rsa -in privkey.pem -pubout -out public.pem -- privkey.pem 是私钥, public.pem 是公钥 -- 私钥用于 加密 和 签名, 通常保密, 放在…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
动态规划-1035.不相交的线-力扣(LeetCode)
一、题目解析 光看题目要求和例图,感觉这题好麻烦,直线不能相交啊,每个数字只属于一条连线啊等等,但我们结合题目所给的信息和例图的内容,这不就是最长公共子序列吗?,我们把最长公共子序列连线起…...




























































