MyBatis——Java 持久层框架

文章目录

  • MyBatis 是什么
  • 准备工作
    • 创建一个数据库和表
    • 引入依赖
  • 配置连接字符串和 MyBatis
  • MyBatis 组成
  • MyBatis 使用步骤
    • 定义一个类
    • 创建 MyBatis 接口(以查询所有为例)
    • 创建与接口对应的 xml 文件(实现接口中的所有方法)
    • 使用单元测试进行验证
    • 查询单条记录
    • 增加数据
    • 修改和删除
  • \#{} 和 ${} 的区别
  • like 查询
  • resultMap
  • 动态 SQL
    • `<if>`
    • `<trim>`
    • `<where>`
    • `<set>`
    • `<foreach>`

MyBatis 是什么

  • 是一款持久层框架
  • 基于 JDBC
  • 可以通过方便的设置实现数据库操作

Mybatis(之前称为 iBatis)也是一个 ORM 框架,ORM(Object Relational Mapping),即对象关系映射。

ORM 把数据库映射为对象:

  • 数据库表(table)–>类(class)
  • 记录(record,行数据)–>对象(object)
  • 字段(field)–>对象的属性(attribute)

准备工作

创建一个数据库和表

create database mycnblog default character set utf8mb4;

use mycnblog;

create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime datetime default now(),
    updatetime datetime default now(),
    `state` int default 1
) default charset 'utf8mb4';

insert into userinfo values(1, 'admin', '123', '', '2023-12-10 10:09:30', '2023-12-10 10:09:30', 1);

引入依赖

MyBatis Framework 和 MySQL Driver

引入之后,我们的项目是启动不了的,还需要进行配置。

配置连接字符串和 MyBatis

配置 application.yml,指定要连接的数据库在哪

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

如果 mysql-connector-java 是5.x 之前的使用的是 com.mysql.jdbc.Driver,之后的使用的是 com.mysql.cj.jdbc.Driver

指定 MyBatis 在哪里查找映射器(Mapper)的 XML 文件:

在 MyBatis 中,Mapper 文件定义了 SQL 映射和与数据库的交互。

mybatis:
  mapper-locations: classpath:mapper/**Mapper.xml

img

classpath:mapper/**Mapper.xml:表示在类路径(classpath)下的 mapper 目录中查找所有以 Mapper.xml 结尾的文件。

** 是通配符,它和 * 的区别是:

  • ** 包括子目录,可以递归匹配多级子目录。
  • * 不包括子目录,只匹配当前目录下的文件。

如果想看 MyBatis 最终执行的 SQL 语句,还可以进行如下配置:

mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

完成上述操作,启动项目,如果可以启动,就说明我们的环境配置完成了。


MyBatis 组成

MyBatis 主要由两部分组成:

  1. 接口(Mapper 接口): MyBatis 的接口用于定义数据库操作的方法。每个接口方法通常对应一个数据库操作,比如查询、插入、更新或删除数据。这些接口方法的签名定义了输入参数和返回类型,而实际的 SQL 查询则是通过 XML 文件或注解来配置的。
  2. XML 文件(Mapper XML 文件): MyBatis 的 XML 文件用于存放 SQL 映射配置,即将接口方法与实际的 SQL 语句进行关联。XML 文件中包含了数据库操作的具体 SQL 语句,以及输入参数和输出结果的映射关系。每个 Mapper 接口通常对应一个同名的 XML 文件。

MyBatis 使用步骤

定义一个类

这个类的属性名和数据库表中的字段名一致

package org.example.mybatisdemo.model;

import lombok.Data;

import java.util.Date;

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private Date createtime;
    private Date updatetime;
    private int state;
}

创建 MyBatis 接口(以查询所有为例)

@Mapper 注解是 MyBatis 框架中用于标识一个接口为 MyBatis 映射器(Mapper)的注解。

当你在一个接口上使用 @Mapper 注解时,MyBatis 将会扫描这个接口,并为其创建一个实现类,用于执行与数据库相关的 SQL 操作。

Spring 将会在运行时为这个接口生成代理对象,使其可以被注入到其他组件中

package org.example.mybatisdemo.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.example.mybatisdemo.model.UserInfo;

import java.util.List;

@Mapper // 此注解表示这是一个 mybatis 接口
public interface UserMapper {
    List<UserInfo> getAll();
}

创建与接口对应的 xml 文件(实现接口中的所有方法)

img

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="">
    
</mapper>

namespace 里填要实现的接口的路径。

例:mapper 里面添加 select 标签,表示要实现查询方法,id 指定实现的方法名(和接口中的一致),result 指定返回的记录的类型,标签内部填写具体的 sql 语句

<?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="org.example.mybatisdemo.mapper.UserMapper">
    <select id="getAll" resultType="org.example.mybatisdemo.model.UserInfo">
        select * from userinfo
    </select>
</mapper>

使用单元测试进行验证

在要测试的代码上右键,选择 Generate->Test

img

生成的测试类会进入到 test 目录下面

设置当前测试环境为 SpringBoot,并注入要测试的类:

package org.example.mybatisdemo.mapper;

import org.example.mybatisdemo.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;

@SpringBootTest // 当前测试的上下文环境为SpringBoot
class UserMapperTest {
    @Autowired // 注入要测试的类
    private UserMapper userMapper;

    @Test // 测试
    void getAll() {
        List<UserInfo> list = userMapper.getAll();
        for (UserInfo user : list) {
            System.out.println(user.toString());
        }
    }
}

运行测试方法,查看测试结果:

UserInfo(id=1, username=admin, password=123, photo=, createtime=Sun Dec 10 10:09:30 HKT 2023, updatetime=Sun Dec 10 10:09:30 HKT 2023, state=1)

查询单条记录

查询单条记录需要提供参数,供 where 语句使用。

在抽象方法的参数列表中,用 @Param 注解指定传递给 SQL 语句的参数名

@Mapper // 此注解表示这是一个 mybatis 接口
public interface UserMapper {
    List<UserInfo> getAll();

    UserInfo getUserById(@Param("id") Integer id);
}

在 XML 映射文件中,可以使用 #{id} 来引用方法参数。

<select id="getUserById" resultType="org.example.mybatisdemo.model.UserInfo">
    select * from userinfo where id = #{id}
</select>

注:@Param("id") 也可以省略,通常建议写上。

测试:

@Test
void getUserById() {
    UserInfo userInfo = userMapper.getUserById(1);
    System.out.println(userInfo);
}

增加数据

@Mapper // 此注解表示这是一个 mybatis 接口
public interface UserMapper {
    List<UserInfo> getAll();

    UserInfo getUserById(@Param("id") Integer id);

    int add(UserInfo userInfo); // 传入的是对象,不加 @Param 注解
}

xml 文件中使用 insert 标签,直接用 #{属性名} 来获取对象中的属性:

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

如果传入对象的时候加了 @Param 注解,如:

int add(@Param("userInfo") UserInfo userInfo);

那么 xml 获取属性的时候,必须要使用 .

<insert id="add">
    insert into userinfo(username, password)
    values (#{userInfo.username}, #{userInfo.password})
</insert>

测试:

@Test
void add() {
    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("zhangsan");
    userInfo.setPassword("123");
    int effect = userMapper.add(userInfo);
    System.out.println("影响的行数:" + effect);
}

增加数据的时候返回自增主键

在 insert 标签属性中添加 useGeneratedKeys=“true” keyProperty=“id”

<insert id="add" useGeneratedKeys="true" keyProperty="id">
  • useGeneratedKeys="true":这个属性用于指定是否使用数据库自动生成的主键。当设置为 true 时,表示插入数据后,将从数据库获取生成的主键值,并将其设置到相应的属性中。
  • keyProperty="id":如果 useGeneratedKeys 设置为 true,则需要使用 keyProperty 属性指定将生成的主键值设置到哪个 Java 对象的属性中。在这个例子中,表示将生成的主键值设置到 Java 对象的 id 属性中。

测试:

@Test
void add() {
    UserInfo userInfo = new UserInfo();
    userInfo.setUsername("zhangsan");
    userInfo.setPassword("123");
    int effect = userMapper.add(userInfo);
    System.out.println("影响的行数:" + effect + " id: " + userInfo.getId());
}
// 输出:影响的行数:1 id: 3

修改和删除

在 xml 中分别使用的是 update 标签和 delete 标签,除此以外,其他的关于 MyBatis 的操作都和查询、增加一样,这里不再赘述。

#{} 和 ${} 的区别

#{} 和 ${} 在构造 SQL 语句的方式上存在差异:

  1. #{} 表达式(预编译):
    • #{} 表达式是 MyBatis 中用于预编译参数的占位符。这种方式会在 SQL 语句中使用占位符 ?,然后通过预编译的方式向 SQL 语句中传递参数。这样可以有效防止 SQL 注入攻击。
  2. ${} 表达式(字符串拼接):
    • ${} 表达式是用于字符串拼接的方式。在 SQL 语句中,${} 会直接替换成参数的字符串表示形式,不会进行预编译。

预编译的方式具有以下优点:

  1. 参数类型校验: 预编译时数据库引擎能够获取到参数的类型信息,可以对参数进行类型校验。如果传递给数据库的参数类型与预期的类型不匹配,数据库引擎通常会拒绝执行。
  2. 转义处理: 预编译会对参数值进行转义处理,确保特殊字符不会破坏 SQL 语句的结构。这有助于防止恶意构造的参数值破坏 SQL 查询语句。

绝大部分场景都是使用 #{} ,但是也有部分场景适合使用 ${}

比如我要传递的参数是 SQL 中的关键字,比如 asc 和 desc

<select id="getAllByOrder" resultType="org.example.mybatisdemo.model.UserInfo">
    select * from userinfo order by ${order}
</select>

如果使用 #{} 则会将关键字识别成字符串,在最终生成的 SQL 语句中画蛇添足地增加 '',比如 select * from userinfo order by 'desc' 导致 SQL 语法错误。直接使用 ${} 字符串拼接的方式就简便很多。

而且我们可以在代码中 if 判断,保证传入的参数只能是 asc 和 desc,从而防止 SQL 注入。

like 查询

模糊查询获取参数也必须用 #{} ,不能用 ${} 因为传入的参数是无法穷举的,有 SQL 注入的风险。

#{} 会画蛇添足,和通配符 % _ 配合使用不太方便。

<select id="searchUsers" resultType="org.example.mybatisdemo.model.UserInfo">
    select * from userinfo
    where username like '%#{pattern}%'
</select>

以上代码最后构造的 SQL 语句形如 select * from userinfo where username like '%'s'%'

解决方法:

要么写成下面的形式,% 直接通过 Java 代码传入:

<select id="searchUsers" resultType="org.example.mybatisdemo.model.UserInfo">
    select * from userinfo
    where username like #{pattern}
</select>

Java 代码:

List<UserInfo> list = userMapper.searchUsers("%s%");

这样自动添加 '' 后就正确了。

要么使用 concat:

<select id="searchUsers" resultType="org.example.mybatisdemo.model.UserInfo">
    select * from userinfo
    where username like concat('%', #{pattern}, '%')
</select>

Java 代码:

List<UserInfo> list = userMapper.searchUsers("s");

resultMap

resultMap 是一种用于映射查询结果集的配置元素。它允许你定义一个映射规则,将数据库查询结果的列映射到 Java 对象的属性中。

简单来说,这种方式可以让 Java 代码中的类的属性名,和数据库中的字段名在不一致的情况下也能一一对应。

<resultMap id="userResultMap" type="org.example.mybatisdemo.model.UserInfo">
    <id property="id" column="user_id"/>
    <result property="username" column="user_name"/>
    <result property="password" column="user_password"/>
    <!-- 其他属性的映射... -->
</resultMap>
  • id 元素用于定义主键映射,property 指定了 Java 对象中的属性名,column 指定了数据库结果集中的列名。
  • result 元素用于定义其他属性的映射规则。
<select id="getUserById" resultMap="userResultMap">
    select * from users where user_id = #{userId}
</select>

getUserById 查询将使用名为 userResultMapresultMap 进行结果映射。MyBatis 将查询结果中的列按照 resultMap 中定义的映射规则进行映射,从而创建一个包含查询结果的 Java 对象。

动态 SQL

动态 SQL 是指在 SQL 语句中根据不同的条件或参数动态生成不同的 SQL 片段的技术。在 MyBatis 中,动态 SQL 主要通过使用 <if>、<choose>、<when>、<otherwise>、<trim>、<where>、<set> 等 XML 元素来实现。

<if>

<if> 标签用于在 SQL 语句中根据条件动态包含或排除某段 SQL 语句。

基本的 <if> 标签语法如下:

<if test="condition">
    <!-- 要包含的 SQL 语句片段 -->
</if>

test 属性用于指定一个条件表达式,如果条件表达式为真,那么 <if> 内部定义的 SQL 语句片段将会被包含在最终的 SQL 语句中。如果条件表达式为假,则这部分 SQL 语句将被忽略。

例子:

<select id="getUserByCondition" resultType="User">
    SELECT * FROM users
    <where>
        <if test="username != null and username != ''">
            AND username = #{username}
        </if>
        <if test="password != null and password != ''">
            AND password = #{password}
        </if>
    </where>
</select>

<trim>

<trim> 标签,用于在生成 SQL 语句时处理多余的空白字符,同时可以根据条件来动态添加或移除 SQL 片段的开头或结尾。

<trim> 元素的基本语法结构如下:

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
    <!-- SQL 语句片段 -->
</trim>
  • prefix 属性用于指定在 SQL 语句片段前添加的内容。
  • prefixOverrides 属性用于指定需要从 SQL 语句片段开头移除的前缀,可以是逗号分隔的前缀列表。
  • suffix 属性用于指定在 SQL 语句片段后添加的内容。
  • suffixOverrides 属性用于指定需要从 SQL 语句片段结尾移除的后缀,可以是逗号分隔的后缀列表。

示例:

<select id="getUserByCondition" resultType="User">
    select * from users
    <trim prefix="where" prefixOverrides="and | or">
        <if test="username != null and username != ''">
            and username = #{username}
        </if>
        <if test="password != null and password != ''">
            or password = #{password}
        </if>
    </trim>
</select>

在这个例子中,<trim> 元素的作用是处理 WHERE 子句,根据动态条件来生成合适的查询语句。具体解释如下:

  • prefix="where" 指定了在 SQL 语句片段前添加的内容,即添加了 where
  • prefixOverrides="and | or" 指定了需要从 SQL 语句片段开头移除的前缀,即移除了可能出现的多余的 andor
  • <trim> 元素内部,根据动态条件使用 <if> 元素生成相应的查询条件。

假设在执行这个查询时,传入的参数是 username="John"password=null,最终生成的 SQL 语句会是:

select * from users
where
    username = 'John'

<where>

<where> 标签用于在 where 子句中动态生成条件。<where> 元素会自动处理生成的条件之间的逻辑关系,避免不必要的 and 或 or 连接符。

基本的 <where> 标签语法如下:

<select id="getUserByCondition" resultType="User">
    SELECT * FROM users
    <where>
        <!-- 动态生成的条件 -->
    </where>
</select>

其示例在 if 标签已经涉及到。

例:

<select id="selectUsers" resultType="User">
  SELECT * FROM users
  <where>
    <if test="name != null">
      AND name = #{name}
    </if>
    <if test="age != null">
      AND age = #{age}
    </if>
    <!-- 可以根据需要添加更多的条件 -->
  </where>
</select>

假设传入的参数是 name = 'John'age = 25,生成的 SQL 语句将类似于:

SELECT * FROM users
WHERE
  name = 'John'
  AND age = 25;

如果只传入了 name = 'John',而没有传入 age 参数,生成的 SQL 语句将是:

SELECT * FROM users
WHERE
  name = 'John';

如果两个条件都没有被传入,生成的 SQL 语句将仅包含基本的 SELECT 语句,而不包含 WHERE 子句:

SELECT * FROM users;

where 标签更简单地完成了上面 trim 标签的例子

<set>

<set> 元素针对 update 语句。它主要用于处理动态更新表中的列,根据传入的参数动态生成 set 子句。<set> 元素可以使得在更新记录时只更新传入的非空字段,从而避免更新所有字段,提高了 SQL 语句的灵活性。

例子:

<update id="updateUser">
  UPDATE users
  <set>
    <if test="name != null">
      name = #{name},
    </if>
    <if test="age != null">
      age = #{age},
    </if>
    <!-- 可以根据需要添加更多的更新字段 -->
  </set>
  WHERE id = #{id}
</update>

例如,如果调用上述的更新方法时传入了 name = 'John'age = 25,生成的 SQL 语句将类似于:

UPDATE users
SET
  name = 'John',
  age = 25
WHERE id = #{id};

如果只传入了 name = 'John' 而没有传入 age 参数,生成的 SQL 语句将是:

UPDATE users
SET
  name = 'John'
WHERE id = #{id};

<foreach>

<foreach> 通常用于动态生成 SQL 语句中的 IN 子句,允许我们在查询或更新操作中使用一组值。<foreach> 主要用于遍历集合或数组,并根据集合中的元素动态生成相应的 SQL 片段。

例子:

<select id="selectUsersByIds" resultType="User" parameterType="java.util.List">
  SELECT * FROM users
  WHERE id IN
  <foreach collection="ids" item="id" open="(" separator="," close=")">
    #{id}
  </foreach>
</select>

在上述例子中,<foreach> 元素用于循环遍历传入的 ids 集合,并根据集合中的元素动态生成 IN 子句。其中,collection 属性指定了要迭代的集合,item 属性指定了集合中的元素变量名,open 属性定义了 IN 子句的开头,separator 属性定义了元素之间的分隔符,close 属性定义了 IN 子句的结尾。

例如,如果传入的 ids 集合为 [1, 2, 3],生成的 SQL 语句将类似于:

SELECT * FROM users
WHERE id IN (1, 2, 3);

<foreach> 元素也可以用于其他操作,比如在插入操作中批量插入数据。下面是一个简单的插入示例:

<insert id="insertUsers" parameterType="java.util.List">
  INSERT INTO users (name, age)
  VALUES
  <foreach collection="list" item="user" separator="," >
    (#{user.name}, #{user.age})
  </foreach>
</insert>

<foreach> 元素用于循环遍历传入的 list 集合,并根据集合中的元素动态生成插入语句。这种方式可以在一次数据库操作中插入多条记录,提高了效率。

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

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

相关文章

[面试题~k8s] 云原生必问基础篇

文章目录 概念篇1. k8s 是什么2. Container3. Pod4. Node5. Namespace6. Service7. Label8. Replica Set&#xff08;副本集)9. Deployment10. Volume11. Namespace12. PV 和 PVC 基础篇1. 删除 pod 流程2. k8s 有哪些组件master nodeworker node 3. k8s 和 docker 的关系4. 简…

Java网络编程——通过JDBC API访问数据库

关系数据库仍然是目前最流行的数据库系统。如果没有特别说明&#xff0c;本帖所说的数据库就都指关系数据库。关系数据库中最主要的数据结构是表&#xff0c;表用主键来标识每一条记录&#xff0c;表与表之间可以存在外键参照关系。数据库服务器提供管理数据库的各种功能&#…

shell条件测试

1.1.用途 为了能够正确处理Shell程序运行过程中遇到的各种情况&#xff0c;Linux Shell提供了一组测试运算符. 通过这些运算符&#xff0c;shell程序能够判断某种或者几个条件是否成立。 条件测试在各种流程控制语句&#xff0c;例如判断语句和循环语句中发挥了…

平台工程文化:软件开发的创新路径和协作之道

在快速发展的软件开发领域&#xff0c;具有前瞻性思维的企业组织正在拥抱平台工程文化的变革力量。这种创新方法强调创建共享平台、工具和实践&#xff0c;使开发人员能够更快、更高效地交付高质量的软件。在本文中&#xff0c;我们将深入探讨平台工程文化的核心原则和深远的好…

Java网络编程——基础入门

1、进程间的通信 进程指运行中的程序&#xff0c;进程的任务就是执行程序中的代码。EchoPlayer类是一个独立的Java程序&#xff0c;它可以在任意一台安装了JDK的主机上运行&#xff1a; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStr…

Finereport基于linux的简单安装(单节点)

简介 本文以单节点简单部署为例&#xff0c;不适用企业级高可用部署策略。 FineReport的运行依赖于Tomcat &#xff0c;Tomcat 是免费且性能相对稳定的 Web 应用服务器,也可以充当JSP容器。它是一个用于运行Java Servlet和JavaServer Pages&#xff08;JSP&#xff09;的Web服务…

Eclipse 4.30 正式发布 来看看有哪些值得期待的新特性

Eclipse 4.30 已正式发布&#xff0c;主要特性如下&#xff1a; 1、支持新的 Java 语言特性&#xff1a;包括 JEP 440: Record Patterns 和 JEP 441: Pattern Matching for Switch 2、针对 Java 编辑器的快速修复功能&#xff1a;包括添加默认 case、移除默认 case 和插入 br…

报道 | 2023年1月-2024年3月国际运筹优化会议汇总

2023年1月-2024年3月召开会议汇总&#xff1a; SIAM Symposium on Algorithm Engineering and Experiments 2024 Location: Alexandria, VA, United States Important dates: Conference: January 7, 2024 - January 8, 2024 Details: https://www.siam.org/conferences/cm…

模电·放大电路的分析方法——等效电路法

放大电路的分析方法——等效电路法 晶体管的直流模型及静态工作点的估算法晶体管共射h参数等效模型 h h h参数等效模型的由来参数的物理意义简化的h参数等效模型 r b e {r\tiny be} rbe的近似表达式 共射放大电路动态参数的分析电压放大倍数 A ˙ u \.{A}\tiny u A˙u输入电阻 …

CrystalDiskInfo中文版(硬盘检测工具) v9.1.1.0 绿色汉化版-供大家学习研究参考

更新内容 重新支持三星SATA SSD寿命报告 增加对ZHITAI SC001的支持 新增SK hynix Gold S31支持 增加了KLEVV NEO N610的支持。 改进的Micron/Crucial SATA SSD支持 已更改 卸载程序将显示一个确认对话框&#xff0c;用于删除设置。 强大功能 1.拥有多国语言&#xff0c;…

curl 18 HTTP/2 stream

cd /Users/haijunyan/Desktop/CustomKit/KeepThreadAlive/KeepThreadAlive //Podfile所在文件夹 git config --global https.postBuffer 10485760000 git config --global http.postBuffer 10485760000 pod install https://blog.csdn.net/weixin_41872403/article/details/86…

全网最新最全【Kali Linux】 渗透测试技术大全

利矛出击&#xff1a;Kali Linux 渗透测试大法 在网络攻防实践中&#xff0c;系统的防御措施可以称为“盾”&#xff0c;而渗透测试则是“矛”。二者同等重要&#xff0c;因为“矛”可以试探出“盾”有多坚固&#xff0c;并且及时发现问题&#xff0c;修补漏洞&#xff0c;提升…

苍穹外卖项目笔记(8)— 缓存商品、购物车功能

前言 代码链接&#xff1a; Echo0701/take-out⁤ (github.com) 1 缓存菜品 1.1 问题说明 【注】很多时候系统性能的瓶颈就在于数据库这端 1.2 实现思路 通过 Redis 来缓存数据&#xff0c;减少数据库查询操作 【注】Redis 基于内存来保存数据的&#xff0c;访问 Redis 数据…

多任务学习(Multi-Task Learning)和迁移学习(Transfer Learning)的详细解释以及区别(系列1)

文章目录 前言一、多任务学习&#xff08;Multi-Task Learning&#xff09;是什么&#xff1f;二、多任务学习&#xff08;Multi-Task Learning&#xff09;对数据的要求三、迁移学习是什么&#xff1f;四&#xff0c;迁移学习对数据的要求五&#xff0c;多任务学习与迁移学习的…

正则表达式(8):基本正则表达式小结

正则表达式&#xff08;8&#xff09;&#xff1a;基本正则表达式小结 本博文转载自 写这篇文章的目的就是总结前文中所介绍的”基本正则表达式”&#xff0c;并且结合一些实例进行练习&#xff0c;以便我们能够在练习中完全掌握它们。 首先&#xff0c;我们对前文中提到的符…

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解前言DenseNet讲解Dense Block(稠密块)Dense Layer(稠密层)Transition Layer 过渡层DenseNet模型结构 DenseNet Pytorch代码完整代码附加…

蛋白质语言空间下的对比学习预测DTI

基于序列的DTI预测可以加速药物发现。而这种计算预测需要具有通用性和可扩展性&#xff0c;同时对输入中的细微变化保持敏感。然而&#xff0c;目前的计算技术不能同时满足这些目标。因此该研究开发了ConPLex&#xff0c;成功地利用了预训练蛋白质语言模型&#xff08;PLex&…

基于JavaWeb+SSM+Vue实习记录微信小程序系统的设计和实现

基于JavaWebSSMVue实习记录微信小程序系统的设计和实现 源码获取入口Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 Lun文目录 目 录 摘 要 III Abstract 1 1 系统概述 1 1.1 概述 2 1.2课题意义 3 1.3 主要内…

vue常用的修饰符

一、定义 修饰符是用于限定类型以及类型成员的声明的一种符号&#xff0c;vue中修饰符分为以下五种&#xff1a;表单修饰符、事件修饰符、鼠标按键修饰符、键值修饰符、v-bind修饰符 二、作用 1.表单修饰符 lazy&#xff1a;在我们填完信息&#xff0c;光标离开标签的时候&a…

cache教程 3.HTTP服务器

上一节我们实现了单机版的缓存服务&#xff0c;但是我们的目标是分布式缓存。那么&#xff0c;我们就需要把缓存服务部署到多态机器节点上&#xff0c;对外提供访问接口。客户端就可以通过这些接口去实现缓存的增删改查。 分布式缓存需要实现节点间通信&#xff0c;而通信方法…