JavaWeb框架梳理(五)——Mybatis進階


來源於how2j
github項目入口

Mybatis添加日誌

有時候需要打印日誌,知道mybatis執行了什麼樣的SQL語句,以便進行調試。這時,就需要開啓日誌,而mybatis自身是沒有帶日誌的,使用的都是第三方日誌,這裏講解如何開啓log4j日誌功能。
在這裏插入圖片描述

  • 添加log4j.jar在這裏插入圖片描述

  • 配置文件log4j.properties

    • 在src目錄下,新建文件log4j.properties,其作用是輸出com.how2java包下參與Mybatis的類的SQL語句輸出
    • 代碼:
    # Global logging configuration
    log4j.rootLogger=ERROR, stdout
    # MyBatis logging configuration...
    log4j.logger.com.how2java=TRACE
    # Console output...
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    
  • 效果如上

事務管理

  • 配置:
<transactionManager type="JDBC"/>

另一個值是MANAGED,是交由容器管理,如weblogic等,不在本知識點討論。

  • 測試:
package com.how2java;
   
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
 
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
   
public class TestMybatis {
   
    public static void main(String[] args) throws IOException, SQLException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
 
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
  
        Category c1 = new Category();
        c1.setName("長度夠短的名稱");
        mapper.add(c1);
         
        Category c2 = new Category();
        c2.setName("超過最大長度30的名稱超過最大長度30的名稱超過最大長度30的名稱超過最大長度30的名稱超過最大長度30的名稱超過最大長度30的名稱");
        mapper.add(c2);       
 
        listAll(mapper);
        session.commit();
        session.close();
   
    }
  
    private static void listAll(CategoryMapper mapper) {
        List<Category> cs = mapper.list();
        for (Category c : cs) {
            System.out.println(c.getName());
        }
    }
}
  • 效果在這裏插入圖片描述
    插入第二個數據會因爲長度超過32,而導致無法插入到數據庫。
    因爲在同一個事務裏,所以第一個數據,也無法插入成功。
  • 只有當表的類型是INNODB的時候,才支持事務,所以需要把表category_的類型設置爲INNODB,否則無法觀察到事務.
  • 修改表的類型爲INNODB的SQL:alter table category_ ENGINE = innodb;
  • 查看錶的類型的SQL:show table status from how2java;

分頁

傳統方式

  • 先準備數據
package com.how2java;
    
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
import com.how2java.pojo.Category;
    
public class TestMybatis {
    
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
        List<Category> cs = session.selectList("listCategory");
        for (Category c : cs) {
            session.delete("deleteCategory", c);
        }
        for (int i = 0; i < 100; i++) {
            Category c = new Category();
            c.setName("category name " + i);
            session.insert("addCategory", c);
        }
        List<Category> cs2 = session.selectList("listCategory");
        for (Category c : cs2) {
            System.out.println(c.getName());
        }
 
        session.commit();
        session.close();
 
    }
}
  • Category.xml

    • 新增limit:
    <?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">
     
        <mapper namespace="com.how2java.pojo">
            <insert id="addCategory" parameterType="Category" >
                insert into category_ ( name ) values (#{name})   
            </insert>
             
            <delete id="deleteCategory" parameterType="Category" >
                delete from category_ where id= #{id}  
            </delete>
             
            <select id="getCategory" parameterType="_int" resultType="Category">
                select * from   category_  where id= #{id}   
            </select>
     
            <update id="updateCategory" parameterType="Category" >
                update category_ set name=#{name} where id=#{id}   
            </update>
            <select id="listCategory" resultType="Category">
                select * from   category_
                    <if test="start!=null and count!=null">
                        limit #{start},#{count}
                    </if>
            </select>    
        </mapper>
    
  • CategoryMapper.java

package com.how2java.mapper;
  
import java.util.List;
 
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
 
import com.how2java.pojo.Category;
  
public interface CategoryMapper {
    @Select(" select * from category_ ")
    @Results({@Result(property = "products", javaType = List.class, column = "id", 
          many = @Many(select = "com.how2java.mapper.ProductMapper.listByCategory"))})      
    public List<Category> list();
     
    @Select(" select * from category_ limit #{start},#{count}")
    public List<Category> listByPage(@Param("start") int start, @Param("count")int count);
}

  • Test:
package com.how2java;
   
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
 
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 
import com.how2java.mapper.CategoryMapper;
import com.how2java.pojo.Category;
   
public class TestMybatis {
   
    public static void main(String[] args) throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession();
 
        CategoryMapper mapper = session.getMapper(CategoryMapper.class);
         
        List<Category>  cs =mapper.listByPage(0, 5);
        for (Category c : cs) {
            System.out.println(c);
        }
        session.commit();
        session.close();
    }
}
  • res:在這裏插入圖片描述

分頁插件

  • mybatis-config.xml:開啓插件:
<?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>
    <settings> 
            <!-- 打開延遲加載的開關 --> 
            <setting name="lazyLoadingEnabled" value="true" /> 
            <!-- 將積極加載改爲消息加載即按需加載 --> 
            <setting name="aggressiveLazyLoading" value="false"/> 
        </settings>   
    <typeAliases>
      <package name="com.how2java.pojo"/>
    </typeAliases>
    //開啓插件
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
             
        </plugin>
    </plugins>     
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="admin"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/how2java/pojo/Category.xml"/>
        <mapper class="com.how2java.mapper.CategoryMapper"/> 
        <mapper class="com.how2java.mapper.ProductMapper"/> 
    </mappers>
   
</configuration>
  • Category.xml

    • limit註釋掉,因爲分頁相關工作,會由PageHelper去做掉,不需要自己去寫了
    • 代碼:
    <?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">
     
        <mapper namespace="com.how2java.pojo">
            <insert id="addCategory" parameterType="Category" >
                insert into category_ ( name ) values (#{name})   
            </insert>
             
            <delete id="deleteCategory" parameterType="Category" >
                delete from category_ where id= #{id}  
            </delete>
             
            <select id="getCategory" parameterType="_int" resultType="Category">
                select * from   category_  where id= #{id}   
            </select>
     
            <update id="updateCategory" parameterType="Category" >
                update category_ set name=#{name} where id=#{id}   
            </update>
            <select id="listCategory" resultType="Category">
                select * from   category_
    <!--                 <if test="start!=null and count!=null"> -->
    <!--                     limit #{start},#{count} -->
    <!--                 </if> -->
            </select>    
        </mapper>
    
  • 分頁查詢:

    • 查詢很有意思,只需要在執行查詢所有的調用之前,執行一條語句即可:PageHelper.offsetPage(0, 5);
    • 獲取總數:PageInfo page= new PageInfo<>(cs);
    • 代碼:
    package com.how2java;
       
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
     
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     
    import com.github.pagehelper.PageHelper;
    import com.github.pagehelper.PageInfo;
    import com.how2java.pojo.Category;
       
    public class TestMybatis {
        public static void main(String[] args) throws IOException, InterruptedException {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession session = sqlSessionFactory.openSession();
          
            PageHelper.offsetPage(0, 5);
     
            List<Category> cs = session.selectList("listCategory");
            for (Category c : cs) {
                System.out.println(c.getName());
            }
            PageInfo pageInfo = new PageInfo<>(cs);
            System.out.println("總數:"+pageInfo.getTotal());
            System.out.println(pageInfo);
            session.commit();
            session.close();
        }
    }
    
    
  • res:在這裏插入圖片描述

緩存

一級緩存

  • 再一個session中查詢相同數據

    • 如圖所示,在session1中查詢兩次id=1的Category對象。
      第一次會去數據庫中取數據,但是第二次就不會訪問數據庫了,而是直接從session中取出來。
      在這裏插入圖片描述
    • 代碼:
    package com.how2java;
     
    import java.io.IOException;
    import java.io.InputStream;
     
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
     
    import com.how2java.pojo.Category;
     
    public class TestMybatis {
     
        public static void main(String[] args) throws IOException {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession session1 = sqlSessionFactory.openSession();
     
            Category c1 = session1.selectOne("getCategory", 1);
            System.out.println(c1);
            Category c2 = session1.selectOne("getCategory", 1);
            System.out.println(c2);
     
            session1.commit();
            session1.close();
             
        }
     
    }
    
  • 在不同Session裏查相同id的數據:

    • 另外打開一個session,取同樣id的數據,就會發現需要執行sql語句,證實了一級緩存是在session裏的。
    • 在這裏插入圖片描述
    • 代碼:
    public static void main(String[] args) throws IOException {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            SqlSession session1 = sqlSessionFactory.openSession();
     
            Category c1 = session1.selectOne("getCategory", 1);
            System.out.println(c1);
            Category c2 = session1.selectOne("getCategory", 1);
            System.out.println(c2);
     
            session1.commit();
            session1.close();
             
            SqlSession session2 = sqlSessionFactory.openSession();
            Category c3 = session2.selectOne("getCategory", 1);
            System.out.println(c3);    
            session2.commit();
            session2.close();
             
        }
    

二級緩存

  • 啓動二級緩存<setting name="cacheEnabled" value="true"/>
  • 代碼:
<?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>
    <settings> 
            <!-- 打開延遲加載的開關 --> 
            <setting name="lazyLoadingEnabled" value="true" /> 
            <!-- 將積極加載改爲消息加載即按需加載 --> 
            <setting name="aggressiveLazyLoading" value="false"/>
            <setting name="cacheEnabled" value="true"/>
        </settings>   
    <typeAliases>
      <package name="com.how2java.pojo"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
            <property name="driver" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="admin"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/how2java/pojo/Category.xml"/>
        <mapper class="com.how2java.mapper.CategoryMapper"/> 
        <mapper class="com.how2java.mapper.ProductMapper"/> 
    </mappers>
</configuration>
  • 在Category.xml中增加,以啓動對Category對象的二級緩存
<?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">
 
    <mapper namespace="com.how2java.pojo">
        <cache/>
        <insert id="addCategory" parameterType="Category" >
            insert into category_ ( name ) values (#{name})   
        </insert>
         
        <delete id="deleteCategory" parameterType="Category" >
            delete from category_ where id= #{id}  
        </delete>
         
        <select id="getCategory" parameterType="_int" resultType="Category">
            select * from   category_  where id= #{id}   
        </select>
 
        <update id="updateCategory" parameterType="Category" >
            update category_ set name=#{name} where id=#{id}   
        </update>
        <select id="listCategory" resultType="Category">
            select * from   category_
                <if test="start!=null and count!=null">
                    limit #{start},#{count}
                </if>
        </select>    
    </mapper>
  • 序列化Categorypublic class Category implements Serializable{
  • 測試:
  • 在這裏插入圖片描述
  • 再次運行TestMybatis,如圖所示,在同一個SessionFactory下查詢id=1的數據,只有第一次需要執行sql語句,以後都是從緩存中取出
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章