主頁 > 後端開發 > mybatis 框架學習筆記

mybatis 框架學習筆記

2020-10-30 23:08:08 後端開發

目錄
  • 自定義持久層框架
    • jdbc 代碼基礎回顧
      • 解決傳統jdbc存在的問題
    • 自定義持久層框架設計思路
      • 使用端 --> 專案
    • 自定義持久層框架本身
    • mybatis 簡介
      • sqlMapConfig.xml 節點說明
      • 傳統dao層開發方式
      • dao層開發方式
      • mybatis 外部properties 檔案
      • mybatis aliasType
      • mapper.xml
        • 動態sql
      • mybatis復雜映射開發
        • 一對一查詢
        • 一對多查詢
        • 多對多查詢
    • mybatis 注解開發
      • 注解一對多
      • 注解多對多
      • mybatis 快取
        • 一級快取
        • 一級快取分析
        • 二級快取
      • redis-cache 分析
      • mybatis的插件
        • 以上組件的創建原理
        • 自定義mybatis 插件
        • mybatis的第三方插件
      • mybatis架構原理
        • mybatis傳統方式原始碼分析
        • Mapper代理方式
        • 設計模式
        • mybatis 執行流程圖解
      • mybatis延遲加載
      • mybatis 動態sql相關類
        • 常用的資料庫連接池
        • mybatis 查詢資料量大的時候會造成oom 如何處理

2020年8月25日20:55:29

自定義持久層框架

  • 持久層框架 是對jdbc 的封裝, 并解決了jdbc存在的問題
jdbc 代碼基礎回顧
try{
    Class.formName("com.mysql.jdbc.Driver");
    connection = .....
}cache(Exception e){
    
}
  • 傳統jdbc 存在 資料庫配置資訊存在硬編碼問題 當更換資料庫后需要再次對資料庫驅動資訊進行更改
  • 頻繁創建釋放資料庫連接
  • sql陳述句 設定引數 獲取結果集等引數均存在硬編碼問題
  • 手動封裝結果集 較為繁瑣
解決傳統jdbc存在的問題
  • 硬編碼 --> 組態檔
  • 硬編碼 --> 連接池
  • 手動封裝結果集 --> 反射 內省
自定義持久層框架設計思路
使用端 --> 專案
  • 引入自定義持久層jar
  • 提供資料庫配置資訊及sql配置資訊
    • sql配置資訊
      • sql陳述句
      • 引數型別
      • 回傳值型別
  • 使用組態檔提供外上述兩種配置資訊
  • sqlMapConfig.xml 存放資料庫的配置資訊,存入mapper.xml全路徑
  • mapper.xml 存放sql配置資訊
自定義持久層框架本身
  • 創建為專案工程,本質是對jdbc代碼進行封裝-->底層為傳統的jdbc

    • 資料庫配置資訊
    • sql 配置資訊 占位符 引數 sql陳述句等
    • 根據呼叫處傳遞的配置資訊進行決議
      • 加載組態檔 --> 以位元組輸入流的形式加載 --> 存盤在記憶體中
      • 創建Resource類,getResourceAsStream(String path)
      • 創建2個javaBean(容器物件),存放的是對組態檔決議出的內容
        • Configuration:核心配置類: 存放sqlMapperConfig.xml決議的內容
        • MappedStrement:映射配置類:存放mapper.xml決議的內容
      • 決議組態檔:Dom4j
        • 創建類:SqlSessionFactoryBuilder,存在方法:build(InputStream in)
        • build方法實作邏輯:
          • 使用dom4j決議組態檔,將決議結果封裝到容器物件內
          • 創建sqlSessionFactory物件,生產sqlSession(會話物件),避免重復創建連接 --> 工廠模式 降低耦合
      • 創建sqlSessionFactory介面及實作類DefaultSqlSessionFactory
        • openSession方法 : 創建 sqlSession物件
      • 創建SqlSession 介面及實作類DefaultSqlSession 定義對資料庫的CRUD方法
        • selectList()
        • selectOne()
        • update()
        • delete()
      • 創建Excutor介面及實作類 SimpleExcutor 實作類
        • query(Configuration conf,MappedStatement mapped,Object ...params):執行JDBC代碼

    graph TB
    b("工程專案")
    
    subgraph 工程專案
    d("mapper.xml") --"mapper.xml全路徑"--> c("sqlMapConfig.xml")
    b --"sql執行陳述句"--> d
    b --"資料庫配置"--> c
    end
    
    b --"參考"--> a
    
    subgraph 自定義持久層
    tip("本質是對jdbc代碼的封裝")
    a("自定義持久層")
    
    tip --> a
    a --"1. 創建"--> a1("Resources類")
    a1 --> a1a("InputStream()")
    a1 --"加載組態檔為位元組輸入流"--> a1b("getResourceAsStream(String path)")
    
    
    a --"2. 創建"--> a2("容器javaBean")
    
    subgraph 容器
    a2 --"創建核心配置類"--> a2a("Configuration")
    a2a --"存放"--> a21a("sqlMapConfig.xml 決議的內容")
    a2 --"創建核心配置類"--> a2b("MappedStatement")
    a2b --"映射配置類"--> a2b1("mapper.xml 決議的內容")
    end
    
    a --"3. 創建"--> a3("SqlSessionFactory")
    a3 --"實作類"--> a3a("DefaultSqlSessionFactory")
    a3a --"方法"--> a3a1("openSession()")
    a3a1 --"生產"--> a3a1a("Sqlsession")
    
    a --"4. 決議組態檔dom4j"--> a4("SqlSessionFactoryBuilder")
    a4 --"方法"--> a41("build(inputStream in)")
    a41 --"使用dom4j決議組態檔" --> a4a1a("決議結果")
    a4a1a --"封裝到容器物件"--> a2
    a41 --"創建"--> a41b("SqlSessionFactory物件")
    a41b  --"工廠模式生產"--> a41b1("sqlSession會話物件")
    
    a --"5. 創建"--> a5("SqlSession介面")
    a5 --"實作類"--> a5a("DefaultSession")
    a5a --"串列查詢"--> a5a1("selectList()")
    a5a --"查詢單個"--> a5a2("selectONe()")
    a5a --"修改"--> a5a3("update()")
    a5a --"洗掉"--> a5a4("delete()")
    
    a --"6. 創建"--> a6("Excutor介面")
    a6 --"實作類"--> a6a("SimpleExcutor")
    a6a --"成員方法"--> a6a1("query(Configuration conf,MappedStatement st,Object ...params);")
    a6a1 --"執行jdbc代碼" -->a6a1a("sql陳述句")
    end
    
    

mybatis 簡介

  • 持久層框架

  • 基于orm:Object Relation Mapping 物體類和資料庫表建立映射關聯關系

  • 半自動 可以對sql進行優化 hibernate -> 全自動

  • 輕量級:啟動的程序中需要的資源比較少

  • 底層: 對jdbc執行代碼 進行封裝 規避硬編碼,頻繁開閉資料源

sqlMapConfig.xml 節點說明
  • environments 資料庫環境的配置,支持多環境配置
  • environments.default--> 指定mybatis 使用的默認環境名稱
  • environment.id-->當前環境的名稱
  • environment - transcationManager.type="JDBC" 指定事務管理型別為jdbc
  • environment - dataSource.type="POOLED" 指定資料源型別為連接池
  • environment - dataSource
    • property.driver 資料庫驅動
    • property.url 資料庫地址 注意連接編碼格式
    • property.user 資料庫連接用戶名
    • property.password 資料庫連接用密碼
  • mapper 配置的四種方式:
    • mapper.resource 相對于類路徑的參考
    • mapper.url 完全限定資源定位符
    • mapper.class 介面對應的全路徑
    • package.name 批量加載 保證映射檔案與介面同包同名

傳統dao層開發方式
dao層開發方式
mybatis 外部properties 檔案
  • 設定mybatis xml組態檔的約束頭
  • 在resources下創建外部組態檔 格式:物件.屬性=值
  • 加載外部組態檔
    • 在 configutation 后第一個節點之前 引入外部組態檔 <properties resource='路徑'/>
mybatis aliasType
  • 在mybatis 組態檔中的typeAliases 節點中設定
    <typeAliases>
        <typeAlias type="pojo類路徑的全限定名" alais="別名"></typeAlias>
    </typeAliases>
    // 對于基礎資料型別 mybatis 已定義了別名
    string ==> String
    long ==> Long
    int ==> Integer
    double ==> Double
    boolean ==> Boolean
    
  • 當存在多個pojo時不適用以上方法,采用package模式[批量起別名]
    • package模式 不要單獨指定alias屬性 默認為類本身的類名,且不區分大小寫
    <typeAliases>
        <package name="pojo類所在包的全限定名"></typeAlias>
        // 不要單獨指定alias屬性 默認為類本身的類名,且不區分大小寫
    </typeAliases>
    
mapper.xml
動態sql
  • if 標簽 判斷入參是否符合條件, 不符合不拼接
  • where 標簽 自動拼接where 同時去掉where后的第一個and 關鍵字
  • foreach 標簽
    • collection array 注意便攜式不要使用#{}
    • open 回圈前追加
    • close 回圈結束后追加
    • item 單次回圈內的資料物件 生成的變數
    • separator 前后回圈資料之間的分隔符
  • sql 標簽 抽取sql片段
    • id sql陳述句的標識
    • 內容為具體的sql陳述句 可用于封裝 分頁 和 查詢某張表時的前面部分
mybatis復雜映射開發

sqlMapConfig.xml 內引入 mapper.xml

<package name="與介面同包同名的包名"><package>
一對一查詢
  • resultMap 手動配置物體屬性與表欄位的映射關系 可用于mybatis 的resultMMap
    • id
    • type 按照封裝物件的全路徑
    <resultMap id="orderMap" type="com.lagou.pojo.Order">
        <result property="id" column="id"></result>
        <result property="orderTime" column="orderTime"></result>
        <result property="total" column="total"></result>
    
        <association property="user" javaType="com.lagou.pojo.User">
            <result property="id" column="uid"></result>
            <result property="username" column="username"></result>
        </association>
    </resultMap>
    
    <!--resultMap:手動來配置物體屬性與表欄位的映射關系-->
    <select id="findOrderAndUser" resultMap="orderMap">
        select * from orders o,user u where o.uid = u.id
    </select>
    
一對多查詢
    <resultMap id="userMap" type="com.lagou.pojo.User">
        <result property="id" column="uid"></result>
        <result property="username" column="username"></result>
        <collection property="orderList" ofType="com.lagou.pojo.Order">
            <result property="id" column="id"></result>
            <result property="orderTime" column="orderTime"></result>
            <result property="total" column="total"></result>
        </collection>
    </resultMap>

    <select id="findAll" resultMap="userMap">
        select * from user u left join orders o on u.id = o.uid
    </select>
多對多查詢
  • 查詢用戶的同時查詢出用戶的角色
   <resultMap id="userRoleMap" type="com.lagou.pojo.User">
       <result property="id" column="userid"></result>
       <result property="username" column="username"></result>
       <collection property="roleList" ofType="com.lagou.pojo.Role">
           <result property="id" column="roleid"></result>
           <result property="roleName" column="roleName"></result>
           <result property="roleDesc" column="roleDesc"></result>
       </collection>
   </resultMap>

   <select id="findAllUserAndRole" resultMap="userRoleMap">
       select * from user u left join sys_user_role ur on u.id = ur.userid
   		left join sys_role r on r.id = ur.roleid
   </select>

mybatis 注解開發

使用注解開發 無需撰寫任何組態檔

  • @Insert 增
  • @Update 刪
  • @Delete 改
  • @Select 查
  • @Result 實作對結果集的封裝 替代result標簽節點
  • @Results 替代resultMap 標簽節點
  • @One 替代單個pojo物件 替代 association 標簽節點
  • @Many 如果屬性為集合時 則采用 此注解
注解一對多
@Results({
    @Result(property = "id",column = "id"),
    @Result(property = "orderTime",column = "orderTime"),
    @Result(property = "total",column = "total"),
    @Result(property = "user",column = "uid",javaType = User.class,
        one=@One(select = "com.lagou.mapper.IUserMapper.findUserById"))
})
@Select("select * from orders")
public List<Order> findOrderAndUser();
注解多對多
# IUserMapper
    //查詢所有用戶、同時查詢每個用戶關聯的角色資訊
    @Select("select * from user")
    @Results({
            @Result(property = "id",column = "id"),
            @Result(property = "username",column = "username"),
            @Result(property = "roleList",column = "id",javaType = List.class,
             many = @Many(select = "com.lagou.mapper.IRoleMapper.findRoleByUid"))
    })
    public List<User> findAllUserAndRole();
# IRoleMapper
    @Select("select * from sys_role r,sys_user_role ur where r.id = ur.roleid and ur.userid = #{uid}")
    public List<Role> findRoleByUid(Integer uid);
mybatis 快取
一級快取

使用同一個sqlSession 物件時,資料會被快取
mybatis 一級快取程序圖解

  1. 第一次發起查詢用戶id為1的用戶資訊,先去找快取中是否有id為1的用戶資訊,如果沒有,從
    資料庫查詢用戶資訊,得到用戶資訊,將用戶資訊存盤到一級快取中,
  2. 如果中間sqlSession去執行commit操作(執行插入、更新、洗掉),則會清空SqlSession中的
    一級快取,這樣做的目的為了讓快取中存盤的是最新的資訊,避免臟讀,
  3. 第二次發起查詢用戶id為1的用戶資訊,先去找快取中是否有id為1的用戶資訊,快取中有,直
    接從快取中獲取用戶資訊
一級快取分析

一級快取分析 流程圖

  • 一級快取到底是什么
    底層是一個hashMap 參照上述流程圖
    
  • 一級快取什么時候被創建
    快取key創建類: Excustor.class.createCacheKey()
    BaseExcutor.createCacheKey() //創建一級快取的key
    
    CacheKey.update()
      - updateList.add(configuration.getEnviroment().getId());
    
  • 一級快取的作業流程是怎樣的
  • 一級快取的清空 sqlSession.close() 或者執行帶有事務的操作
  • 在分布式環境下也會存在臟讀問題 解決:禁用一級快取或調整快取為statement 級別
二級快取
  • 原理 類似 一級快取
  • 操作的sqlSession 執行了事務操作后 會清空二級快取
  • 一級快取 默認開啟
  • 二級快取需要手動配置開啟
    1. xml開發形式
    <setting>
        <setting name="cacheEnabled" value="https://www.cnblogs.com/Yount/p/true" />
    </setting>
    2. 注解形式
    在dao介面上添加注解 @CacheNamespace
    
  • 二級快取 快取的不是物件 而是物件中的資料
    • pojo類需要實作 Serializable 介面
    • 二級快取的存盤機制是多樣的,可能存盤在硬碟上 或者記憶體中
  • 當執行帶有事務的操作后,二級快取會被清空
  • 當基于xml配置時還可以配置
    • useCache 屬性 false 禁用二級快取 每次查詢都發送sql去資料庫查詢 默認為true
    • 注解形式:@select 注解之前添加 @Options(cache="false")
    • flushCache 屬性: 每次增刪改操作后 清空快取 默認true

二級快取整合redis

mybatis二級快取結構示意圖

  • PerpetualCache 是mybatis默認實作快取功能的類
  • 二級快取的底層資料結構 還是 HashMap org.apache.ibatis.cache.impl.PerpetualCache --> private Map<Object, Object> cache = new HashMap()
  • 指定mybatis二級快取的實作類
    在dao介面上添加注解 
    @CacheNamespace(implementation=PerpetualCache.class) 
    PerpetualCache.class 更換為自定義快取實作類
    如 : @CacheNamespace(implementation = RedisCache.class)
    
  • 二級快取 存在的問題
    • 單服務器下 --> 沒問題
    • 分布式 --> 無法實作分布式快取
  • 分布式快取技術
    • redis 官方提供有mybatis-redis實作類
    <dependency>
        <groupId>org.mybatis.caches</groupId>
        <artifactId>mybatis-redis</artifactId>
        <version>1.0.0-beta2</version>
    </dependency>
    
    配置組態檔 : redis.properties
    配置以下屬性:
      host=localhost
      port=6379
      connectionTimeout=5000
      password=123456
      database=0
    
    • memcached
    • ehcache
  • 二級快取存在的臟讀問題分析
    二級快取namespace級別產生臟讀問題分析
redis-cache 分析
  • redis-cache 是如何存取值的
    1. 必須實作mybatis 的cache 介面
    2. 使用 jedis.hget 進行取值
    
  • redis-cache 使用的是哪種redis 資料結構
    • redis 的 hash 資料型別

mybatis的插件

  • 一種形式的拓展點
    • 增加靈活性
    • 根據實際需求 自行拓展
  • mybatis 的四大組件 及允許攔截的方法
    • Executor 執行器
      • update
      • query
      • commit
      • rollback 等
    • StatementHandler sql語法構建器
      • prepare
      • parameterize
      • batch
      • update
      • query 等
    • ParameterHandler 引數處理器
      • getParameterObject
      • setParameterObject
    • ResultSetHandler 結果集處理器
      • handleResultSets
      • handleOutputParameters
  • 插件攔截器底層是對以上四個組件的攔截,采用動態代理實作
以上組件的創建原理
  1. 每個創建出來的物件不是直接回傳的,而是interceptorChain.pluginAll(parameterHandler)
  2. 獲取到所有的Interceptor(攔截器)(插件需要實作的介面);呼叫interceptor.plugin(target);回傳target包裝后的物件
  3. 插件機制,我們可以使用插件為目標物件創建一個代理物件;AOP(面向切面)我們的插件可以為四大物件創建出代理物件,代理物件就可以攔截到四大物件的每一個執行;
  4. 由于使用了jdk動態代理,那么就回去執行 invoke 方法,可以在攔截器 的前置和后置處理器內做相應的處理操作
@Intercepta({
    @signature(
        type=Executor.class,
        method="query",
        args=(MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
    )
})
public class ExamplePlugin implements Interceptor{
//省略邏輯
}
自定義mybatis 插件
  • 插件 --> 攔截器
org.apache.ibatis.plugin.Interceptor 類
# 攔截方法:只要被攔截的目標物件的目標方法被執行時,每次都會執行intercept方法
Interceptor.intercept 
# 主要為了把當前的攔截器生成代理存到攔截器鏈中
Interceptor.plugin
# 獲取組態檔的引數
Interceptor.setProperties
  • 定義

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.*;

import java.sql.Connection;
import java.util.Properties;

# 可以多個Signature 
@Intercepts({
    @Signature(type= StatementHandler.class,method = "prepare",args = {Connection.class,Integer.class}),
    @Signature(type= Executor.class,method = "prepare",args = {Connection.class,Integer.class})
})
public class MyPlugin implements Interceptor {
    /*
        攔截方法:只要被攔截的目標物件的目標方法被執行時,每次都會執行intercept方法
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("對方法:" + invocation.getMethod().getName() + " 進行了增強...." );
        return invocation.proceed(); //原方法執行
    }
    /*
       主要為了把當前的攔截器生成代理存到攔截器鏈中
     */
    @Override
    public Object plugin(Object target) { Object wrap = Plugin.wrap(target, this); return wrap; }
    /*
        獲取組態檔的引數
     */
    @Override
    public void setProperties(Properties properties) { System.out.println("獲取到的組態檔的引數是:"+properties); }
}
  • 配置
<plugins>
    <plugin interceptor="com.lagou.plugin.MyPlugin">
        <property name="name" value="https://www.cnblogs.com/Yount/p/tom"/> <!-- 設定引數 -->
    </plugin>
</plugins>
  • 使用
1. MyPlugin.plugin --> MyPlugin.intercept  --> MyPlugin.setProperties 
mybatis的第三方插件
  • PageHelper
    • 匯入maven 依賴
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>3.7.5</version>
    </dependency>
    
    • 在mybatis組態檔中配置PageHelper
    在 plugins 節點內 添加 plugin 并設定屬性 `property` 方言 `dialect` 值設 `mysql`
    <plugin interceptor="com.github.pagehelper.PageHelper">
        <property name="dialect" value="https://www.cnblogs.com/Yount/p/mysql"/>
    </plugin>
    
  • 通用 mapper
    • 匯入依賴
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper</artifactId>
        <version>3.1.2</version>
    </dependency>
    
    • mybatis 的組態檔內配置 通用mapper 的plugin
    <plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor">
        <!--指定當前通用mapper介面使用的是哪一個-->
        <property name="mappers" value="https://www.cnblogs.com/Yount/p/tk.mybatis.mapper.common.Mapper"/>
    </plugin>
    
    • 物體類設定關聯
    @Table(name = "user")
    public class User implements Serializable {
    
        @Id //對應的是注解id
        @GeneratedValue(strategy = GenerationType.IDENTITY) 
        // @GeneratedValue strategy 設定主鍵的生成策略
        // GenerationType.IDENTITY 底層必須支持自增長
        // GenerationType.SEQUENCY 底層不支持自增長
        // GenerationType.TABLE 從表中取值 生成主鍵
        // GenerationType.AUTO 自動選擇合適的生成主鍵
        private Integer id;
        
        @Column(name="123") 當與表的欄位不同時,采用@Column 保持同步
        private String username;
        // Get Set 略
    }
    
    • 創建dao介面 繼承tk.mybatis.mapper.common.Mapper傳入泛型
    egg: public interface UserMapper  extends Mapper<User> {}
    
    • 使用
      • 傳統呼叫
      InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
      SqlSession sqlSession = sqlSessionFactory.openSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      User user = new User();
      user.setId(1);
      User user1 = mapper.selectOne(user);
      System.out.println(user1);
      
      • Example 方式呼叫
      InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
      SqlSession sqlSession = sqlSessionFactory.openSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      // example 方式呼叫
      Example example = new Example(User.class);
      // 查詢User表中的全部記錄
      example.createCriteria().andEqualTo("id",1);
      // 執行查詢,獲得結果
      List<User> users = mapper.selectByExample(example);
      for (User user2 : users) {
          System.out.println(user2);
      }
      

隨堂測驗01 自定義持久層框架

  1. 自定義持久層框架IPersistence是如何解決JDBC存在的問題:() [多選題]

    • [x] A. 用組態檔解決了硬編碼問題
    • [x] B.使用了C3P0連接池解決了頻繁創建釋放資料庫連接問題
    • [x] C.在simpleExecute中使用到了反射進行了引數的設定
    • [x] D.在simpleExecute中使用了內省進行了回傳結果集的封裝
  2. 在進行自定義持久層框架IPersistence優化時,主要為了解決那些問題:() [多選題]

    • [x] A.應用在Dao層,整個操作的模板代碼重復
    • [x] B.呼叫sqlSession方法時、引數statementId硬編碼
    • [ ] C.無法保證statementId的唯一性
    • [ ] D.引數存在硬編碼
  3. 下列關于Configuration及MappedStatement配置類,說法正確的是:() [多選題]

    • [x] A.使用dom4j對sqlMapConfig.xml決議時,會將決議出來的內容以不同形式封裝到Configuration物件中
    • [ ] B.使用dom4j對mapper.xml決議時,每個

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/195919.html

標籤:Java

上一篇:【16】進大廠必須掌握的面試題-100個python面試

下一篇:一起來讀官方檔案-----SpringIOC(10)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more