MyBatis-日誌、分頁、緩存

日誌

如果一個數據庫的操作出現了異常,這時候我們需要排錯,日誌就是最好的助手。

之前使用的是輸出語句或者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的使用:

  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");
    

分頁

使用分頁可以減少數據的處理量。

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方法等。

使用步驟:

  1. 在IDEA中安裝lombok插件

  2. 在項目中導入lombok的包

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

    @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)中

步驟:

  1. 開啓全局緩存

    <!--顯示地開啓全局緩存-->
    <setting name="cacheEnabled" value="true"/>
    
  2. 在要使用二級緩存的Mapper中開啓

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

    也可以自定義參數

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

    我們需要將實體類序列化,否則就會報錯:

    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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章