主頁 > 後端開發 > Mybatis-學習筆記

Mybatis-學習筆記

2021-06-16 06:10:21 後端開發

Mybatis-9.28

環境:

  • JDK1.8
  • Mysql 5.7
  • maven 3.6.1
  • IDEA

回顧:

  • JDBC
  • Mysql
  • Java基礎
  • Maven
  • Junit

SSM框架:組態檔的, 最好的方式:看官網檔案;

1、簡介

1.1、什么是Mybatis

1569633932712

  • MyBatis 是一款優秀的持久層框架
  • 它支持定制化 SQL、存盤程序以及高級映射,
  • MyBatis 避免了幾乎所有的 JDBC 代碼和手動設定引數以及獲取結果集,
  • MyBatis 可以使用簡單的 XML 或注解來配置和映射原生型別、介面和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄,
  • MyBatis 本是apache的一個開源專案iBatis, 2010年這個專案由apache software foundation 遷移到了google code,并且改名為MyBatis ,
  • 2013年11月遷移到Github,

如何獲得Mybatis?

  • maven倉庫:

    <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.2</version>
    </dependency>
    
  • Github : https://github.com/mybatis/mybatis-3/releases

  • 中文檔案:https://mybatis.org/mybatis-3/zh/index.html

1.2、持久化

資料持久化

  • 持久化就是將程式的資料在持久狀態和瞬時狀態轉化的程序
  • 記憶體:斷電即失
  • 資料庫(Jdbc),io檔案持久化,
  • 生活:冷藏. 罐頭,

為什么需要需要持久化?

  • 有一些物件,不能讓他丟掉,

  • 記憶體太貴了

1.3、持久層

Dao層,Service層,Controller層….

  • 完成持久化作業的代碼塊
  • 層界限十分明顯,

1.4 為什么需要Mybatis?

  • 幫助程式猿將資料存入到資料庫中,
  • 方便
  • 傳統的JDBC代碼太復雜了,簡化,框架,自動化,
  • 不用Mybatis也可以,更容易上手, 技術沒有高低之分
  • 優點:
    • 簡單易學
    • 靈活
    • sql和代碼的分離,提高了可維護性,
    • 提供映射標簽,支持物件與資料庫的orm欄位關系映射
    • 提供物件關系映射標簽,支持物件關系組建維護
    • 提供xml標簽,支持撰寫動態sql,

最重要的一點:使用的人多!

Spring SpringMVC SpringBoot

2、第一個Mybatis程式

思路:搭建環境-->匯入Mybatis-->撰寫代碼-->測驗!

2.1、搭建環境

搭建資料庫

CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
  `id` INT(20) NOT NULL PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL,
  `pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO `user`(`id`,`name`,`pwd`) VALUES 
(1,'狂神','123456'),
(2,'張三','123456'),
(3,'李四','123890')

新建專案

  1. 新建一個普通的maven專案

  2. 洗掉src目錄

  3. 匯入maven依賴

        <!--匯入依賴-->
        <dependencies>
            <!--mysql驅動-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <!--mybatis-->
            <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.2</version>
            </dependency>
            <!--junit-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
        </dependencies>
    

2.2、創建一個模塊

  • 撰寫mybatis的核心組態檔

    <?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核心組態檔-->
    <configuration>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="https://www.cnblogs.com/pxlsdz/p/com.mysql.jdbc.Driver"/>
                    <property name="url" value="https://www.cnblogs.com/pxlsdz/p/jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
                    <property name="username" value="https://www.cnblogs.com/pxlsdz/p/root"/>
                    <property name="password" value="https://www.cnblogs.com/pxlsdz/p/123456"/>
                </dataSource>
            </environment>
        </environments>
    
    </configuration>
    
  • 撰寫mybatis工具類

    //sqlSessionFactory --> sqlSession
    public class MybatisUtils {
    
        private static SqlSessionFactory sqlSessionFactory;
    
        static{
            try {
                //使用Mybatis第一步:獲取sqlSessionFactory物件
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        //既然有了 SqlSessionFactory,顧名思義,我們就可以從中獲得 SqlSession 的實體了,
        // SqlSession 完全包含了面向資料庫執行 SQL 命令所需的所有方法,
        public static SqlSession  getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    
    }
    
    

2.3、撰寫代碼

  • 物體類

    package com.kuang.pojo;
    
    //物體類
    public class User {
        private int id;
        private String name;
        private String pwd;
    
        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
    
  • Dao介面

    public interface UserDao {
        List<User> getUserList();
    }
    
  • 介面實作類由原來的UserDaoImpl轉變為一個 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">
            <!--namespace=系結一個對應的Dao/Mapper介面-->
    <mapper namespace="com.kuang.dao.UserDao">
    
    <!--select查詢陳述句-->
       <select id="getUserList" resultType="com.kuang.pojo.User">
           select * from mybatis.user
       </select>
    
    </mapper>
    

2.4、測驗

注意點:

org.apache.ibatis.binding.BindingException: Type interface com.kuang.dao.UserDao is not known to the MapperRegistry.

MapperRegistry是什么?

核心組態檔中注冊 mappers

<mappers>        <mapper resource="com/sdz/dao/UserMapper.xml"/>    </mappers>
  • junit測驗

    @Testpublic void test(){    //第一步:獲得SqlSession物件    SqlSession sqlSession = MybatisUtils.getSqlSession();    //方式一:getMapper    UserDao userDao = sqlSession.getMapper(UserDao.class);    List<User> userList = userDao.getUserList();    for (User user : userList) {        System.out.println(user);    }    //關閉SqlSession    sqlSession.close();}
    

你們可以能會遇到的問題:

  1. 組態檔沒有注冊
  2. 系結介面錯誤,
  3. 方法名不對
  4. 回傳型別不對
  5. Maven匯出資源問題

3、CRUD

1、namespace

namespace中的包名要和 Dao/mapper 介面的包名一致!

2、select

選擇,查詢陳述句;

  • id : 就是對應的namespace中的方法名;
  • resultType:Sql陳述句執行的回傳值!
  • parameterType : 引數型別!
  1. 撰寫介面

    //根據ID查詢用戶User getUserById(int id);
    
  2. 撰寫對應的mapper中的sql陳述句

    <select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">        select * from mybatis.user where id = #{id}</select>
    
  3. 測驗

        @Test    public void getUserById() {        SqlSession sqlSession = MybatisUtils.getSqlSession();        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        User user = mapper.getUserById(1);        System.out.println(user);        sqlSession.close();    }
    

3、Insert

    <!--物件中的屬性,可以直接取出來-->    <insert id="addUser" parameterType="com.kuang.pojo.User">        insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});    </insert>

4、update

    <update id="updateUser" parameterType="com.kuang.pojo.User">        update mybatis.user set name=#{name},pwd=#{pwd}  where id = #{id} ;    </update>

5、Delete

    <delete id="deleteUser" parameterType="int">        delete from mybatis.user where id = #{id};    </delete>

注意點:

  • 增刪改需要提交事務!

6、分析錯誤

  • 標簽不要匹配錯
  • resource 系結mapper,需要使用路徑!
  • 程式組態檔必須符合規范!
  • NullPointerException,沒有注冊到資源!
  • 輸出的xml檔案中存在中文亂碼問題!
  • maven資源沒有匯出問題!

7、萬能Map

假設,我們的物體類,或者資料庫中的表,欄位或者引數過多,我們應當考慮使用Map!

    //萬能的Map    int addUser2(Map<String,Object> map);
    <!--物件中的屬性,可以直接取出來    傳遞map的key-->    <insert id="addUser" parameterType="map">        insert into mybatis.user (id, pwd) values (#{userid},#{passWord});    </insert>
    @Test    public void addUser2(){        SqlSession sqlSession = MybatisUtils.getSqlSession();        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        Map<String, Object> map = new HashMap<String, Object>();        map.put("userid",5);        map.put("passWord","2222333");        mapper.addUser2(map);        sqlSession.close();    }

Map傳遞引數,直接在sql中取出key即可! 【parameterType="map"】

物件傳遞引數,直接在sql中取物件的屬性即可!【parameterType="Object"】

只有一個基本型別引數的情況下,可以直接在sql中取到!

多個引數用Map,或者注解!

8、思考題

模糊查詢怎么寫?

  1. Java代碼執行的時候,傳遞通配符 % %

    List<User> userList = mapper.getUserLike("%李%");
    
  2. 在sql拼接中使用通配符!

    select * from mybatis.user where name like "%"#{value}"%"
    

4、配置決議

1、核心組態檔

  • mybatis-config.xml

  • MyBatis 的組態檔包含了會深深影響 MyBatis 行為的設定和屬性資訊,

    configuration(配置)properties(屬性)settings(設定)typeAliases(型別別名)typeHandlers(型別處理器)objectFactory(物件工廠)plugins(插件)environments(環境配置)environment(環境變數)transactionManager(事務管理器)dataSource(資料源)databaseIdProvider(資料庫廠商標識)mappers(映射器)
    

2、環境配置(environments)

MyBatis 可以配置成適應多種環境

不過要記住:盡管可以配置多個環境,但每個 SqlSessionFactory 實體只能選擇一種環境,

學會使用配置多套運行環境!

Mybatis默認的事務管理器就是 JDBC , 連接池 : POOLED

3、屬性(properties)

我們可以通過properties屬性來實作參考組態檔

這些屬性都是可外部配置且可動態替換的,既可以在典型的 Java 屬性檔案中配置,亦可通過 properties 元素的子元素來傳遞,【db.properties】

1569656528134

撰寫一個組態檔

db.properties

driver=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8username=rootpassword=123456

在核心組態檔中映入

    <!--引入外部組態檔-->    <properties resource="db.properties">        <property name="username" value="https://www.cnblogs.com/pxlsdz/p/root"/>        <property name="pwd" value="https://www.cnblogs.com/pxlsdz/p/11111"/>    </properties>
  • 可以直接引入外部檔案
  • 可以在其中增加一些屬性配置
  • 如果兩個檔案有同一個欄位,優先使用外部組態檔的!

4、型別別名(typeAliases)

  • 型別別名是為 Java 型別設定一個短的名字,‘
  • 存在的意義僅在于用來減少類完全限定名的冗余,
    <!--可以給物體類起別名-->    <typeAliases>        <typeAlias type="com.kuang.pojo.User" alias="User"/>    </typeAliases>

也可以指定一個包名,MyBatis 會在包名下面搜索需要的 Java Bean,比如:

掃描物體類的包,它的默認別名就為這個類的 類名,首字母小寫!

<!--可以給物體類起別名--><typeAliases>    <package name="com.kuang.pojo"/></typeAliases>

在物體類比較少的時候,使用第一種方式,

如果物體類十分多,建議使用第二種,

第一種可以DIY別名,第二種則·不行·,如果非要改,需要在物體上增加注解

@Alias("user")public class User {}

5、設定

這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的運行時行為,

1569657659080

1569657672791

6、其他配置

  • typeHandlers(型別處理器)
  • objectFactory(物件工廠)
  • plugins插件
    • mybatis-generator-core
    • mybatis-plus
    • 通用mapper

7、映射器(mappers)

MapperRegistry:注冊系結我們的Mapper檔案;

方式一: 【推薦使用】

<!--每一個Mapper.XML都需要在Mybatis核心組態檔中注冊!--><mappers>    <mapper resource="com/kuang/dao/UserMapper.xml"/></mappers>

方式二:使用class檔案系結注冊

<!--每一個Mapper.XML都需要在Mybatis核心組態檔中注冊!--><mappers>    <mapper /></mappers>

注意點:

  • 介面和他的Mapper組態檔必須同名!
  • 介面和他的Mapper組態檔必須在同一個包下!

方式三:使用掃描包進行注入系結

<!--每一個Mapper.XML都需要在Mybatis核心組態檔中注冊!--><mappers>    <package name="com.kuang.dao"/></mappers>

注意點:

  • 介面和他的Mapper組態檔必須同名!
  • 介面和他的Mapper組態檔必須在同一個包下!

練習時間:

  • 將資料庫組態檔外部引入
  • 物體類別名
  • 保證UserMapper 介面 和 UserMapper .xml 改為一致!并且放在同一個包下!

8、生命周期和作用域

1569660357745

生命周期,和作用域,是至關重要的,因為錯誤的使用會導致非常嚴重的并發問題

SqlSessionFactoryBuilder:

  • 一旦創建了 SqlSessionFactory,就不再需要它了
  • 區域變數

SqlSessionFactory:

  • 說白了就是可以想象為 :資料庫連接池
  • SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創建另一個實體,
  • 因此 SqlSessionFactory 的最佳作用域是應用作用域,
  • 最簡單的就是使用單例模式或者靜態單例模式,

SqlSession

  • 連接到連接池的一個請求!
  • SqlSession 的實體不是執行緒安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域,
  • 用完之后需要趕緊關閉,否則資源被占用!

1569660737088

這里面的每一個Mapper,就代表一個具體的業務!

5、解決屬性名和欄位名不一致的問題

1、 問題

資料庫中的欄位

1569660831076

新建一個專案,拷貝之前的,測驗物體類欄位不一致的情況

public class User {        private int id;    private String name;    private String password;}

測驗出現問題

1569661145806

//    select * from mybatis.user where id = #{id}//型別處理器//    select id,name,pwd from mybatis.user where id = #{id}

解決方法:

  • 起別名

    <select id="getUserById" resultType="com.kuang.pojo.User">    select id,name,pwd as password from mybatis.user where id = #{id}</select>
    

2、resultMap

結果集映射

id   name   pwdid   name   password
<!--結果集映射--><resultMap id="UserMap" type="User">    <!--column資料庫中的欄位,property物體類中的屬性-->    <result column="id" property="id"/>    <result column="name" property="name"/>    <result column="pwd" property="password"/></resultMap><select id="getUserById" resultMap="UserMap">    select * from mybatis.user where id = #{id}</select>
屬性: result物件: association(一對多)集合: collection 
  • resultMap 元素是 MyBatis 中最重要最強大的元素
  • ResultMap 的設計思想是,對于簡單的陳述句根本不需要配置顯式的結果映射,而對于復雜一點的陳述句只需要描述它們的關系就行了,
  • ResultMap 最優秀的地方在于,雖然你已經對它相當了解了,但是根本就不需要顯式地用到他們,
  • 如果世界總是這么簡單就好了,

6、日志

6.1、日志工廠

如果一個資料庫操作,出現了例外,我們需要排錯,日志就是最好的助手!

曾經:sout 、debug

現在:日志工廠!

1569892155104

  • SLF4J

  • LOG4J 【掌握】

  • LOG4J2

  • JDK_LOGGING

  • COMMONS_LOGGING

  • STDOUT_LOGGING 【掌握】

  • NO_LOGGING

在Mybatis中具體使用那個一日志實作,在設定中設定!

STDOUT_LOGGING標準日志輸出

在mybatis核心組態檔中,配置我們的日志!

<settings>    <setting name="logImpl" value="https://www.cnblogs.com/pxlsdz/p/STDOUT_LOGGING"/></settings>

1569892595060

6.2、Log4j

什么是Log4j?

  • Log4j是Apache的一個開源專案,通過使用Log4j,我們可以控制日志資訊輸送的目的地是控制臺、檔案、GUI組件
  • 我們也可以控制每一條日志的輸出格式;
  • 通過定義每一條日志資訊的級別,我們能夠更加細致地控制日志的生成程序,
  • 通過一個組態檔來靈活地進行配置,而不需要修改應用的代碼,
  1. 先匯入log4j的包

    <!-- https://mvnrepository.com/artifact/log4j/log4j --><dependency>    <groupId>log4j</groupId>    <artifactId>log4j</artifactId>    <version>1.2.17</version></dependency>
    
  2. log4j.properties

    #將等級為DEBUG的日志資訊輸出到console和file這兩個目的地,console和file的定義在下面的代碼log4j.rootLogger=DEBUG,console,file#控制臺輸出的相關設定log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.Threshold=DEBUGlog4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%c]-%m%n#檔案輸出的相關設定log4j.appender.file = org.apache.log4j.RollingFileAppenderlog4j.appender.file.File=./log/kuang.loglog4j.appender.file.MaxFileSize=10mblog4j.appender.file.Threshold=DEBUGlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#日志輸出級別log4j.logger.org.mybatis=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG
    
  3. 配置log4j為日志的實作

    <settings>    <setting name="logImpl" value="https://www.cnblogs.com/pxlsdz/p/LOG4j"/></settings>
    
  4. Log4j的使用!,直接測驗運行剛才的查詢

    1569893505842

簡單使用

  1. 在要使用Log4j 的類中,匯入包 import org.apache.log4j.Logger;

  2. 日志物件,引數為當前類的class

    static Logger logger = Logger.getLogger(UserDaoTest.class);
    
  3. 日志級別(重要,在代碼中寫上)

    logger.info("info:進入了testLog4j");logger.debug("debug:進入了testLog4j");logger.error("error:進入了testLog4j");
    

7、分頁

思考:為什么要分頁?

  • 減少資料的處理量

7.1、使用Limit分頁

語法:SELECT * from user limit startIndex,pageSize;SELECT * from user limit 3;  #[0,n]

使用Mybatis實作分頁,核心SQL

  1. 介面

    //分頁List<User> getUserByLimit(Map<String,Integer> map);
    
  2. Mapper.xml

    <!--//分頁,resultMap="UserMap" 做了映射才用resultMap映射才用--><select id="getUserByLimit" parameterType="map" resultMap="UserMap">    select * from  mybatis.user limit #{startIndex},#{pageSize}</select>
    
  3. 測驗

    @Testpublic void getUserByLimit(){SqlSession sqlSession = MybatisUtils.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);HashMap<String, Integer> map = new HashMap<String, Integer>();    map.put("startIndex",1);    map.put("pageSize",2);    List<User> userList =  mapper.getUserByLimit(map);    for (User user : userList) {    System.out.println(user);    }    sqlSession.close();    }
    

7.2、RowBounds分頁

不再使用SQL實作分頁

  1. 介面

    //分頁2List<User> getUserByRowBounds();
    
  2. mapper.xml

      <!--//分頁-->    <select id="getUserByLimit" parameterType="map" resultType="user">    select * from  mybatis.user limit #{startIndex},#{pageSize}    </select>
    
  3. 測驗

    @Testpublic void getUserByRowBounds(){SqlSession sqlSession = MybatisUtils.getSqlSession();//RowBounds實作RowBounds rowBounds = new RowBounds(1, 2);//通過Java代碼層面實作分頁List<User> userList = sqlSession.selectList("com.kuang.dao.UserMapper.getUserByRowBounds",null,rowBounds);    for (User user : userList) {    System.out.println(user);    }    sqlSession.close();    }
    

7.3、分頁插件

1569896603103

了解即可,萬一 以后公司的架構師,說要使用,你需要知道它是什么東西!

8、使用注解開發

8.1、面向介面編程

- 大家之前都學過面向物件編程,也學習過介面,但在真正的開發中,很多時候我們會選擇面向介面編程
- 根本原因 : 解耦 , 可拓展 , 提高復用 , 分層開發中 , 上層不用管具體的實作 , 大家都遵守共同的標準 , 使得開發變得容易 , 規范性更好
- 在一個面向物件的系統中,系統的各種功能是由許許多多的不同物件協作完成的,在這種情況下,各個物件內部是如何實作自己的,對系統設計人員來講就不那么重要了;
- 而各個物件之間的協作關系則成為系統設計的關鍵,小到不同類之間的通信,大到各模塊之間的互動,在系統設計之初都是要著重考慮的,這也是系統設計的主要作業內容,面向介面編程就是指按照這種思想來編程,

關于介面的理解

- 介面從更深層次的理解,應是定義(規范,約束)與實作(名實分離的原則)的分離,
- 介面的本身反映了系統設計人員對系統的抽象理解,
- 介面應有兩類:
- 第一類是對一個個體的抽象,它可對應為一個抽象體(abstract class);
- 第二類是對一個個體某一方面的抽象,即形成一個抽象面(interface);
- 一個體有可能有多個抽象面,抽象體與抽象面是有區別的,

三個面向區別

- 面向物件是指,我們考慮問題時,以物件為單位,考慮它的屬性及方法 .
- 面向程序是指,我們考慮問題時,以一個具體的流程(事務程序)為單位,考慮它的實作 .
- 介面設計與非介面設計是針對復用技術而言的,與面向物件(程序)不是一個問題.更多的體現就是對系統整體的架構

8.2、使用注解開發

  1. 注解在介面上實作

    @Select("select * from user")List<User> getUsers();
    
  2. 需要再核心組態檔中系結介面!

    <!--系結介面--><mappers>    <mapper /></mappers>
    
  3. 測驗

本質:反射機制實作

底層:動態代理!

1569898830704

Mybatis詳細的執行流程!

1569898830704

8.3、CRUD

我們可以在工具類創建的時候實作自動提交事務!(盡量不要)

public static SqlSession  getSqlSession(){    return sqlSessionFactory.openSession(true);}

撰寫介面,增加注解

public interface UserMapper {    @Select("select * from user")    List<User> getUsers();    // 方法存在多個引數,所有的引數前面必須加上 @Param("id")注解,以@Param("id")為準    @Select("select * from user where id = #{id}")    User getUserByID(@Param("id") int id);    @Insert("insert into user(id,name,pwd) values (#{id},#{name},#{password})")    int addUser(User user);        @Update("update user set name=#{name},pwd=#{password} where id = #{id}")    int updateUser(User user);        @Delete("delete from user where id = #{uid}")    int deleteUser(@Param("uid") int id);}

測驗類

【注意:我們必須要講介面注冊系結到我們的核心組態檔中!】

關于@Param() 注解

  • 基本型別的引數或者String型別,需要加上
  • 參考型別不需要加
  • 如果只有一個基本型別的話,可以忽略,但是建議大家都加上!
  • 我們在SQL中參考的就是我們這里的 @Param() 中設定的屬性名!

**#{} \({} 區別** 經常碰到這樣的面試題目:#{}和\){}的區別是什么?

  1. 網上的答案是:#{}是預編譯處理,${}是字串替換,mybatis在處理#{}時,會將sql中的#{}替換為?號,呼叫PreparedStatement的set方法來賦值;mybatis在處理 $ { } 時,就是把 ${ } 替換成變數的值,使用 #{} 可以有效的防止SQL注入,提高系統安全性,

    對于這個題目我感覺要抓住兩點:

    (1)$ 符號一般用來當作占位符,常使用Linux腳本的人應該對此有更深的體會吧,既然是占位符,當然就是被用來替換的,知道了這點就能很容易區分$和#,從而不容易記錯了,

    (2)預編譯的機制,預編譯是提前對SQL陳述句進行預編譯,而其后注入的引數將不會再進行SQL編譯,我們知道,SQL注入是發生在編譯的程序中,因為惡意注入了某些特殊字符,最后被編譯成了惡意的執行操作,而預編譯機制則可以很好的防止SQL注入,

9、Lombok

Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.Never write another getter or equals method again, with one annotation your class has a fully featured builder, Automate your logging variables, and much more.
  • java library
  • plugs
  • build tools
  • with one annotation your class

使用步驟:

  1. 在IDEA中安裝Lombok插件!

  2. 在專案中匯入lombok的jar包

    <dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.18.10</version></dependency>
    
  3. 在物體類上加注解即可!

    @Data@AllArgsConstructor@NoArgsConstructor
    
@Getter and @Setter@FieldNameConstants@ToString@EqualsAndHashCode@AllArgsConstructor, @RequiredArgsConstructor and @NoArgsConstructor@Log, @Log4j, @Log4j2, @Slf4j, @XSlf4j, @CommonsLog, @JBossLog, @Flogger@Data@Builder@Singular@Delegate@Value@Accessors@Wither@SneakyThrows

說明:

@Data:無參構造,get、set、tostring、hashcode,equals@AllArgsConstructor :有參@NoArgsConstructor :無參@EqualsAndHashCode@ToString@Getter

10、多對一處理

多對一:

1569909163944

  • 多個學生,對應一個老師
  • 對于學生這邊而言, 關聯 .. 多個學生,關聯一個老師 【多對一】
  • 對于老師而言, 集合 , 一個老師,有很多學生 【一對多】

1569909422471

SQL:

CREATE TABLE `teacher` (  `id` INT(10) NOT NULL,  `name` VARCHAR(30) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO teacher(`id`, `name`) VALUES (1, '秦老師'); CREATE TABLE `student` (  `id` INT(10) NOT NULL,  `name` VARCHAR(30) DEFAULT NULL,  `tid` INT(10) DEFAULT NULL,  PRIMARY KEY (`id`),  KEY `fktid` (`tid`),  CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher` (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小紅', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小張', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

測驗環境搭建

  1. 匯入lombok
  2. 新建物體類 Teacher,Student
  3. 建立Mapper介面
  4. 建立Mapper.XML檔案
  5. 在核心組態檔中系結注冊我們的Mapper介面或者檔案!【方式很多,隨心選】
  6. 測驗查詢是否能夠成功!

簡單例子

package com.sdz.dao;import com.sdz.pojo.Teacher;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;public interface TeacherMapper {    @Select("select * from teacher where id = #{tid}")    Teacher getTeacher(@Param("tid") int id);}

mybatis-config.xml

   <mappers>        <mapper />        <mapper />    </mappers>

測驗

package com.sdz.dao;import com.sdz.pojo.Teacher;import com.sdz.utils.MybatisUtils;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class MyTest {    @Test    public void getTeacher(){        SqlSession sqlSession = MybatisUtils.getSession();        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);        Teacher teacher = mapper.getTeacher(1);        System.out.println(teacher);        sqlSession.close();    }}

按照查詢嵌套處理

    <!--    思路:        1. 查詢所有的學生資訊        2. 根據查詢出來的學生的tid,尋找對應的老師!  子查詢    -->    <select id="getStudent" resultMap="StudentTeacher">        select * from student    </select>    <resultMap id="StudentTeacher" type="Student">        <!--        <result property="id" column="id"/>        <result property="name" column="name"/>        -->        <!--復雜的屬性,我們需要單獨處理        物件: association        集合: collection -->        <association property="hr" column="tid" javaType="Teacher" select="getTeacher"/>    </resultMap>    <select id="getTeacher" resultType="Teacher">        select * from teacher where id = #{id}    </select>

按照結果嵌套處理

(別名sid,sname,tname)

<!--按照結果嵌套處理--><select id="getStudent2" resultMap="StudentTeacher2">    select s.id sid,s.sid sname,t.name tname    from student s,teacher t    where s.tid = t.id;</select><resultMap id="StudentTeacher2" type="Student">    <result property="id" column="sid"/>    <result property="name" column="sname"/>    <association property="teacher" javaType="Teacher">        <result property="name" column="tname"/>    </association></resultMap>

回顧Mysql 多對一查詢方式:

  • 子查詢
  • 聯表查詢

11、一對多處理

比如:一個老師擁有多個學生!

對于老師而言,就是一對多的關系!

環境搭建

  1. 環境搭建,和剛才一樣

物體類

@Datapublic class Student {    private int id;    private String name;    private int tid;}
@Datapublic class Teacher {    private int id;    private String name;    //一個老師擁有多個學生    private List<Student> students;}

按照結果嵌套處理

   <!--按結果嵌套查詢-->    <select id="getTeacherStudent" resultMap="TeacherStudent">        select s.id sid, s.name sname, t.name tname,t.id tid        from student s,teacher t        where s.tid = t.id and t.id = #{tid}    </select>    <resultMap id="TeacherStudent" type="Teacher">        <result property="id" column="tid"/>        <result property="name" column="tname"/>        <!--復雜的屬性,我們需要單獨處理 物件: association 集合: collection        javaType:指定屬性的型別!        ofType:集合中的泛型資訊        -->        <collection property="students" ofType="Student">            <result property="id" column="sid"/>            <result property="name" column="sname"/>            <result property="tid" column="tid"/>        </collection>    </resultMap>

按照查詢嵌套處理

<!--按照查詢嵌套處理--><select id="getTeacher2" resultMap="TeacherStudent2">    select * from mybatis.teacher where id = #{tid}</select><resultMap id="TeacherStudent2" type="Teacher">    <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/></resultMap><select id="getStudentByTeacherId" resultType="Student">    select * from mybatis.student where tid = #{tid}</select>

小結

  1. 關聯 - association 【多對一】
  2. 集合 - collection 【一對多】
  3. javaType & ofType
    1. JavaType 用來指定物體類中屬性的型別
    2. ofType 用來指定映射到List或者集合中的 pojo型別,泛型中的約束型別!

注意點:

  • 保證SQL的可讀性,盡量保證通俗易懂
  • 注意一對多和多對一中,屬性名和欄位的問題!
  • 如果問題不好排查錯誤,可以使用日志 , 建議使用 Log4j

慢SQL 1s 1000s

面試高頻

  • Mysql引擎
  • InnoDB底層原理
  • 索引
  • 索引優化!

12、動態 SQL

什么是動態SQL:動態SQL就是指根據不同的條件生成不同的SQL陳述句

利用動態 SQL 這一特性可以徹底擺脫這種痛苦,

動態 SQL 元素和 JSTL 或基于類似 XML 的文本處理器相似,在 MyBatis 之前的版本中,有很多元素需要花時間了解,MyBatis 3 大大精簡了元素種類,現在只需學習原來一半的元素便可,MyBatis 采用功能強大的基于 OGNL 的運算式來淘汰其它大部分元素,ifchoose (when, otherwise)trim (where, set)foreach

搭建環境

CREATE TABLE `blog` (  `id` varchar(50) NOT NULL COMMENT '博客id',  `title` varchar(100) NOT NULL COMMENT '博客標題',  `author` varchar(30) NOT NULL COMMENT '博客作者',  `create_time` datetime NOT NULL COMMENT '創建時間',  `views` int(30) NOT NULL COMMENT '瀏覽量') ENGINE=InnoDB DEFAULT CHARSET=utf8

創建一個基礎工程

  1. 導包

  2. 撰寫組態檔

  3. 撰寫物體類

    @Datapublic class Blog {    private String id;    private String title;    private String author;    private Date createTime;//屬性名與欄位名不一致    private int views;        }
    
  4. 撰寫物體類對應Mapper介面 和 Mapper.XML檔案

    createTime與資料庫的列名 create_time

       <settings>       <!-- <setting name="logImpl" value="https://www.cnblogs.com/pxlsdz/p/STDOUT_LOGGING"/>-->        <setting name="logImpl" value="https://www.cnblogs.com/pxlsdz/p/LOG4j"/>        <!--	是否開啟駝峰命名自動映射,即從經典資料庫列名 A_COLUMN 映射到經典 Java 屬性名 aColumn,-->        <setting name="mapUnderscoreToCamelcase" value="https://www.cnblogs.com/pxlsdz/p/true"/>    </settings>
    

插入資料

  @Test    public void addBlog(){        SqlSession sqlSession = MybatisUtils.getSession();        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);        Blog blog = new Blog();        blog.setId(IDutils.getId());        blog.setTitle("Mybatis 如此簡單");        blog.setAuthor("sdz");        blog.setCreateTime(new Date());        blog.setViews(9999);        mapper.addBlog(blog);        blog.setId(IDutils.getId());        blog.setTitle("Spring 如此簡單");        blog.setAuthor("sdz");        blog.setCreateTime(new Date());        blog.setViews(9999);        mapper.addBlog(blog);        blog.setId(IDutils.getId());        blog.setTitle("SpringMVC 如此簡單");        blog.setAuthor("sdz");        blog.setCreateTime(new Date());        blog.setViews(9999);        mapper.addBlog(blog);        sqlSession.close();    }

IF

<select id="queryBlogIF" parameterType="map" resultType="blog">    select * from mybatis.blog where 1=1    <if test="title != null">        and title = #{title}    </if>    <if test="author != null">        and author = #{author}    </if></select>

where 1=1 可以保證sql陳述句憑借正確(不然會出現where and),或者用下述方法的where標簽,

test

  @Test    public void queryBlogIF(){        SqlSession sqlSession = MybatisUtils.getSession();        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);        Map map = new HashMap();        //map.put("title", "Mybatis 如此簡單");        map.put("author", "sdz");        List<Blog> blogs = mapper.queryBlogIF(map);        for (Blog blog: blogs) {            System.out.println(blog);        }        sqlSession.close();    }

choose (when, otherwise)

    <select id="queryBlogChoose" parameterType="map" resultType="blog">        select * from mybatis.blog        <where>            <choose>                <when test="title != null">                    title = #{title}                </when>                <when test="author != null">                    and author = #{author}                </when>                <otherwise>                    and views = #{views}                </otherwise>            </choose>        </where>    </select>

where元素只會在至少有一個子元素的條件回傳SQL子句的情況下才去插入"WHERE"子句,而且,若陳述句的開頭為"AND"或“OR", where 元素也會將它們去除,如下,對于第一個if查詢這么修改,

set元素會動態前置SET關鍵字,同時也會刪掉無關的逗號

trim (where,set)

select * from mybatis.blog<where>    <if test="title != null">        title = #{title}    </if>    <if test="author != null">        and author = #{author}    </if></where>
<update id="updateBlog" parameterType="map">    update mybatis.blog    <set>        <if test="title != null">            title = #{title},        </if>        <if test="author != null">            author = #{author}        </if>    </set>    where id = #{id}</update>

如果 where 元素與你期望的不太一樣,你也可以通過自定義 trim 元素來定制 where 元素的功能,比如,和 where 元素等價的自定義 trim 元素為:

<trim prefix="WHERE" prefixOverrides="AND |OR ">  ...</trim>

prefixOverrides 屬性會忽略通過管道符分隔的文本序列(注意此例中的空格是必要的),上述例子會移除所有 prefixOverrides 屬性中指定的內容,并且插入 prefix 屬性中指定的內容,

set 元素會動態地在行首插入 SET 關鍵字,并會刪掉額外的逗號(這些逗號是在使用條件陳述句給列賦值時引入的),

來看看與 set 元素等價的自定義 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">  ...</trim>

注意,我們覆寫了后綴值設定,并且自定義了前綴值,

所謂的動態SQL,本質還是SQL陳述句 , 只是我們可以在SQL層面,去執行一個邏輯代碼

if

where , set , choose ,when

SQL片段

有的時候,我們可能會將一些功能的部分抽取出來,方便復用!

  1. 使用SQL標簽抽取公共的部分

    <sql id="if-title-author">    <if test="title != null">        and title = #{title}    </if>    <if test="author != null">        and author = #{author}    </if></sql>
    
  2. 在需要使用的地方使用Include標簽參考即可

    <select id="queryBlogIF" parameterType="map" resultType="blog">    select * from mybatis.blog    <where>        <include refid="if-title-author"></include>    </where></select>
    

注意事項:

  • 最好基于單表來定義SQL片段!
  • 不要存在where標簽

Foreach

select * from user where 1=1 and   <foreach item="id" collection="ids"      open="(" separator="or" close=")">        #{id}  </foreach>(id=1 or id=2 or id=3)

1569979229205

1569979339190

<!--        select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)        我們現在傳遞一個萬能的map , 這map中可以存在一個集合!--><select id="queryBlogForeach" parameterType="map" resultType="blog">    select * from mybatis.blog    <where>        <foreach collection="ids" item="id" open="and (" close=")" separator="or">            id = #{id}        </foreach>    </where></select>

test

    @Test    public void queryBlogForeach(){        SqlSession sqlSession = MybatisUtils.getSession();        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);        Map map = new HashMap();        ArrayList<Integer> ids = new ArrayList<Integer>();        ids.add(1);        ids.add(2);        map.put("ids", ids);        List<Blog> blogs = mapper.queryBlogForeach(map);        for (Blog blog: blogs) {            System.out.println(blog);        }        sqlSession.close();    }

動態SQL就是在拼接SQL陳述句,我們只要保證SQL的正確性,按照SQL的格式,去排列組合就可以了

建議:

  • 現在Mysql中寫出完整的SQL,再對應的去修改成為我們的動態SQL實作通用即可!

13、快取 (了解)

13.1、簡介

查詢  :  連接資料庫 ,耗資源!	一次查詢的結果,給他暫存在一個可以直接取到的地方!--> 記憶體 : 快取	我們再次查詢相同資料的時候,直接走快取,就不用走資料庫了
  1. 什么是快取 [ Cache ]?

    • 存在記憶體中的臨時資料,
    • 將用戶經常查詢的資料放在快取(記憶體)中,用戶去查詢資料就不用從磁盤上(關系型資料庫資料檔案)查詢,從快取中查詢,從而提高查詢效率,解決了高并發系統的性能問題,
  2. 為什么使用快取?

    • 減少和資料庫的互動次數,減少系統開銷,提高系統效率,
  3. 什么樣的資料能使用快取?

    • 經常查詢并且不經常改變的資料,【可以使用快取】

13.2、Mybatis快取

  • MyBatis包含一個非常強大的查詢快取特性,它可以非常方便地定制和配置快取,快取可以極大的提升查詢效率,

  • MyBatis系統中默認定義了兩級快取:一級快取二級快取

    • 默認情況下,只有一級快取開啟,(SqlSession級別的快取,也稱為本地快取)

    • 二級快取需要手動開啟和配置,他是基于namespace級別的快取,

    • 為了提高擴展性,MyBatis定義了快取介面Cache,我們可以通過實作Cache介面來自定義二級快取

13.3、一級快取

  • 一級快取也叫本地快取: SqlSession
    • 與資料庫同一次會話期間查詢到的資料會放在本地快取中,
    • 以后如果需要獲取相同的資料,直接從快取中拿,沒必須再去查詢資料庫;

測驗步驟:

  1. 開啟日志!
  2. 測驗在一個Sesion中查詢兩次相同記錄
  3. 查看日志輸出

1569983650437

快取失效的情況:

  1. 查詢不同的東西

  2. 增刪改操作,可能會改變原來的資料,所以必定會重繪快取!

    1569983952321

  3. 查詢不同的Mapper.xml

  4. 手動清理快取!

    1569984008824

小結:一級快取默認是開啟的,只在一次SqlSession中有效,也就是拿到連接到關閉連接這個區間段!

一級快取就是一個Map,

13.4、二級快取

  • 二級快取也叫全域快取,一級快取作用域太低了,所以誕生了二級快取
  • 基于namespace級別的快取,一個名稱空間,對應一個二級快取;
  • 作業機制
    • 一個會話查詢一條資料,這個資料就會被放在當前會話的一級快取中;
    • 如果當前會話關閉了,這個會話對應的一級快取就沒了;但是我們想要的是,會話關閉了,一級快取中的資料被保存到二級快取中;
    • 新的會話查詢資訊,就可以從二級快取中獲取內容;
    • 不同的mapper查出的資料會放在自己對應的快取(map)中;

步驟:

  1. 開啟全域快取

    <!--顯示的開啟全域快取--><setting name="cacheEnabled" value="https://www.cnblogs.com/pxlsdz/p/true"/>
    
  2. 在要使用二級快取的Mapper中開啟

    <!--在當前Mapper.xml中使用二級快取--><cache/>
    

    也可以自定義引數

    <!--在當前Mapper.xml中使用二級快取--><cache  eviction="FIFO"       flushInterval="60000"       size="512"       readOnly="true"/>
    
  3. 測驗

    1. 問題:我們需要將物體類序列化!否則就會報錯!

      Caused by: java.io.NotSerializableException: com.kuang.pojo.User
      

小結:

  • 只要開啟了二級快取,在同一個Mapper下就有效
  • 所有的資料都會先放在一級快取中;
  • 只有當會話提交,或者關閉的時候,才會提交到二級緩沖中!

13.5、快取原理

1569985541106

13.6、自定義快取-ehcache

Ehcache是一種廣泛使用的開源Java分布式快取,主要面向通用快取

要在程式中使用ehcache,先要導包!

<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache --><dependency>    <groupId>org.mybatis.caches</groupId>    <artifactId>mybatis-ehcache</artifactId>    <version>1.1.0</version></dependency>

在mapper中指定使用我們的ehcache快取實作!

<!--在當前Mapper.xml中使用二級快取--><cache type="org.mybatis.caches.ehcache.EhcacheCache"/>

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"         updateCheck="false">    <!--       diskStore:為快取路徑,ehcache分為記憶體和磁盤兩級,此屬性定義磁盤的快取位置,引數解釋如下:       user.home – 用戶主目錄       user.dir  – 用戶當前作業目錄       java.io.tmpdir – 默認臨時檔案路徑     -->    <diskStore path="./tmpdir/Tmp_EhCache"/>        <defaultCache            eternal="false"            maxElementsInMemory="10000"            overflowToDisk="false"            diskPersistent="false"            timeToIdleSeconds="1800"            timeToLiveSeconds="259200"            memoryStoreEvictionPolicy="LRU"/>     <cache            name="cloud_user"            eternal="false"            maxElementsInMemory="5000"            overflowToDisk="false"            diskPersistent="false"            timeToIdleSeconds="1800"            timeToLiveSeconds="1800"            memoryStoreEvictionPolicy="LRU"/>    <!--       defaultCache:默認快取策略,當ehcache找不到定義的快取時,則使用這個快取策略,只能定義一個,     -->    <!--      name:快取名稱,      maxElementsInMemory:快取最大數目      maxElementsOnDisk:硬碟最大快取個數,      eternal:物件是否永久有效,一但設定了,timeout將不起作用,      overflowToDisk:是否保存到磁盤,當系統當機時      timeToIdleSeconds:設定物件在失效前的允許閑置時間(單位:秒),僅當eternal=false物件不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大,      timeToLiveSeconds:設定物件在失效前允許存活時間(單位:秒),最大時間介于創建時間和失效時間之間,僅當eternal=false物件不是永久有效時使用,默認是0.,也就是物件存活時間無窮大,      diskPersistent:是否快取虛擬機重啟期資料 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.      diskSpoolBufferSizeMB:這個引數設定DiskStore(磁盤快取)的快取區大小,默認是30MB,每個Cache都應該有自己的一個緩沖區,      diskExpiryThreadIntervalSeconds:磁盤失效執行緒運行時間間隔,默認是120秒,      memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理記憶體,默認策略是LRU(最近最少使用),你可以設定為FIFO(先進先出)或是LFU(較少使用),      clearOnFlush:記憶體數量最大時是否清除,      memoryStoreEvictionPolicy:可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數),      FIFO,first in first out,這個是大家最熟的,先進先出,      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一點就是講一直以來最少被使用的,如上面所講,快取的元素有一個hit屬性,hit值最小的將會被清出快取,      LRU,Least Recently Used,最近最少使用的,快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那么現有快取元素中時間戳離當前時間最遠的元素將被清出快取,   --></ehcache>

Redis資料庫來做快取! K-V

練習:29道練習題實戰!

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

標籤:Java

上一篇:python爬蟲學習--爬好看網視頻

下一篇:eclipse-SSM框架整合及實作增刪改查

標籤雲
其他(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