MyBatis项目的创建和使用

news2024/11/25 23:35:11

什么是MyBatis?

MyBaits是一个更简单的完成程序与数据库交互的工具。MyBatis将复杂的JDBC进行了封装,让使用者可以通过简单的xml和注解对数据库进行记录。

MyBatis的执行流程

创建MyBatis项目

添加依赖

还是SpringBoot的创建流程:SpringBoot项目创建和使用_追梦不止~的博客-CSDN博客

在添加依赖处增加如下两个依赖:

项目创建好后,是如下图(此处我删除了三个文件,不删也可以):

配置连接

在配置文件中(application.properties)中添加如下设置:

//这两行是连起来的,其中mycnblog是我的数据库名,修改成你自己的
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false

//用户名和密码改成你自己的,一般用户名没有改就都是root
spring.datasource.username=root
spring.datasource.password=123456

//固定的
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

如果是yml后缀的配置文件,也是相同的配置,将上述改成yml格式即可。

配置xml路径

同样是在配置文件中添加:

//myBatis是目录,自己设置
//文件名的后缀部分必须是Mapper.xml不能修改,前面可以添加内容
//这里的*代表通配符
mybatis.mapper-locations=classpath:/myBatis/*Mapper.xml

添加业务代码

添加实体类

这个实体类是与我表中的属性一一对应的(包括属性名和类型)

@Data
public class UserEntity {
    private int id;
    private String username;
    private String password;
    private String phone;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int state;
}

添加mapper接口

//注解不能少
@Mapper
public interface UserMapper {
    //每个方法都对应一个sql操作
}

添加Mapper.xml

在resources目录下添加前面在配置文件里面写的xml路径

在xml文件里面添加如下内容:

其中,mapper标签里面的namespace属性里面填的是 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="com.example.demo.mapper.UserMapper">
    
</mapper>

单元测试

什么是单元测试?

单元测试是开发中经常用到的测试方法,在数据库操作中的作用尤为明显。

因为我们在对数据库操作时难免会出现错误,这就可能导致数据库中的数据丢失或出错,通过单元测试就可以很好的解决这个问题。

因为单元测试中有一个标签@Transactional,它会将我们的数据库操作进行回滚,以至于我们的测试不会对数据库的内容造成改变。

MyBatis中实现与数据库交互

注意交互前要先有数据库和表,我是已经提前创建好了

单元测试

什么是单元测试?

单元测试是开发中经常用到的测试方法,在数据库操作中的作用尤为明显。

因为我们在对数据库操作时难免会出现错误,这就可能导致数据库中的数据丢失或出错,通过单元测试就可以很好的解决这个问题。

因为单元测试中有一个标签@Transactional,它会将我们的数据库操作进行回滚,以至于我们的测试不会对数据库的内容造成改变。

如何生成单元测试?

我们对userinfo这个表整体查询,首先在mapper接口类中添加一个方法:

List<UserEntity> getAll();

然后再xml文件中的mapper标签中添加如下内容:

其中id属性是方法名getAll,resultType属性是返回类型,因为返回集合中的类型是UserEntity所以这里就填UserEntity的路径

    <select id="getAll" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo
    </select>

然后我们通过单元测试的方式来进行测验。

我们鼠标右键这个getAll方法后,点击生成,点击生成测试

 然后回出现如下界面,勾中要生成测试的方法,然后点击确定即可。

在test目录下就会生成测试类,如下:

我们对类进行如下操作:

首先要添加@SpringBootTest注解,然后再将mapper类注入进去,然后在生成出来的方法上添加@Transactional注解,让其进行回滚操作,这里是查询操作,不加也可以,如果需要让数据库跟随修改,也可以选择不加。

@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper mapper;

    @Transactional
    @Test
    void getAll() {

    }
}

然后我们在方法中写入我们的代码即可,如下:

    @Transactional
    @Test
    void getAll() {
        List<UserEntity> list = mapper.getAll();
        list.stream().forEach(System.out::println);
    }

然后我们运行这个方法,结果如下:

 此时我的数据库中结果如下: 

查询操作

使用select标签。

在单元测试里面已经演示了一个简单的查询的sql操作,下面的查询操作也是基于前面的基础上的。

${}的使用

xml文件中,${xxx}通常用在sql语句中,充当类似占位符的作用,但是在解析是会将${xxx}里面对应内容看做sql语句的一部分,对于数字类型,如:Integer、double等,它可以直接代指,对于字符串类型需要在${xxx}外面加上引号或单引号:'${xxx}'

此时我们对userinfo这个表中 id 为 1 并且username为 'admin' 的数据进行查询(在我的数据库中共有一条)

此时在mapper接口类中添加方法,返回为UserEntity对象,如下:

@Param注解是给其后面的属性其别名,因为要将参数内容传入xml文件里的sql中,${}里面填加的内容就是注解名字(不加就填原来的名字)

UserEntity getUser(@Param("id")Integer id, @Param("username")String username);

在xml文件中添加如下:

id是数字类型,所以不需要加引号或单引号,username是字符串类型,${}并不会为其自动加引号,所以需要手动添加。

    <select id="getUser" resultType="com.example.demo.entity.UserEntity">
        select * from userinfo where id = ${id} and username = '${username}'
    </select>

生成单元测试,这里不写步骤了,直接给出最终代码,后面同样:

    @Transactional
    @Test
    void getUser() {
        UserEntity user = mapper.getUser(1, "admin");
        System.out.println(user);
    }

执行结果如下:

同时也可以看到,${}的位置填充成了数据。

数据库执行相同操命令,结果如下:

 ${}的缺点:sql注入

前面提到了${}会将里面的内容转化为sql的一部分,但是这样也会产生一系列问题,比如下面的这个查询操作:通过username 和 password来查询某个用户的信息

xml文件:

因为文章规范原因,这里的sql语句进行了修改,将password和=和'${password}'前面的换行删了即可,见谅一下。

<select id="login" resultType="com.example.demo.entity.UserEntity">
    select * from userinfo where username='${username}' and 
password
=
'${password}'
</select>

测试代码:

@Transactional
@Test
void login() {
    UserEntity user = mapper.login("admin","'or 1 = '1");
    System.out.println(user);
}

我们在password的传入中给了一串奇怪的字符串,但是数据库中是没有password为上述所见的数据的,并且此时数据库中只有一条数据。

执行结果如下:

可以看到:虽然数据库中没有这样的数据,但是仍然拿到了用户信息,这样的情况就是sql注入。

并且我们对这条sql进行解读过后,它的解析如下:

查询 userinfo 表中 username = 'admin' 并且 password 为空串 的数据 或者 1 = '1'

因为and的优先级比or高,所以会将 username = 'admin' and password 为空串 看为一体,or 1 = '1'另看做一体,此时只要 1 = '1' 这个条件满足,就会查询出userinfo表中的所有数据,所以表中的数据会被查询出来,但是因为接收的类型是UserEntity,所以如果表有多条数据的情况下就无法用这个来获取,需要注入更复杂的sql来获取了。

#{}的使用

#{}与${}不同的是,${}会将内容看做为sql语句的一部分,而#{}则是将其看做一个占位符。因此#{}无法被sql注入,并且对于字符串类型不需要另外加引号。

我们使用和上面sql注入相同的数据来测试:

xml文件:

此处将${}换做了#{},所以要将外部的单引号去掉,不然会报错。

<select id="login" resultType="com.example.demo.entity.UserEntity">
    select * from userinfo where username=#{username} and password=#{password}
</select>

测试代码:

@Transactional
@Test
void login() {
    UserEntity user = mapper.login("admin","'or 1 = '1");
    System.out.println(user);
}

执行结果如下:

得到的结果是null,并且在sql中 #{}的位置替换成了?,和JDBC中的?占位符是相同的作用。

#{}和${}的区别

${}是字符串替换,对字符串类型替换时需要再外围加上引号或单引号,执行时会将${}里面的内容转化为sql语句的一部分,容易出现sql注入。

#{}是预编译处理,字符串类型不需要加引号,执行时会将#{}替换为?,它的作用和JDBC中的?作用相同。

like查询

like查询与其他查询比较特殊的地方在于:like的模糊匹配中无法使用#{}来注入数据,只能使用${}来注入,但是这个注入方式前面也说了,不如不对输入的内容进行判断,很容易被sql注入,所以此处我们使用concat(MySQL里面的字符串拼接函数)配合#{},来完成like的模糊匹配。

举例:在userinfo表中模糊查询username = '%zhang%'的信息。

mapper接口类:

List<UserEntity> getListByLike(@Param("username") String username);

xml文件:

<select id="getListByLike" resultType="com.example.demo.entity.UserEntity">
    select * from userinfo where username like concat('%', #{username}, '%')
</select>

测试代码:

@Test
void getListByLike() {
    List<UserEntity> list = mapper.getListByLike("zhang");
    list.stream().forEach(System.out::println);
}

结果如下:

数据库数据如下:

返回字典映射resultMap

在前面的查询操作中我们使用的是resultType,绝大部分的查询返回类型都可以通过resultType来设置,但是有一种情况比较特殊:当实体类中的属性名和与其对应的表中的列名不相同时,虽然不会报错,但是该属性不会获取到数据。

这个时候就可以通过resultMap来解决。

首先在xml文件里面创建一个resultMap标签,并将要获取的属性插入标签中。

其中id是该reslutMap的名字,type是要接受数据的类的路径

id标签:主键列

result标签:普通列

在标签中:

property属性 表示 类的属性名

column属性 表示 数据库中表的列名

<resultMap id="BaseMap" type="com.example.demo.entity.UserEntity">
    <id property="id" column="id"></id>
    <result property="username" column="username"></result>
    <result property="pwd" column="password"></result>
    <result property="createtime" column="createtime"></result>
    <result property="updatetime" column="updatetime"></result>
</resultMap>

使用:将原本的resultType代替为resultMap。

举例:在userinfo表中模糊查询username =  '%zhang%'的数据(测试代码和mapper接口类中的内容和前面的like查询中的例子相同)

xml文件:

<resultMap id="BaseMap" type="com.example.demo.entity.UserEntity">
    <id property="id" column="id"></id>
    <result property="username" column="username"></result>
    <result property="pwd" column="password"></result>
    <result property="createtime" column="createtime"></result>
    <result property="updatetime" column="updatetime"></result>
</resultMap>


<select id="getListByLike" resultMap="BaseMap">
    select * from userinfo where username like concat('%', #{username}, '%')
</select>

执行结果:

数据库结果:

修改操作

xml中使用update标签

修改和查询不同,它的返回的是执行成功的行数,所以,它的返回类型就是清一色的int/Integer。

举例:查询id 为 1 并且 password = admin的数据,将password修改为123456

mapper接口类:

int updatePassword(@Param("id")Integer id,
                   @Param("password")String password,
                   @Param("newPassword")String newPassword);

xml文件:

<update id="updatePassword">
    update userinfo set password=#{newPassword} where id=#{id} and password=#{password}
</update>

测试代码:

此处我没有添加@Transactional,为的是可以更好的观察数据是否被修改。

@Test
void updatePassword() {
    int result = mapper.updatePassword(1,"admin","123456");
    System.out.println(result);
}

执行结果如下:

数据库中查询结果如下:

如图是update操作前后两次的查询结果

password的已被修改。

删除操作

使用delete标签。

和update操作相同,返回值都int/Integer类型,返回的是删除的行数。

举例:删除userinfo表中,username 为 zhangsan 的数据(该数据已经提前被插入进去了)

mapper接口类:

int delByName(@Param("username") String username);

xml文件:

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

测试代码:

@Test
void delByName() {
    int result = mapper.delByName("zhangsan");
    System.out.println(result);
}

执行结果:

查询结果:

增添操作

insert标签,在insert标签中可以选择:是否返回该条操作主键列的数据和返回主键的位置。

它的返回类型为int/Integer,返回的是新增成功的行数。

举例:在userinfo表中 添加username 为 zhangsan,password 为 123456的数据,并且将该条sql的主键列返回到id中。

mapper接口类:

int addUserGetId(UserEntity user);

xml文件:

其中useGeneratedKeys代表的是是否返回该条操作的主键列数据,默认为false。

KeyProperty填的是返回到哪个属性里面,因为传入的时候会传入一个UserEntity对象过来,返回的主键数据会存放到这个对象里。

<insert id="addUserGetId" useGeneratedKeys="true" keyProperty="id">
    insert into userinfo(username, password) values(#{username}, #{password})
</insert>

测试代码:

@Test
void addUserGetId() {
    UserEntity user = new UserEntity();
    user.setUsername("zhangsan");
    user.setPassword("123456");
    int result = mapper.addUserGetId(user);
    System.out.println(result);
    System.out.println(user.getId());
}

执行结果如下:

数据库中数据如下:

多表查询

多表操作,也需要实体类来接受,首先是一个文章类

@Data
public class ArticleInfo {
    private int id;
    private String title;
    private String content;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int uid;
    private int rcount;
    private int state;
}

然后将用户类userinfo的username属性和文章类相结合,形成一个多表查询的实体类(也可以直接在文章类里面加个username属性)

因为有了文章类,所以直接让多表查询的实体类继承文章类即可。并且要重写里面的toString方法,因为lombok的toString方法不会将父类的属性一并打印,所以要自己进行重写。

@Data
public class ArticleInfoVO extends ArticleInfo {
    private String username;

    @Override
    public String toString() {
        return "ArticleInfoVO{" +
                "username='" + username + '\'' +
                "} " + super.toString();
    }
}

接下来是mapper接口类:

@Mapper
public interface ArticleMapper {
    
}

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.example.demo.mapper.ArticleMapper">
    
</mapper>

一对一情况

举例:查找文章表中文章编号为1的文章,在查找信息里面要包含该文章对应的作者名。

解析:因为查找信息需要文章信息和作者名,所以需要联合文章表和作者表两个表进行多表查询。

mapper接口类:

List<ArticleInfoVO> getDetail(@Param("id") Integer id);

xml文件:

这里的sql里使用了起别名,articleinfo是文章表别名为a,userinfo是作者表别名为u(后面不再声明)

<select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select a.*,u.username from articleinfo a left join userinfo u on u.id = a.uid where a.id = #{id}
</select>

测试代码:

@Test
void getDetail() {
    List<ArticleInfoVO> list = mapper.getDetail(1);
    list.stream().forEach(System.out::println);
}

结果:

一对多情况

举例:在文章表中查找uid(作者id)为1的文章,在查找信息里面要包含该文章对应的作者名。

mapper接口类:

List<ArticleInfoVO> getListByUid(@Param("uid") Integer uid);

xml文件:

<select id="getListByUid" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select a.*,u.username from articleinfo a left join userinfo u on u.id = a.uid where a.uid = #{uid}
</select>

测试代码:

@Test
void getListByUid() {
    List<ArticleInfoVO> list = mapper.getListByUid(1);
    list.stream().forEach(System.out::println);
}

结果:

动态sql使用 

动态sql本质上就是在sql语句中加上了逻辑判断,在一些场景下需要在sql阶段进行逻辑判断。

比如:在注册信息时,有必填项和选填项,在选填项中可能一些项在创建表时是有默认值的,如果不传递该项就会使用默认值,此时就可以使用动态sql进行逻辑判断,来决定该项是否要传递。

<if>标签

和Java里面的if判断相同。

语法:在sql中使用,if标签里面的test属性为必填项,相当于if中的逻辑判断语句。

举例:添加一个用户,使用if标签判断是否传递了photo属性,并查看sql区别

mapper接口类:

int addUser2(UserEntity user);

xml文件:

test中的photo代表的是传入的photo属性,但是不需要加#{}。

<insert id="addUser2">
    insert into userinfo(username,password
    <if test="photo != null">
        ,photo
    </if>
    ) values(#{username},#{password}
    <if test="photo != null">
        ,#{photo}
    </if>
    )
</insert>

测试代码1,传递photo属性:

@Transactional
@Test
void addUser2() {
    UserEntity user = new UserEntity();
    user.setUsername("lisi");
    user.setPassword("123456");
    //user.setPhoto("photo.png");
    int result = mapper.addUser2(user);
    System.out.println(result);
}

结果:

测试代码2,传递photo属性:

@Transactional
@Test
void addUser2() {
    UserEntity user = new UserEntity();
    user.setUsername("lisi");
    user.setPassword("123456");
    user.setPhoto("photo.png");
    int result = mapper.addUser2(user);
    System.out.println(result);
}

结果:

和测试1相比测试2的结果多了一个参数photo,而测试1因为没有传递,所以在if判断时被排查到,所以没有传递photo。

<trim>标签

<trim>标签它一般和<if>标签搭配使用,在<trim>标签包含的语句,可以通过<trim>里面的属性进行前缀、后缀的添加和删除。

prefix:添加前缀

suffix:添加后缀

prefixOverrides:清除前缀

suffixOverrides:清除后缀

举例:假设所有的属性都是非必选,此时需要所有属性都需要<if>标签判断,但是会出现逗号如何分配的问题,此时将所有的<if>标签的最后都加上逗号,并使用<trim>标签删除最后一个逗号,完成sql语句。

mapper接口类:

int addUser3(UserEntity user);

xml文件:

<insert id="addUser3">
    insert into userinfo
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
            username,
        </if>
        <if test="password != null">
            password,
        </if>
        <if test="photo != null">
            photo,
        </if>
    </trim>

     values

    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="username != null">
            #{username},
        </if>
        <if test="password != null">
            #{password},
        </if>
        <if test="photo != null">
            #{photo},
        </if>
    </trim>
    
</insert>

测试代码:

@Transactional
@Test
void addUser3() {
    UserEntity user = new UserEntity();
    user.setUsername("lisi");
    user.setPassword("123456");
    user.setPhoto("photo.png");
    int result = mapper.addUser3(user);
    System.out.println(result);
}

结果:

<where>标签

<where>标签也是搭配<if>标签使用的。

<where>标签里面如果没有内容则不会添加where语句,如果里面有内容,则会在内容前加上where并且会去除标签内容的前缀and。

使用场景:where里面的条件为非必传

举例:根据id和title查询articleinfo表中的数据,id和title都可能为null

mapper接口类:

List<ArticleInfoVO> getUserByIdOrTitle(@Param("id")Integer id, @Param("title")String title);

xml文件:

第一种方法:where 1=1

因为id和title都可能为null会被<if>标签排除,那么where的后面可能会出现没有条件的情况,此时添加1=1,可以解决这个问题。

<select id="getUserByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    where 1=1
    <trim prefixOverrides="and">
        and
        <if test="id != null and id > 0">
            and id = #{id}
        </if>
        <if test="title != null and title != ''">
            and title like concat('%',#{title},'%')
        </if>
    </trim>
</select>

第二种方法:<trim>标签

因为trim标签中如果没有内容就不会添加前后缀,所以在trim标签中加上前缀where,也可以解决问题。

<select id="getUserByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    <trim prefix="where" prefixOverrides="and">
        <if test="id != null and id > 0">
            and id = #{id}
        </if>
        <if test="title != null and title != ''">
            and title like concat('%',#{title},'%')
        </if>
    </trim>
</select>

第三种方法:<where>标签

<where>标签相当于简化的第二种方法,因为<where>标签的特性:若内容不为空自动添加where和去除前缀and,所以也可以解决问题,并且代码更加简洁。

<select id="getUserByIdOrTitle" resultType="com.example.demo.entity.vo.ArticleInfoVO">
    select * from articleinfo
    <where>
        <if test="id != null and id > 0">
            and id = #{id}
        </if>
        <if test="title != null and title != ''">
            and title like concat('%',#{title},'%')
        </if>
    </where>
</select>

测试代码:

这里只写了一种情况,还可以 全为null 或者 都不为null 或者 title属性为null,id不为null

@Test
void getUserByIdOrTitle() {
    List<ArticleInfoVO> list = mapper.getUserByIdOrTitle(null,"s");
    list.stream().forEach(System.out::println);
}

结果:

<set>标签

set标签使用于修改sql(update)

<set>标签里面的内容不能为空,并且会自动添加set前缀。

举例:根据传入的id,修改articleinfo表中的title和content属性

mapper接口类:

int updateTitleAndContent(@Param("title")String title,
                              @Param("content")String content,
                              @Param("id")Integer id);

xml文件:

传入数据时要注意,set标签里面一定不能没有内容

<update id="updateTitleAndContent">
    update articleinfo
    <set>
        <if test="title != null and title != ''">
            title = #{title},
        </if>
        <if test="content != null and content != ''">
            content = #{content},
        </if>
    </set>
    where id = #{id}
</update>

测试代码:

@Transactional
@Test
void updateTitleAndContent() {
    int result = mapper.updateTitleAndContent("java","java正文",1);
}

结果:

<foreach>标签 

<foreach>标签 会将传入的集合类或数组等容器里面的数据循环取出并注入到sql中。

<foreach>标签 中有五个属性:

collection:传入的集合类的变量名。比如:我传入一个List对象,名字为list,此时里面填list

item:集合类中每一个成员的别名。比如:别名为id,在<foreach>标签里面使用时就可以使用#{id}等。

open:添加前缀。

close:添加后缀。

separator:循环内容的间隔符

举例:删除articleinfo表中id为1、2、3的数据,1、2、3使用List传输。

mapper接口类:

int delByIdList(List<Integer> idList);

xml文件:

collection里填写集合名idList,item填写别名为id,separator填写间隔符号为英文逗号,open填写前缀为( ,close填写后缀为) 。

<delete id="delByIdList">
    delete from articleinfo 
    where id in
    <foreach collection="idList" item="id" separator="," open="(" close=")">
        #{id}
    </foreach>
</delete>

测试代码:

@Transactional
@Test
void delByIdList() {
    List<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    int result = mapper.delByIdList(list);
    System.out.println(result);
}

结果:

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

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

相关文章

SpringMvc笔记-教程-快速回忆

title: SpringMvc笔记 date: 2023-05-14 09:50:02 categories: 后端Java tags:JavaSpring 三层架构&#xff1a; web层主要由servlet来处理&#xff0c;负责页面请求和数据的收集以及响应结果给前端service层主要负责业务逻辑的处理dao层主要负责数据的增删改查操作 MVC设计…

点餐小程序实战教程03-店铺信息展示

目录 1 创建模型应用2 创建用户3 创建自定义应用4 创建页面5 页面搭建6 定义变量7 数据绑定8 绑定事件9 预览发布总结我们上一篇设计了店铺信息数据源,并且录入了测试数据,本篇我们就介绍一下店铺信息展示功能的开发。 1 创建模型应用 我们在上篇讲解的是通过数据源的管理数…

【redis】redis经典五大类型源码及其底层实现

【redis】redis经典五大类型源码及其底层实现 文章目录 【redis】redis经典五大类型源码及其底层实现前言一、面试题redis数据类型的底层数据结构阅读源码的意义 二、在哪找redis的源码&#xff1f;三、SRC下的源码该怎么看&#xff1f;1、redis基本的数据结构&#xff08;骨架…

路径规划算法:基于樽海鞘算法的路径规划算法- 附代码

路径规划算法&#xff1a;基于樽海鞘优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于樽海鞘优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法…

桂院校园导航小程序 静态项目 二次开发教程 1.0.1

Gitee代码仓库&#xff1a;桂院校园导航小程序 GitHub代码仓库&#xff1a;GLU-Guide 先 假装 大伙都成功安装了静态项目&#xff0c;并能在 微信开发者工具 和 手机 上正确运行。 接着就是 将项目 改成自己的学校。 代码里的注释我就不说明了&#xff0c;有提到 我的学校 …

现代软件测试中的自动化测试工具

自动化测试的重要性和优势 引言&#xff1a;随着软件开发的不断发展&#xff0c;自动化测试工具在现代软件测试中扮演着重要角色。提高效率&#xff1a;自动化测试可以加快测试流程&#xff0c;减少人工测试所需的时间和资源。提升准确性&#xff1a;自动化测试工具可以减少人…

python3 爬虫相关学习3:requests.get(url)的各种属性

目录 1 requests.get(url) 的各种属性 1.1 response.text 1 requests.get(url) 的各种属性&#xff0c;也就是response的各种属性 接触的requests模块的常用功能&#xff1a;一般把 response requests.get(url) requests.get(url)的各种属性 print(response.text)print(…

Flink Watermark 源码分析

随着 flink 的快速发展与 API 的迭代导致新老版本差别巨大遂重拾 flink&#xff0c;在回顾到时间语义时对 watermark 有了不一样的理解。 一、如何生成 在 flink 1.12(第一次学习的版本)时 watermark 生成策略还有两种: punctuated 和 periodic&#xff0c;在 1.17 中 punctua…

基于自建靶场三层网络的内网渗透

注意&#xff1a;一切内容仅用于安全技术的分享&#xff0c;切勿用于其他用途&#xff0c;产生严重的后果与作者无关 前言介绍&#xff1a; 网络拓扑图&#xff1a; 为了方便起见&#xff0c;我在每个服务器放有webshell&#xff0c;这里主要是让我们熟悉sock代理的使用。 这…

修剪二叉搜索树

1题目 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除&#xff0c;原有的父代子代关系都应当…

10 常见网站安全攻击手段及防御方法

在某种程度上&#xff0c;互联网上的每个网站都容易遭受安全攻击。从人为失误到网络罪犯团伙发起的复杂攻击均在威胁范围之内。 网络攻击者最主要的动机是求财。无论你运营的是电子商务项目还是简单的小型商业网站&#xff0c;潜在攻击的风险就在那里。 知己知彼百战不殆&…

【一起撸个深度学习框架】6 折与曲的相会——激活函数

CSDN个人主页&#xff1a;清风莫追欢迎关注本专栏&#xff1a;《一起撸个DL框架》GitHub获取源码&#xff1a;https://github.com/flying-forever/OurDLblibli视频合集&#xff1a;https://space.bilibili.com/3493285974772098/channel/series 文章目录 6 折与曲的相会——激活…

史蒂夫·青木主题的 Game Jam

准备好潜入史蒂夫青木的脑海中&#xff0c;创造一个探索他内心思想的游戏吧&#xff01;史蒂夫青木主题 Game Jam 正式推出&#xff0c;这是一场为期两周的游戏制作比赛&#xff0c;鼓励参赛者创造和史蒂夫青木内心世界有关的游戏。 探索这位传奇艺术家和 DJ 潜意识&#xff0c…

nginx压测记录

nginx压测记录 1 概述2 原理3 环境3.1 设备与部署3.2 nginx配置/服务器配置 4 netty服务5 步骤6 结果7 写在最后 1 概述 都说nginx的负载均衡能力很强&#xff0c;最近出于好奇对nginx的实际并发能力进行了简单的测试&#xff0c;主要测试了TCP/IP层的长链接负载均衡 2 原理 …

Python 与数据科学实验(Exp9)

实验9 多分类手写数字识别实验 1.实验数据 &#xff08;1&#xff09;训练集 所给数据一共有42000张灰度图像&#xff08;分辨率为28*28&#xff09;&#xff0c;目前以train_data.csv文件给出. 图像内容涵盖了10个手写数字0-9。 图像示例如图所示&#xff1a; train_data.…

算法(一)—— 回溯(4)困难题

文章目录 1 37 解数独2 51 N 皇后 1 37 解数独 首先明确需要两个for循环&#xff0c;这样才可以遍历整个9*9的表。 此题数字的选取逻辑再次展现了回溯的暴力性。 此题需要拥有返回值&#xff0c;与数据结构&#xff08;六&#xff09;—— 二叉树&#xff08;5&#xff09;中…

物联网和云计算:如何将设备数据和云端服务相结合

第一章&#xff1a;引言 物联网和云计算是当今IT领域中的两个重要概念&#xff0c;它们的结合为企业和个人带来了巨大的机遇和挑战。物联网通过连接各种设备和传感器&#xff0c;实现了设备之间的互联互通&#xff0c;而云计算则提供了强大的计算和存储能力。本文将深入探讨如何…

MySQL学习(基础篇1.0)

MySQL概述&#xff08;基础&#xff09; SQL 全称Structured Query Language,结构化察浑语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库的统一标准。 SQL通用语法 SQL语言的统统用语法&#xff1a; SQL语句可以单行或多行书写&#xff0c;以分号…

论文阅读|基于图神经网络的配电网故障定位方法

来源&#xff1a;北京交通大学硕士学位论文&#xff0c;2022 摘要 电网拓扑形态多样&#xff0c;重构场景频繁&#xff0c;&#xff0c;传统故障定位方法的单一阈值设定无法满足要求&#xff0c;基于人工智能的配电网故障定位技术具有很大的应用潜力&#xff0c;但仍存在着拓…

HTML概述及常用语法

什么是 HTML HTML 用来描述网页的一种语言 HTML -- hyper text markup language 超文本标记语言 超文本包括&#xff1a;文字、图片、音频、视频、动画等等 标记语言&#xff1a;是一套标记标签&#xff0c; HTML 使用标记标签来 描述 网页 <> HTML 发展史 HTML5 …