來源於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(); } }
- 如圖所示,在session1中查詢兩次id=1的Category對象。
-
在不同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>
- 序列化Category
public class Category implements Serializable{
- 測試:
- 再次運行TestMybatis,如圖所示,在同一個SessionFactory下查詢id=1的數據,只有第一次需要執行sql語句,以後都是從緩存中取出