MyBatis笔记梳理

文章目录

  • 什么是 MyBatis?
  • 前期准备
    • 依赖
    • 配置文件
    • mapper
    • 利用注解
  • 增、删、改、查
    • #{} 和 ${} 的区别
    • 类型别名
  • 动态sql
    • where if
    • foreach
    • sql引用
    • 不常用标签
  • 多表查询
    • 多对一(一对一)
    • 一对多
    • 多对多
    • 多表查询 个人理解
  • 延迟加载
    • 概念
    • 使用场景
    • 延迟加载配置
    • 延迟加载使用
    • 个人理解
  • 缓存技术
    • 测试一级缓存
    • 在这里插入图片描述
    • 在这里插入图片描述
    • 测试二级缓存
    • 二级缓存配置
    • 自定义缓存

什么是 MyBatis?

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

前期准备

依赖

        <!--mybatis核心包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>

配置文件

sqlMapConfig.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 配置环境们 -->
    <environments default="mysql">
        <!-- 配置具体的环境 -->
        <environment id="mysql">
            <!-- 配置事务管理类型 -->
            <transactionManager type="JDBC"/>
            <!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql:///mybatis_db"/>
                <property name="username" value="root"/>
                <property name="password" value="2552696563"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 加载映射的配置文件 -->
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>
</configuration>

或者用spring去整合
applicationContext.xml:

    <!-- jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///mybatis003
    jdbc.username=root
    jdbc.password=root -->
    <!--加载数据库参数文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--配置数据库交给spring管理-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${db.driverClassName}"></property>
        <property name="url" value="${db.url}"></property>
        <property name="username" value="${db.username}"></property>
        <property name="password" value="${db.password}"></property>
    </bean>

    <!--创建和数据库交互的工厂-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:sqlMapConfig.xml"></property>
    
    <!-- 扫描,不用在显式的写映射文件 -->
    </bean>
        <bean id="mapperScan" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <property name="basePackage" value="com.qcby.dao"></property>
    </bean>

mapper

通常我们将写 sql 的 xml 放在 resources/mapper 目录下。
一般一个 dao 对应一个 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="com.qcby.dao.UserDao">
    <!-- 这里写sql语句 -->
</mapper>

利用注解

基本不用,知道就可以。

public interface UserMapper {
    
    @Select("SELECT id, username, email FROM users WHERE id = #{id}")
    @Results({
        @Result(property = "userId", column = "id"),
        @Result(property = "userName", column = "username"),
        @Result(property = "emailAddress", column = "email")
    })
    User getUserById(int id);
}
<configuration>
    <mappers>
        <package name="com.qcby.dao"/>
        <!-- 其他 Mapper 的配置... -->
    </mappers>
</configuration>
  • @Select 注解用于指定查询语句。
  • #{userId} 是一个参数占位符,通过 @Param 注解指定了参数名称。

增、删、改、查

首先,基本是sql要会编写。

https://blog.csdn.net/Cosmoshhhyyy/article/details/133383339?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170666553716800215042990%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170666553716800215042990&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_ecpm_v1~rank_v31_ecpm-1-133383339-null-null.nonecase&utm_term=%E6%95%B0%E6%8D%AE%E5%BA%93&spm=1018.2226.3001.4450

假设有这么个类:
com.qcby.model.User:

public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    ......
}

public User findById(int id);
    <select id="findById" resultType="com.qcby.model.User" parameterType="int">
        select * from user where id = #{id};
    </select>
  • id 对应方法名字映射
  • parameterType 参数类型
  • resultType 返回值类型
  • #{id} 占位符对应传入的参数

public int insert(User user);
    <insert id="insert" parameterType="com.qcby.model.User">
      <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
          select last_insert_id();
      </selectKey>
        insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
    </insert>
  • selectKey 处理主键生成的元素,通常用于插入操作
  • order 有after before,这里是在插入之后查询插入生成的主键
  • select last_insert_id();

public int update(User user);
    <update id="update" parameterType="com.qcby.model.User">
        update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}
    </update>

public void delete(Integer userId);
    <delete id="delete" parameterType="int">
        delete from user where id = #{id};
    </delete>

#{} 和 ${} 的区别

#{} 占位符:

  • 语法是用于预处理 SQL 语句中的参数,MyBatis 会根据参数的类型和属性名安全地将参数插入 SQL 语句中。
  • 防止 SQL 注入攻击,因为 MyBatis 会使用预编译的方式将参数值传递给 SQL 引擎,而不是简单地拼接字符串。
  • 在 SQL 语句中的位置可以是任意合法的位置,比如在 WHERE 子句、SET 子句等。

${} 占位符:

  • 语法是用于将属性值直接插入 SQL 语句中,没有经过预处理。
  • 是简单的字符串替换拼接,可以用于替换表名、列名等静态部分。
  • 不提供防止 SQL 注入的保护,因此应谨慎使用,尽量避免直接使用用户输入的值。

类型别名

在sqlMapConfig加上:

    <typeAliases>
        <package name="com.qcby.model"/>
    </typeAliases>

这样我们parameterType 和 resultType中就不用写完整的路径
像 com.qcby.model.User 可以直接写错user

动态sql

假设有个类:

public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    private List<Integer> ids;
    ........

}

where if

根据用户名和性别进行模糊查询。

public List<User> findByIf(User user);
  <select id="findByIf" parameterType="user" resultType="user">
        select * from user
        <where>
            <if test="username != null and username != ''" >
                AND username like #{username}
            </if>
            <if test="sex != null and sex != ''">
                AND sex = #{sex}
            </if>
        </where>
    </select>
  • where 去掉1=1用的
  • test if的判断条件,写载where里
  • 里面不能使用 && || 要用 and or
  • 如果符合条件,拼接 if 标签中的内容
  • %熊% 用#{},熊 用’%${}%’

foreach

查询id 为 user里list ids中所有用户

public List<User> findByForeach(User user);
<!-- select * from user where id in (1, 2, 3, ...) -->
    <select id="findByForeach" parameterType="user" resultType="user">
        select * from user
        <where>
            <foreach collection="ids" open="id in (" close=")" separator="," item="i">
                #{i}
            </foreach>
        </where>
    </select>
  • collection 集合
  • open 以什么开头
  • close 以什么结尾
  • separator 以什么分割
  • item 循环中每个元素的别名
select * from user where id = 1 or id = 2 or id = 3 or id = 4

sql引用

使用 refid 的好处在于,它可以让你在多个地方重用相同的 SQL 片段,当 SQL 片段需要修改时,只需要修改一处,不用在多个地方做同样的修改,提高了配置的可维护性和可读性。

   <!--SQL-->
    <sql id="findAll">
        select * from user
    </sql>
    
    <!-- select * from user where .. -->
    <select id="findAll" resultType="com.qcby.model.User">
        <include refid="findAll" />
        <where>
            ......
        </where>
    </select>

例如:

<!-- 定义一个 SQL 片段 -->
<sql id="selectColumns">
    id, username, email
</sql>

<!-- 引用已定义的 SQL 片段 -->
<select id="getUserById" parameterType="int" resultType="User">
    SELECT
    <include refid="selectColumns"/>
    FROM users
    WHERE id = #{userId}
</select>

不常用标签

<choose>, <when>, <otherwise> 
<select id="selectUserByCondition" parameterType="User" resultType="User">
    SELECT * FROM users
    <where>
        <choose>
            <when test="username != null">
                AND username = #{username}
            </when>
            <when test="email != null">
                AND email = #{email}
            </when>
            <otherwise>
                AND status = 'ACTIVE'
            </otherwise>
        </choose>
    </where>
</select>
  • choose:定义一个选择块,其中包含多个 when 和一个可选的 otherwise。
  • when:用于定义条件成立时要执行的 SQL 片段。在上述例子中,如果 username 不为 null,则执行 AND username = #{username}。
  • otherwise:定义一个默认的 SQL 片段,当所有条件都不成立时执行。在上述例子中,如果 username 和 email 都为 null,则执行 AND status = ‘ACTIVE’。

<trim>
<select id="selectUsers" parameterType="Map" resultType="User">
    SELECT * FROM users
    <trim prefix="WHERE" prefixOverrides="AND | OR">
        <if test="username != null">
            AND username = #{username}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </trim>
</select>
  • prefix:可选属性,用于在 SQL 片段的前面添加一个字符串。
  • prefixOverrides:可选属性,用于指定要从 SQL 片段的开头删除的字符串。
  • suffix:可选属性,用于在 SQL 片段的末尾添加一个字符串。
  • suffixOverrides:可选属性,用于指定要从 SQL 片段的结尾删除的字符串。

可以用在set,update

<update id="updateUser" parameterType="User">
    UPDATE users
    <set>
        <trim suffixOverrides=",">
            <if test="username != null">
                username = #{username},
            </if>
            <if test="email != null">
                email = #{email}
            </if>
        </trim>
    </set>
    WHERE id = #{id}
</update>

多表查询

public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    ......
}
public class Account {

    private Integer id;
    private Integer uid;
    private Double money;
    ......
}

多对一(一对一)

多个账户 对应 一个用户
在多的一方添加对方属性
这里再acccount 添加 user 属性。

public class Account {

    private Integer id;
    private Integer uid;
    private Double money;
    private User user; // 这里
    ......
}

现在查询所有账户信息和其拥有者

public List<Account> findAll();
    <select id="findAll" resultMap="accountMap">
        select a.*,u.username,u.address from account a,user u where a.uid = u.id
    </select>
    <resultMap id="accountMap" type="com.qcby.model.Account">
        <result property="id" column="id" />
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <association property="user" javaType="com.qcby.model.User">
           <result property="username" column="username"/>
            <result property="address" column="address"/>
        </association>
    </resultMap>
  • resultMap 结果映射
  • property 指定java对象属性
  • column 查询出的结果中列名
  • association 处理关联关系

一对多

一个用户对应多个账号
在一的一方,加上多的一方的对象集合
这里user加上account的集合list

public class User {

    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    private List<Account> accounts; // 这里
    ......
}

查询所有用户及其所有账户金额

public List<User> findOneToMany();  
    <select id="findOneToMany" resultMap="userMap">
        select u.*,a.money from user u left join account a on u.id = a.uid
    </select>
    <resultMap id="userMap" type="com.qcby.model.User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="birthday" column="birthday"/>
        <result property="sex" column="sex"/>
        <result property="address" column="address"/>
        <collection property="accounts" ofType="com.qcby.model.Account">
            <result property="money" column="money"/>
        </collection>
    </resultMap>
  • collection 集合的封装
  • ofType 指定集合中元素类型

多对多

和一对多相同
在自己类上加上对方的集合
或者再对方上面加上自己的集合

例如有一个角色类, 一个用户有多个角色,一个角色可以有多个用户。

public class Role {

    private Integer id;
    private String role_name;
    private String role_desc;
    private List<User> users; // 这里
    .......
}

public List<Role> findAllRole();
    <select id="findAllRole" resultMap="roleMap">
          SELECT r.*,u.username FROM USER u,user_role ur,role r WHERE u.id = ur.UID AND ur.RID = r.ID
    </select>
    <resultMap id="roleMap" type="role">
        <result property="id" column="id"/>
        <result property="role_name" column="role_name"/>
        <result property="role_desc" column="role_desc"/>
        <collection property="users" ofType="user">
            <result property="username" column="username"/>
        </collection>
    </resultMap>

多表查询 个人理解

无非是两种方法:

  • 在自己类上加上对方类属性
  • 在自己类上加上对方类的集合

其实就是根据查询的角度来查询,和实际生活是对应的。

而数据库不会因为这个变化,比如无论是一对多、还是多对一,数据库都是多的一方把一的一方的主键作为外键。

而多对多都是建立再建立一个表。

我们的数据库结构从始至终都没有变化就可以印证这一点。所以不要弄混。

延迟加载

概念

延迟加载(Lazy Loading)是一种在对象关系映射(ORM)框架中常见的优化技术,用于提高性能并减少资源消耗。它的核心思想是:不在对象初始化时加载其关联的数据,而是在访问相关属性时才触发数据的加载。

延迟加载的优点:

  • 性能优化: 延迟加载可以减少初始化对象时的查询量,提高初始化速度。
  • 资源消耗: 可以避免加载不需要的关联数据,减少内存占用。

使用场景

  • 直接加载:多对一
  • 延迟加载:一对多

例如:
在查账户时,一个账户对应一个用户,可以直接把用户信息查出来,就用直接加载。

再查用户时,一个用户对应多个账户,可能我们用不到账户信息暂时,等用到的时候再去加载,就利用延迟加载。

延迟加载配置

    <settings>
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改为消极加载及按需加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

在这里插入图片描述

延迟加载使用

多对一:

    <!-- 查询所有账户 -->
    <select id="findAll" resultMap="accountMap">
        SELECT * from account
    </select>
    
    <!-- 通过用户的id查询账户信息 -->
    <select id="findByUid" parameterType="int" resultType="account">
        select * from account where uid = #{uid}
    </select>
    
    <!-- 映射 -->
    <resultMap type="Account" id="accountMap">
        <id property="id" column="id"/>
        <result property="uid" column="uid"/>
        <result property="money" column="money"/>
        <!-- 配置延迟加载 -->
        <association property="user" javaType="User" select="com.qcby.dao.UserMapper.findById" column="uid">
            <id property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="birthday" column="birthday"/>
            <result property="sex" column="sex"/>
            <result property="addresss" column="addresss"/>
        </association>
    </resultMap>
  • association 上的select 就是对应的select名字而已

一对多:

    <!-- 查询所有用户 -->
    <select id="findAll" resultMap="userMap">
        select * from user
    </select>
     
    <!-- 通过用户的id查询账户信息 -->
    <select id="findByUid" parameterType="int" resultType="account">
        select * from account where uid = #{uid}
    </select>

    <!-- 映射 -->
    <resultMap type="user" id="userMap">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="birthday" property="birthday"/>
        <result column="sex" property="sex"/>
        <result column="addresss" property="addresss"/>

        <collection property="accounts" ofType="Account" select="com.qcby.dao.AccountMapper.findByUid" column="id" >
            <id column="id" property="id"/>
            <result column="uid" property="uid"/>
            <result column="money" property="money"/>
        </collection>
    </resultMap>

个人理解

无非就是把我们之前写的多表查询中的collection 或则 association 对应的sql提取了出来,将select拆分成两个select, 单独设置了一个select方法,只有用到的时候才去调用。

当然多了一个column属性,作为拎出来的方法参数,例如多对一中的通过用户的id查询用户信息, 一对多中的通过账户的id查询账户信息

缓存技术

  • 一级缓存(Local Cache):
    一级缓存是 MyBatis 默认开启的本地缓存,它位于 SqlSession 的生命周期内,即在同一个 SqlSession 中执行的多个查询可以共享同一个缓存。一级缓存是基于对象引用的,当执行相同的查询语句时,MyBatis 会将查询结果缓存到一级缓存中。
    一级缓存的作用范围是 SqlSession,当 SqlSession 关闭时,缓存也会被清空。

  • 二级缓存(Global Cache):
    二级缓存是 MyBatis 的全局缓存,它可以被多个 SqlSession 共享。当多个 SqlSession 执行相同的查询语句时,MyBatis 将查询结果缓存到二级缓存中,下次相同的查询可以直接从缓存中获取结果。
    二级缓存的作用范围是整个应用程序,因此可以在不同的SqlSession 之间共享数据。

测试一级缓存

顺便讲一下测试方法如何写。
同一sqlSession下,调用两次findById:

  /**
     * 测试缓存
     * @throws Exception
     */
    @Test
    public void run5() throws Exception {
        // 加载配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        // 创建工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 构建session
        SqlSession session = factory.openSession();
        // 通过session创建rMapper接口的代理对象
        UserMapper mapper = session.getMapper(UserMapper.class);

        User user = mapper.findById(1); 
        System.out.println(user); // com.qcby.model.User@2a70a3d8
    
        User user2 = mapper.findById(1); 
        System.out.println(user2); // com.qcby.model.User@2a70a3d8
        session.close();
        in.close();
    }

在这里插入图片描述

不同sqlSession下,调用两次findById:

    /**
     * 测试缓存
     * @throws Exception
     */
    @Test
    public void run5() throws Exception {
        // 加载配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        // 创建工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 构建session
        SqlSession session = factory.openSession();
        // 通过session创建rMapper接口的代理对象
        UserMapper mapper = session.getMapper(UserMapper.class);

        User user = mapper.findById(1);
        System.out.println(user);

        session.close();
        SqlSession session2 = factory.openSession();
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user2 = mapper2.findById(1);
        System.out.println(user2);
        session2.close();
        in.close();
    }

在这里插入图片描述

可以发现,再同一session下,两次输出同一对象,而再不同session下,两次输出不同对象。

证明了一级缓存存在,且声明周期是随session。

测试二级缓存

二级缓存配置

mybatis配置文件中:

<!-- 开启二级缓存 -->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

要使用二级缓存的mapper中:

<!-- 配置二级缓存 -->
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
  • eviction 属性定义了缓存的清理策略,常用的有 LRU(最近最少使用)和 FIFO(先进先出)。
  • flushInterval 属性定义了刷新缓存的时间间隔,单位是毫秒。
  • size 属性定义了缓存的大小,超过这个大小时,将会触发清理操作。
  • readOnly 属性定义了是否只读,如果设置为 true,表示缓存中的数据不会被修改,可以提高性能。

注意实现对应类的序列化接口


    /**
     * 测试缓存
     * @throws Exception
     */
    @Test
    public void run5() throws Exception {
        // 加载配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
        // 创建工厂对象
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 构建session
        SqlSession session = factory.openSession();
        // 通过session创建rMapper接口的代理对象
        UserMapper mapper = session.getMapper(UserMapper.class);

        User user = mapper.findById(1);
        System.out.println(user);

        session.close();
        SqlSession session2 = factory.openSession();
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
        User user2 = mapper2.findById(1);
        System.out.println(user2);
        session2.close();
        in.close();
    }

在这里插入图片描述

自定义缓存

实现Cache接口:

package com.example;

import org.apache.ibatis.cache.Cache;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyCustomCache implements Cache {

    private final String id;
    private final Map<Object, Object> cache = new HashMap<>();
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    public MyCustomCache(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        readWriteLock.writeLock().lock();
        try {
            cache.put(key, value);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    @Override
    public Object getObject(Object key) {
        readWriteLock.readLock().lock();
        try {
            return cache.get(key);
        } finally {
            readWriteLock.readLock().unlock();
        }
    }

    @Override
    public Object removeObject(Object key) {
        readWriteLock.writeLock().lock();
        try {
            return cache.remove(key);
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    @Override
    public void clear() {
        readWriteLock.writeLock().lock();
        try {
            cache.clear();
        } finally {
            readWriteLock.writeLock().unlock();
        }
    }

    @Override
    public int getSize() {
        return cache.size();
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }
}

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

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

相关文章

Emmet常用语法总结

Emmet常用语法总结 子元素&#xff1a;>兄弟元素&#xff1a;上级元素&#xff1a;^倍数&#xff1a;*分组&#xff1a;&#xff08;&#xff09;属性&#xff1a;[]id和类&#xff1a;# .迭代数字&#xff1a;$文本内容&#xff1a;{}注意事项 Emmet是许多流行文本编辑器的…

Linux下find命令详解

find #查找文件 #按照文件名、大小、时间、权限、类型、所属者、所属组来搜索文件 格式&#xff1a; find 查找路径 查找条件 具体条件&#xff08;按文件名或时间大小等&#xff09; 操作 注意&#xff1a; find命令默认的操作是print输出 find是检索…

【Springcloud篇】学习笔记二(四至六章):Eureka、Zookeeper、Consul

第四章_Eureka服务注册与发现 1.Eureka基础知识 1.1Eureka工作流程-服务注册 1.2Eureka两大组件 2.单机Eureka构建步骤 IDEA生成EurekaServer端服务注册中心&#xff0c;类似于物业公司 EurekaClient端cloud-provider-payment8081将注册进EurekaServer成为服务提供者provide…

【学员分享-考试心得】国产数据库潜力无限,云贝教育OBCP认证培训帮您解难题

近年来&#xff0c;随着国产化转型的推进&#xff0c;国外数据库的岗位需求逐渐减少&#xff0c;让许多IT从业者倍感压力。在这种情况下&#xff0c;了解国产数据库成为了求职市场上的竞争力。云贝老师们将聚焦于OceanBase、PostgreSQL、TDSQL等IT培训&#xff0c;探讨其对国产…

如何计算模型的复杂度(参数量,FLOPs)

参考 如何计算神经网络模型的复杂度 深度学习卷积、全连接层、深度可分离层参数量和FLOPs计算公式 概念 Params&#xff1a;模型的参数量。&#xff08;空间复杂度&#xff09;FLOPs&#xff1a;FLoating point Operations&#xff0c;前向推理的计算量。&#xff08;时间复…

Loadbalancer如何优雅分担服务负荷

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Loadbalancer如何优雅分担服务负荷 前言Loadbalancer基础&#xff1a;数字世界的分配大师1. 分发请求&#xff1a;2. 健康检查&#xff1a;3. 会话保持&#xff1a;4. 可伸缩性&#xff1a;5. 负载均衡…

hivesql的基础知识点

目录 一、各数据类型的基础知识点 1.1 数值类型 整数 小数 float double(常用) decimal(针对高精度) 1.2 日期类型 date datetime timestamp time year 1.3 字符串类型 char varchar / varchar2 blob /text tinyblob / tinytext mediumblob / mediumtext lon…

2024年美国大学生数学建模竞赛(F题)减少非法野生动物贸易|ABM/神经网络建模解析,小鹿学长带队指引全代码文章与思路

我是鹿鹿学长&#xff0c;就读于上海交通大学&#xff0c;截至目前已经帮200人完成了建模与思路的构建的处理了&#xff5e; 本篇文章是鹿鹿学长经过深度思考&#xff0c;独辟蹊径&#xff0c;通过Agent-Based Modeling解决非法野生动植物贸易问题。结合神经网络、集成学习、贝…

前端工程化之:webpack1-13(内置插件)

目录 一、内置插件 1.DefinePlugin 2.BannerPlugin 3.ProvidePlugin 一、内置插件 所有的 webpack 内置插件都作为 webpack 的静态属性存在的&#xff0c;使用下面的方式即可创建一个插件对象&#xff1a; const webpack require("webpack")new webpack.插件…

影院购票|电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序目录 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户功能实现 2、管理员功能实现 &#xff08;1&#xff09;影院信息管理 &#xff08;2&#xff09;电影信息管理 &#xff08;3&#xff09;已…

电源芯片并联使用-AMS1117

自记&#xff1a; 电源芯片可不可以并联使用&#xff1a; 1.按照正规大厂Rohm的技术文档介绍&#xff0c;直接并联的两个LDO&#xff0c;只要其输出电压有很小的差异&#xff0c;就会造成电流分配的很大差异。 至于你长期使用没有发现问题&#xff0c;那可能是总电流的余量留…

蓝桥杯---煤球数目

有一堆煤球,堆成三角棱锥形。具体: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形), 如果一共有100层,共有多少个煤球? 请填表示煤球总数目的数字. 注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字. 代码 pu…

Ingress

文章目录 环境准备什么是 Ingress认识 Ingress 资源Ingress 控制器(controller)Ingress 规则pathType 路径类型多重匹配Ingress 类TLS生成证书创建密钥 环境准备 下面的 yaml 文件内容&#xff0c;是使用 sts 创建两个 web 服务&#xff0c;并配置对应的 servcie。web 服务的首…

【JavaScript】前端攻击

前端攻击 1. CSRF的基本概念、缩写、全称 CSRF&#xff08;Cross-site request forgery&#xff09;&#xff1a;跨站请求伪造。 从上图可以看出&#xff0c;要完成一次CSRF攻击&#xff0c;受害者必须满足两个必要的条件&#xff1a; 登录受信任网站A&#xff0c;并在本地生…

【疑问】为什么声明和定义要分离

前言 我们在学习的时候接触过一个话&#xff1a;编写自定义函数的时候 要做到声明和定义分离 那么为什么呢 今天就来简单的了解一下 疑问&#xff1a;错误的发生 下面给出两个源文件和一个头文件以及报错信息 text.cc文件 #include"head.h"int main() {int a 1…

深入理解指针(3)

⽬录 1. 字符指针变量 2. 数组指针变量 3. ⼆维数组传参的本质 4. 函数指针变量 5. 函数指针数组 6. 转移表 1. 字符指针变量 在指针的类型中我们知道有⼀种指针类型为字符指针 char* ; ⼀般使⽤: int main() {char ch w;char *pc &ch;*pc w;return 0; } 还有…

C++类和对象入门(二)

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、类的作用域 类定义了一个新的作用域&#xff0c;类的所有成员都在类的作用域中。在类体外定义成员时&#xff0c;需要…

云服务器安全组、防火墙、端口问题,结合telnet解决项目部署无法访问

无论是运维还是后台亲自操刀在云服务器上部署项目&#xff0c;往往会遇到项目部署上去了&#xff0c;也确定项目正常运行&#xff0c;但还是没法访问的问题。 如果没有经验的小伙伴&#xff0c;很容易陷入疑惑的状态&#xff0c;无从下手解决。 其实这涉及到云平台安全组、服…

idea创建sping项目

一、环境 window10 IDEA 2022.2.3 maven-3.8.6 二、创建sping项目 1、新建Maven项目 File -> New -> Project 然后如下图选中Maven Archetype&#xff0c;在Archetype&#xff0c;选中maven-archetype-webapp&#xff0c;点击Create 2、配置maven 默认是使用IDEA内置…
最新文章