1.什么是 MyBatis?
- MyBatis 是一款優秀的持久層框架(持久層,可以理解成資料 保存在 資料庫或者 硬碟一類可以保存很長時間的設備里面).
- 它支持自定義 SQL、存盤程序以及高級映射,
- MyBatis 免除了幾乎所有的 JDBC 代碼以及設定引數和獲取結果集的作業,MyBatis 可以通過簡單的 XML 或注解來配置和映射原始型別、介面和 Java POJO(Plain Old Java Objects,普通老式 Java 物件)為資料庫中的記錄,
1.2 持久化
記憶體:斷電即失
所以持久化 能把資料保存在磁盤上面
1.3 持久層
完成持久化作業的代碼塊
1.4 為什么要用Mybatis
JDBC代碼太復雜,框架更簡單
- 簡單易學:
- 靈活:
- 解除sql與程式代碼的耦合:通過提供DAO層,將業務邏輯和資料訪問邏輯分離,使系統的設計更清晰,更易維護,更易單元測驗,sql和代碼的分離,提高了可維護性,
- 提供映射標簽,支持物件與資料庫的orm欄位關系映射
- 提供物件關系映射標簽,支持物件關系組建維護
- 提供xml標簽,支持撰寫動態sql,
2.第一個Mybatis程式
思想

2.1搭建資料庫
use mybatis;
CREATE TABLE user(
id INT PRIMARY KEY,
name VARCHAR(20),
pwd VARCHAR(20)
)ENGINE=INNODB DEFAULT charset=utf8;
INSERT INTO `user`(NAME,pwd) VALUES
("chen1","123456"),
("chen2","123456"),
("chen3","123456")
2.2 配置mybatis
1.mybatis組態檔 mybatis-config.xml
作用: SqlSessionFactoryBuilder 則可以從 XML 組態檔或一個預先配置的 Configuration 實體來構建出 SqlSessionFactory 實體,
<?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="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="https://www.cnblogs.com/firsthelloworld/p/${driver}"/>
<property name="url" value="https://www.cnblogs.com/firsthelloworld/p/${url}"/>
<property name="username" value="https://www.cnblogs.com/firsthelloworld/p/${username}"/>
<property name="password" value="https://www.cnblogs.com/firsthelloworld/p/${password}"/>
</dataSource>
</environment>
</environments>
-----------注冊-------------
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
2.構建sqlSessionFactory物件
作用:獲取SqlSession物件(SqlSession 提供了在資料庫執行 SQL 命令所需的所有方法,你可以通過 SqlSession 實體來直接執行已映射的 SQL 陳述句)
public class SqlSeeionUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSessionFactory getSqlSessionFactory(){
return sqlSessionFactory;
}
}
public class UserDaoTest {
@Test
public void test1(){
SqlSessionFactory sqlSessionFactory = SqlSeeionUtils.getSqlSessionFactory();
//獲得sqlSession物件
SqlSession sqlSession = sqlSessionFactory.openSession();
//sqlSession物件 獲得數操作SQL陳述句操作物件 Mapper
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> allUsers = mapper.getAllUsers();
for (User allUser : allUsers) {
System.out.println(allUser);
}
}
}
4.SqlSession物件
-
增刪改 必須需要事務,默認自動提交事務關閉的,需要在sqlSessionFactory.openSession(true);開啟
? sqlSession.commit();
5.映射器.xml檔案和 dao介面
通過 id = dao介面方法名 和 namespace 連接起來
<mapper namespace="com.cb.dao.UserDao">
<select id="getAllUsers" resultType="com.cb.pojo.User">
select * from user
</select>
</mapper>
3.xml組態檔
- configuration(配置)
- properties(屬性)
- ? settings(設定)
- ? typeAliases(型別別名)
- ? typeHandlers(型別處理器)
- ? objectFactory(物件工廠)
- ? plugins(插件)
- ? environments(環境配置)
- ? environment(環境變數)
- ? transactionManager(事務管理器)
- ? dataSource(資料源)
- ? databaseIdProvider(資料庫廠商標識)
- ? mappers(映射器)
environments(環境配置)
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="..." value="https://www.cnblogs.com/firsthelloworld/p/..."/>
</transactionManager>
<dataSource type="POOLED">
<property name="driver" value="https://www.cnblogs.com/firsthelloworld/p/${driver}"/>
<property name="url" value="https://www.cnblogs.com/firsthelloworld/p/${url}"/>
<property name="username" value="https://www.cnblogs.com/firsthelloworld/p/${username}"/>
<property name="password" value="https://www.cnblogs.com/firsthelloworld/p/${password}"/>
</dataSource>
</environment>
</environments>
MyBatis 可以配置成適應多種環境,不過要記住:盡管可以配置多個環境,但每個 SqlSessionFactory 實體只能選擇一種環境,
如果忽略了環境引數,那么將會加載默認環境.
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environment);
事務管理器(transactionManager)
在 MyBatis 中有兩種型別的事務管理器(也就是 type="[JDBC|MANAGED]"):
- JDBC – 這個配置直接使用了 JDBC 的提交和回滾設施,它依賴從資料源獲得的連接來管理事務作用域,
<transactionManager type="MANAGED">
<property name="closeConnection" value="https://www.cnblogs.com/firsthelloworld/p/false"/>
</transactionManager>
如果你正在使用 Spring + MyBatis,則沒有必要配置事務管理器,因為 Spring 模塊會使用自帶的管理器來覆寫前面的配置,
資料源(dataSource)
dataSource 元素使用標準的 JDBC 資料源介面來配置 JDBC 連接物件的資源,
有三種內建的資料源型別(也就是 type="[UNPOOLED|POOLED|JNDI]"):
添加其他資料源
<dataSource type="org.myproject.C3P0DataSourceFactory">
<property name="driver" value="https://www.cnblogs.com/firsthelloworld/p/org.postgresql.Driver"/>
<property name="url" value="https://www.cnblogs.com/firsthelloworld/p/jdbc:postgresql:mydb"/>
<property name="username" value="https://www.cnblogs.com/firsthelloworld/p/postgres"/>
<property name="password" value="https://www.cnblogs.com/firsthelloworld/p/root"/>
</dataSource>
屬性(properties)
<properties resource="db.properties">
</properties>
后面的就可以使用 ${driver}去參考
優先使用resource="db.properties"匯入的
型別別名(typeAliases)
型別別名可為 Java 型別設定一個縮寫名字, 它僅用于 XML 配置,意在降低冗余的全限定類名書寫,例如:
單個
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
</typeAliases>
使用包
<typeAliases>
<package name="domain.blog"/>
</typeAliases>
使用注解
@Alias("author")
public class Author {
...
}
設定(settings)
這是 MyBatis 中極為重要的調整設定,它們會改變 MyBatis 的運行時行為, 下表描述了設定中各項設定的含義、默認值等,
| 設定名 | 描述 | 有效值 | 默認值 |
|---|---|---|---|
| cacheEnabled | 全域性地開啟或關閉所有映射器組態檔中已配置的任何快取, | true | false | true |
| lazyLoadingEnabled | 延遲加載的全域開關,當開啟時,所有關聯物件都會延遲加載, 特定關聯關系中可通過設定 fetchType 屬性來覆寫該項的開關狀態, |
true | false | false |
| logImpl | 指定 MyBatis 所用日志的具體實作,未指定時將自動查找, | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未設定 |
| mapUnderscoreToCamelCase | 是否開啟駝峰命名自動映射,即從經典資料庫列名 A_COLUMN 映射到經典 Java 屬性名 aColumn, | true | false | False |
映射器(mappers)注冊
<!-- 使用相對于類路徑的資源參考 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
//需要在同一個包下面,且介面和.xml檔案同名
<!-- 使用映射器介面實作類的完全限定類名 -->
<mappers>
<mapper />
<mapper />
<mapper />
</mappers>
<!-- 將包內的映射器介面實作全部注冊為映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
4.xml映射器
引數
parameterType |
將會傳入這條陳述句的引數的類全限定名或別名,這個屬性是可選的,因為 MyBatis 可以通過型別處理器(TypeHandler)推斷出具體傳入陳述句的引數,默認值為未設定(unset), |
|---|---|
| #{},${} | #{}防止SQL注入, |
| @Param("") | 定義別名,給傳引數用, |
引數是map
SqlSessionFactory sqlSessionFactory = SqlSeeionUtils.getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
// List<User> allUsers = mapper.getAllUsers();
// for (User allUser : allUsers) {
// System.out.println(allUser);
// }
HashMap<String, Object> map = new HashMap<>();
map.put("userName","aaa");
map.put("password","21321");
mapper.addUser(map);
sqlSession.commit();
sqlSession.close();
<insert id="addUser" parameterType="map">
insert into mybatis.user(name,pwd) values (#{userName},#{password})
</insert>
結果映射resultMap
解決 資料庫欄位 和 屬性 不一致的問題 ,可以把資料庫查詢出來的資料進行封裝成pojo,
resultType只是 簡單的資料回傳
1.解決欄位名和屬性名不一致
-----------取別名-----
<select id="getAllUsers" resultType="com.cb.pojo.User">
select id,name,pwd as password from user
</select>
-----------結果集映射-----
<resultMap id="Users" type="com.cb.pojo.User">
<result column="pwd" property="password"/>
</resultMap>
2.一對多和多對一
回傳映射是一個物件用 association
回傳映射是一個集合用 collection
多對一:多個學生對應一個老師,即
public class Student {
private int id;
private String name;
private Teacher teacher;
}
<resultMap id="stu" type="com.cb.pojo.Student">
<id property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" javaType="com.cb.pojo.Teacher">
<id property="id" column="tid"/>
<result property="name" column="tName"/>
</association>
</resultMap>
<select id="getAllStus" resultMap="stu">
select t.id as tid ,t.name as tName ,s.id,s.name from teacher t left join student s on s.tid = t.id;
</select>
一對多:一個老師對應多個學生,即
@Data
public class Teacher {
private int id;
private String name;
private List<Student> stus;
}
<resultMap id="tea" type="com.cb.pojo.Teacher">
<id column="tid" property="id"/>
<result property="name" column="tname"/>
<collection property="stus" ofType="com.cb.pojo.Student">
<id column="sid" property="id"/>
<result property="name" column="sname"/>
</collection>
</resultMap>
<select id="getAllTea" resultMap="tea">
select t.id tid ,t.name tname ,s.id sid ,s.name sname ,s.tid stid
from teacher t left join student s
on s.tid = t.id;
</select>
5.日志
用來記錄 SQL操作
mybatis 默認提供
| logImpl | 指定 MyBatis 所用日志的具體實作,未指定時將自動查找, | SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING | 未設定 |
|---|---|---|---|
-
SLF4J (掌握)
-
LOG4J
-
LOG4J2
-
JDK_LOGGING
-
COMMONS_LOGGING
-
STDOUT_LOGGING 標準輸出
<settings> <setting name="logImpl" value="https://www.cnblogs.com/firsthelloworld/p/STDOUT_LOGGING"/> </settings> 控制臺 顯示 Created connection 1166151249. Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@45820e51] ==> Preparing: select * from user ==> Parameters: <== Columns: id, name, pwd <== Row: 1, chen1, 123456 <== Row: 2, chen2, 123456 <== Row: 3, chen3, 123456 <== Row: 5, aaa, 21321 <== Total: 4 -
NO_LOGGING
LOG4J
-
控制日志資訊輸送的目的地是控制臺、檔案、GUI組件,甚至是套介面服務器、NT的事件記錄器、UNIX Syslog守護行程等;
-
控制每一條日志的輸出格式;
-
通過定義每一條日志資訊的級別,我們能夠更加細致地控制日志的生成程序
-
通過一個組態檔來靈活地進行配置
匯入log4j的包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
組態檔log4j.properties
#將等級為DEBUG的日志資訊輸出到console和file這兩個目的地,console和file的定義在下面的代碼
log4j.rootLogger=DEBUG,console,file
#控制臺輸出的相關設定
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n
#檔案輸出的相關設定
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n
#日志輸出級別
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
使用log4j
Logger logger = Logger.getLogger(UserDaoTest.class);
logger.info("info------------");
logger.error("info------------");
logger.debug("info------------");
-------------顯示 檔案和控制臺----------
[INFO][20-07-29][com.cb.dao.UserDaoTest]info------------
[ERROR][20-07-29][com.cb.dao.UserDaoTest]info------------
[DEBUG][20-07-29][com.cb.dao.UserDaoTest]info------------
6.分頁
1.使用limit進行分頁
<select id="getUserBylimit" resultType="com.cb.pojo.User" parameterType="map">
select * from user limit #{indexStart} , #{pageSize}
</select>
2.pageHelper插件
1. 使用 Maven
在 pom.xml 中添加如下依賴:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>最新版本</version>
</dependency>
最新版本號可以從首頁查看,
2. 配置攔截器插件
特別注意,新版攔截器是 com.github.pagehelper.PageInterceptor, com.github.pagehelper.PageHelper 現在是一個特殊的 dialect 實作類,是分頁插件的默認實作類,提供了和以前相同的用法,
1. 在 MyBatis 配置 xml 中配置攔截器插件
<!--
plugins在組態檔中的位置必須符合要求,否則會報錯,順序如下:
properties?, settings?,
typeAliases?, typeHandlers?,
objectFactory?,objectWrapperFactory?,
plugins?,
environments?, databaseIdProvider?, mappers?
-->
<plugins>
<!-- com.github.pagehelper為PageHelper類所在包名 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- 使用下面的方式配置引數,后面會有所有的引數介紹 -->
<property name="param1" value="https://www.cnblogs.com/firsthelloworld/p/value1"/>
</plugin>
</plugins>
3. 分頁插件引數介紹
3.代碼中使用
//第三種,Mapper介面方式的呼叫,推薦這種使用方式,
PageHelper.offsetPage(1, 10);
List<Country> list = countryMapper.selectIf(1);
7.注解開發
面向介面開發
代碼實作
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
8.Lombok
Lombok專案是一個Java庫,它會自動插入編輯器和構建工具中,Lombok提供了一組有用的注釋,用來消除Java類中的大量樣板代碼,僅五個字符(@Data)就可以替換數百行代碼從而產生干凈,簡潔且易于維護的Java類,
常用注解:
@常用注解:
@Setter :注解在類或欄位,注解在類時為所有欄位生成setter方法,注解在欄位上時只為該欄位生成setter方法,
@Getter :使用方法同上,區別在于生成的是getter方法,
@ToString :注解在類,添加toString方法,
@EqualsAndHashCode: 注解在類,生成hashCode和equals方法,
@NoArgsConstructor: 注解在類,生成無參的構造方法,
@RequiredArgsConstructor: 注解在類,為類中需要特殊處理的欄位生成構造方法,比如final和被@NonNull注解的欄位,
@AllArgsConstructor: 注解在類,生成包含類中所有欄位的構造方法,
@Data: 注解在類,生成setter/getter、equals、canEqual、hashCode、toString方法,如為final屬性,則不會為該屬性生成setter方法,
@Slf4j: 注解在類,生成log變數,嚴格意義來說是常量,
9.動態SQL
能夠根據不同的條件 構建出 不同的SQL陳述句
if
判斷條件是否滿足 ,滿足就使用,
<select id="getIf" resultType="com.cb.pojo.Blog" parameterType="map" >
select * from blog where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="title != null">
and author= #{author}
</if>
</select>
判斷不為null 且 不為空字串
<if test="keyword != null and keyword != ''">
AND user_id = #{keyword}
</if>
choose (when, otherwise)
從幾個條件選擇 一個條件出來:
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
trim (where, set)
where 標簽 : where 元素只會在子元素回傳任何內容的情況下才插入 “WHERE” 子句,而且,若子句的開頭為 “AND” 或 “OR”,where 元素也會將它們去除,
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
set 跟 update一起用
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
trim標簽:用來重新定義set 和 where標簽
<trim prefix="SET" suffixOverrides=",">
...
</trim>
foreach
動態 SQL 的另一個常見使用場景是對集合進行遍歷(尤其是在構建 IN 條件陳述句的時候),比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
你可以將任何可迭代物件(如 List、Set 等)、Map 物件或者陣列物件作為集合引數傳遞給 foreach,當使用可迭代物件或者陣列時,index 是當前迭代的序號,item 的值是本次迭代獲取到的元素,當使用 Map 物件(或者 Map.Entry 物件的集合)時,index 是鍵,item 是值,
bind
bind 元素允許你在 OGNL 運算式以外創建一個變數,并將其系結到當前的背景關系,比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
_parameter代表那個引數(傳遞過來的引數) '%' + #{name} + '%' _parameter.getName()
案例:
<select id="getUserByName" resultType="com.cb.pojo.User" parameterType="string" >
<bind name="name1" value="'%'+_parameter+'%'"/>
select * from user
where name like #{name1}
</select>
傳遞多個引數
//模糊查詢
List<User> likeByNameOrIponeCode(@Param("name") String name,@Param("ipone") String iponeCode);
<select id="likeByNameOrIponeCode" parameterType="string" resultType="com.cb.pojo.User">
<bind name="_name" value="https://www.cnblogs.com/firsthelloworld/p/'%'+ name +'%'"/>
<bind name="_ipone" value="https://www.cnblogs.com/firsthelloworld/p/'%' + ipone +'%'"/>
SELECT * from t_user
<where>
<if test=" name != null and name!=''">
username like #{_name}
</if>
<if test="ipone != null and ipone!='' ">
or phoneCode like #{_ipone}
</if>
</where>
</select>
10.快取
作用:
-
把查詢出來的資料 快取到記憶體里面
-
再次使用時,就可以不用從關系資料庫里面查詢,提高查詢效率,
-
一般快取不經常改變的資料
-
所有快取都放在以及快取,當SqlSession關閉時,才會轉移到二級快取
mybatis快取
- 默認開啟一級快取
一級快取
Mybatis對快取提供支持,但是在沒有配置的默認情況下,它只開啟一級快取,一級快取只是相對于同一個SqlSession而言,所以在引數和SQL完全一樣的情況下,我們使用同一個SqlSession物件呼叫一個Mapper方法,往往只執行一次SQL,因為使用SelSession第一次查詢后,MyBatis會將其放在快取中,以后再查詢的時候,如果沒有宣告需要重繪,并且快取沒有超時的情況下,SqlSession都會取出當前快取的資料,而不會再次發送SQL到資料庫,

為什么要使用一級快取,不用多說也知道個大概,但是還有幾個問題我們要注意一下,
1、一級快取的生命周期有多長?
每一個請求都都會 開啟一個一個新的SqlSession物件
a、MyBatis在開啟一個資料庫會話時,會 創建一個新的SqlSession物件,SqlSession物件中會有一個新的Executor物件,Executor物件中持有一個新的PerpetualCache物件;當會話結束時,SqlSession物件及其內部的Executor物件還有PerpetualCache物件也一并釋放掉,
b、如果SqlSession呼叫了close()方法,會釋放掉一級快取PerpetualCache物件,一級快取將不可用,
c、如果SqlSession呼叫了clearCache(),會清空PerpetualCache物件中的資料,但是該物件仍可使用,
d、SqlSession中執行了任何一個update操作(update()、delete()、insert()) ,都會清空PerpetualCache物件的資料,但是該物件可以繼續使用
二級快取:
MyBatis的二級快取是namespece級別的快取,它可以提高對資料庫查詢的效率,以提高應用的性能,
? 意思是 新來的請求也可以拿到快取,如果在同一個Mapper下
MyBatis的快取機制整體設計以及二級快取的作業模式

SqlSessionFactory層面上的二級快取默認是不開啟的,二級快取的開席需要進行配置,實作二級快取的時候,MyBatis要求回傳的POJO必須是可序列化的, 也就是要求實作Serializable介面,配置方法很簡單,只需要在映射XML檔案配置就可以開啟快取了
- 映射陳述句檔案中的所有select陳述句將會被快取,
- 映射陳述句檔案中的所欲insert、update和delete陳述句會重繪快取,
- 快取會使用默認的Least Recently Used(LRU,最近最少使用的)演算法來識訓,
- 根據時間表,比如No Flush Interval,(CNFI沒有重繪間隔),快取不會以任何時間順序來重繪,
- 快取會存盤串列集合或物件(無論查詢方法回傳什么)的1024個參考
- 快取會被視為是read/write(可讀/可寫)的快取,意味著物件檢索不是共享的,而且可以安全的被呼叫者修改,不干擾其他呼叫者或執行緒所做的潛在修改,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/116787.html
標籤:Java
上一篇:static關鍵字設計原理
下一篇:Reactor反應器模式
