日誌
如果一個數據庫的操作出現了異常,這時候我們需要排錯,日誌就是最好的助手。
之前使用的是輸出語句或者debug。現在使用的是日誌工廠。
在MyBatis中具體使用哪一個日誌實現,在設置中進行設定即可。在設定的時候注意區分大小寫。
STDOUT_LOGGING
STDOUT_LOGGING標準日誌輸出。
在MyBatis核心配置文件中,配置日誌。
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Log4j
Log4j 是Apache的一個開源項目,通過使用Log4j,我們可以控制日誌信息輸送的目的地是控制檯、文件、GUI組件。
我們可以控制每一條日誌的輸出格式。
通過定義每一條日誌信息的級別,我們能夠更加細緻地控制日誌的生成過程。
通過一個配置文件來靈活地進行配置,而不需要修改應用的代碼。
1、導入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.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/llx.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
3、在覈心配置文件中配置log4j爲日誌的實現
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
4、測試代碼,可以看到日誌的輸出結果
log4j的使用:
-
在要使用Log4j 的類中,導入包 import org.apache.log4j.Logger;
-
日誌對象,參數爲當前類的class
static Logger logger = Logger.getLogger(UserDaoTest.class);
-
日誌級別
logger.info("info:進入了testLog4j"); logger.debug("debug:進入了testLog4j"); logger.error("error:進入了testLog4j");
分頁
使用分頁可以減少數據的處理量。
limit分頁
limit語法:
SELECT * from user limit startIndex,pageSize;
SELECT * from user limit 3; #[0,n]
使用Mybatis實現分頁:
1、編寫接口方法
List<User> getUserByLimit(Map<String,Integer> map);
2、編寫Mapper.xml文件
<!--//分頁-->
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
select * from mybatis.user limit #{startIndex},#{pageSize}
</select>
3、測試
@Test
public 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();
}
RowBounds分頁
不使用SQL實現分頁,使用RowBounds進行分頁。
1、編寫接口方法
List<User> getUserByRowBounds();
2、編寫Mapper.xml文件
<select id="getUserByRowBounds" resultMap="UserMap">
select * from mybatis.user
</select>
3、測試
@Test
public void getUserByRowBounds(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//RowBounds實現
RowBounds rowBounds = new RowBounds(1, 2);
//通過Java代碼層面實現分頁
List<User> userList = sqlSession.selectList("com.llx.dao.UserMapper.getUserByRowBounds",null,rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
lombok
lombok是java的一個庫,它會自動插入編輯器和構建工具中。在實體類上加上註解後,我們可以不用編寫get和set方法,以及構造方法和toString方法等。
使用步驟:
-
在IDEA中安裝lombok插件
-
在項目中導入lombok的包
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency>
-
在實體類上加上註解即可
@Data @AllArgsConstructor @NoArgsConstructor
lombok中的註解:
@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:equals方法和hashCode方法
@ToString:toString方法
@Getter:get方法
@Setter:set方法
緩存
查詢數據庫是比較消耗資源的。我們可以將查詢的結果放在內存(緩存)中,當再次查詢相同的數據時,直接走緩存,不用走數據庫。
緩存:存在內存中的臨時數據。
將用戶經常查詢的數據放在緩存(內存)中,用戶查詢數據不用從磁盤上查詢,從緩存中查詢。從而提高查詢的效率,解決了高併發系統的性能問題。
使用緩存可以減少和數據庫的交互次數,減少系統開銷,提高系統的效率。
經常查詢且不經常改變的數據可以使用緩存。
MyBatis緩存
MyBatis包含一個非常強大的查詢緩存特性,它可以非常方便地定製和配置緩存。使用緩存可以極大的提升查詢效率。
MyBatis系統中默認定義了兩級緩存:一級緩存和二級緩存。
- 默認情況下,只有一級緩存開啓。(SqlSession級別的緩存,也稱爲本地緩存)
- 二級緩存需要手動開啓和配置,他是基於namespace級別的緩存。
- 爲了提高擴展性,MyBatis定義了緩存接口Cache。我們可以通過實現Cache接口來自定義二級緩存。
一級緩存
一級緩存也叫本地緩存: SqlSession。
- 與數據庫同一次會話期間查詢到的數據會放在本地緩存中。
- 以後如果需要獲取相同的數據,直接從緩存中拿,沒必須再去查詢數據庫。
測試在一個Sesion中查詢兩次相同記錄:
緩存失效的情況:
-
查詢不同的東西
-
增刪改操作,可能會改變原來的數據,所以必定會刷新緩存!
-
查詢不同的Mapper.xml
-
手動清理緩存!
一級緩存默認是開啓的,只在一次SqlSession中有效,也就是拿到連接到關閉連接這個區間段!
一級緩存就是一個Map。
二級緩存
二級緩存也叫全局緩存,一級緩存作用域太低了,所以誕生了二級緩存。
基於namespace級別的緩存,一個名稱空間,對應一個二級緩存。
工作機制:
- 一個會話查詢一條數據,這個數據就會被放在當前會話的一級緩存中
- 如果當前會話關閉了,這個會話對應的一級緩存就沒了;但是我們想要的是,會話關閉了,一級緩存中的數據被保存到二級緩存中
- 新的會話查詢信息,就可以從二級緩存中獲取內容
- 不同的mapper查出的數據會放在自己對應的緩存(map)中
步驟:
-
開啓全局緩存
<!--顯示地開啓全局緩存--> <setting name="cacheEnabled" value="true"/>
-
在要使用二級緩存的Mapper中開啓
<!--在當前Mapper.xml中使用二級緩存--> <cache/>
也可以自定義參數
<!--在當前Mapper.xml中使用二級緩存--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
-
測試
我們需要將實體類序列化,否則就會報錯:
Caused by: java.io.NotSerializableException: com.kuang.pojo.User
總結:
- 只要開啓了二級緩存,在同一個Mapper下就有效
- 所有的數據都會先放在一級緩存中;
- 只有當會話提交,或者關閉的時候,纔會提交到二級緩衝中!
緩存原理
當用戶查詢數據的時候,程序會現在二級緩存中查找,若有則返回,若沒有則在一級緩存中找;一級緩存中若有則返回,若沒有則在數據庫中找。
自定義緩存-ehcache
Ehcache是一種廣泛使用的開源Java分佈式緩存,主要面向通用緩存。
要在程序中使用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 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"/>
</ehcache>
Redis數據庫來做緩存! K-V