Mybatis初級講解

1. 總結jdbc開發的問題
1.      頻繁創建數據庫連接對象、釋放,容易造成系統資源浪費,影響系統性能。企業項目中可以使用連接池解決這個問題,但是使用Jdbc需要自己實現連接池。mybatis已經提供了連接池。
2.      sql語句定義、參數設置、結果集處理存在硬編碼。企業項目中,sql語句變化的可能性較大,一旦發生變化,需要修改Java代碼,系統需要重新編譯,重新發布。不好維護。
3.      結果集處理存在重複代碼,處理麻煩。如果可以映射爲java對象會比較方便。
 
2.   mybatis介紹
mybatisApache軟件基金會下的一個開源項目,前身是Ibatis框架。2010年這個項目由apache 軟件基金會遷移到google code下,改名爲mybatis201311月又遷移到了githubhttps://github.com/mybatis/mybatis-3/releases)。
mybatis是一個持久層的框架,是對JDBC操作數據庫的封裝,使開發者只需要關注業務本身,不需要花費精力去處理加載驅動、創建數據庫連接對象、創建statement語句對象、參數設置、結果集處理等一系列繁雜的過程代碼。
mybatis通過xml或註解進行配置,將java對象與sql語句中的參數自動映射生成最終執行的sql語句,並將sql語句執行結果自動映射java對象,返回給業務層(service)應用。
 
3.   mybatis入門程序
3.1. 需求
實現用戶表(user)增、刪、改、查操作。
1.      根據用戶Id查詢用戶
2.      根據用戶名稱模糊查詢用戶
3.      新增用戶
4.      根據用戶Id修改用戶
5.      根據用戶Id刪除用戶
 
3.2. 需求實現
3.2.1. 配置pom.xml文件,加入mybatis依賴
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
 
<groupId>cn.itheima</groupId>
<artifactId>mybatis-first</artifactId>
<version>0.0.1-SNAPSHOT</version>
 
<packaging>jar</packaging>
 
<name>mybatis-first</name>
<url>http://maven.apache.org</url>
 
<properties>
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <!-- mysql版本 -->
     <mysql.version>5.1.30</mysql.version>
     <!-- junit版本 -->
     <junit.version>4.12</junit.version>
     <!-- mybatis版本號 -->
     <mybatis.version>3.4.5</mybatis.version>
     <!-- log4j日誌包版本 -->
     <slf4j.version>1.7.7</slf4j.version>
     <log4j.version>1.2.17</log4j.version>
</properties>
 
<dependencies>
     <!-- mysql數據庫依賴 -->
     <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>${mysql.version}</version>
     </dependency>
     <!-- mybatis核心包 -->
     <dependency>
         <groupId>org.mybatis</groupId>
         <artifactId>mybatis</artifactId>
         <version>${mybatis.version}</version>
     </dependency>
     <!-- log4j日誌包 -->
     <dependency>
         <groupId>log4j</groupId>
         <artifactId>log4j</artifactId>
         <version>${log4j.version}</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-api</artifactId>
         <version>${slf4j.version}</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
         <artifactId>slf4j-log4j12</artifactId>
         <version>${slf4j.version}</version>
     </dependency>
     <!-- junit依賴 -->
     <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>${junit.version}</version>
         <scope>test</scope>
     </dependency>
</dependencies>
</project>
 
3.2.2. 準備配置文件
3.2.2.1. sqlMapConfig.xml
說明:mybatis框架核心配置文件。
<?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>
 
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments default="development">
     <!-- id屬性:唯一標識一個運行環境 -->
     <environment id="development">
         <!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務 -->
        <transactionManager type="JDBC" />
        
         <!-- 數據源配置,POOLED:mybatis提供的連接池 -->
         <dataSource type="POOLED">
             <property name="driver" value="com.mysql.jdbc.Driver" />
             <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
             <property name="username" value="root" />
             <property name="password" value="admin" />
         </dataSource>
     </environment>
</environments>
</configuration>
 
3.2.2.2. log4j.properties
# Global logging configuration
log4j.rootLogger=DEBUG, stdout
 
# 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
 
3.2.3. 準備用戶pojo
public class User {
  private Integer id; // int(11) NOT NULL AUTO_INCREMENT,
  private String username; // varchar(32) NOT NULL COMMENT '用戶名稱',
  private Date birthday; // date DEFAULT NULL COMMENT '生日',
  private String sex; // char(1) DEFAULT NULL COMMENT '性別',
  private String address; // varchar(256) DEFAULT NULL COMMENT '地址',
/**
 * @return the id
 */
public Integer getId() {
     return id;
}
/**
 * @param id the id to set
 */
public void setId(Integer id) {
     this.id = id;
}
/**
 * @return the username
 */
public String getUsername() {
     return username;
}
/**
 * @param username the username to set
 */
public void setUsername(String username) {
     this.username = username;
}
/**
 * @return the birthday
 */
public Date getBirthday() {
     return birthday;
}
/**
 * @param birthday the birthday to set
 */
public void setBirthday(Date birthday) {
     this.birthday = birthday;
}
/**
 * @return the sex
 */
public String getSex() {
     return sex;
}
/**
 * @param sex the sex to set
 */
public void setSex(String sex) {
    this.sex = sex;
}
/**
 * @return the address
 */
public String getAddress() {
     return address;
}
/**
 * @param address the address to set
 */
public void setAddress(String address) {
     this.address = address;
}
/* (non-Javadoc)
 * @see java.lang.Object#toString()
 */
@Override
public String toString() {
     return "User [id=" + id + ", username=" + username + ", birthday="
             + birthday + ", sex=" + sex + ", address=" + address + "]";
}
 
 
 
}
 
3.2.4. 準備sql語句
select * from `user` where id=24
 
3.2.5. 準備mapper映射文件
說明:用於配置java對象,與sql語句的對應關係。
<?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">
<!-- namespace屬性:名稱空間,相當於java中的package,用於放置sql語句衝突 -->
<mapper namespace="test">
<!--說明:mybatis框架針對每一種sql語句:新增/修改/刪除/查詢,提供了對應的標籤:
insert/update/delete/select來放置  -->
 
<!-- 根據用戶Id查詢用戶,說明:
 select標籤:用於放置查詢sql語句
 id屬性:唯一標識一條sql語句
 parameterType屬性:輸入參數類型
 resultType屬性:返回值類型
 #{id}:佔位符,相當於jdbc中的問號:?-->
<select id="queryUserById" parameterType="int" resultType="cn.itheima.mybatis.po.User">
     select * from `user` where id=#{id}
</select>
 
</mapper>
 
 
3.2.6. sqlMapcConfig.xml文件中,加載User.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>
 
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments default="development">
     <!-- id屬性:唯一標識一個運行環境 -->
     <environment id="development">
         <!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務 -->
         <transactionManager type="JDBC" />
        
         <!-- 數據源配置,POOLED:mybatis提供的連接池 -->
         <dataSource type="POOLED">
             <property name="driver" value="com.mysql.jdbc.Driver" />
             <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
             <property name="username" value="root" />
             <property name="password" value="admin" />
         </dataSource>
     </environment>
</environments>
<!-- 加載mapper映射文件 -->
<mappers>
     <!--加載User.xml文件,說明:
       resource屬性:指定配置文件的位置-->
     <mapper resource="sqlmap/User.xml"/>
</mappers>
</configuration>
 
3.2.7. 編寫測試代碼
public class MybatisTest {
// 1.測試根據用戶Id查詢用戶
@Test
public void queryUserByIdTest() throws IOException{
    
     // 1.加載核心配置文件:sqlMapConfig.xml
     // resource屬性:指定核心配置文件位置
     InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    
     // 2.讀取配置文件內容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
     SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
    
     // 3.使用SqlSessionFactory對象,創建sqlSession對象
     // sqlSession對象:
     // 3.1相當於jdbc中的connection對象
     // 3.2 sqlSession對象是線程不安全,每一個執行操作的方法,都需要創建一個sqlSession對象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 4.使用sqlSession對象,調用方法執行
     // selectOne方法:查詢單條記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     Object user = sqlSession.selectOne("test.queryUserById", 24);
     System.out.println(user);
    
     // 5.釋放資源
     sqlSession.close();
    
}
 
}
 
 
3.3. 其他需求實現
3.3.1. 根據用戶名稱模糊查詢用戶
3.3.1.1. 準備sql語句
select * from `user` where username like '%小明%'
 
 
3.3.1.2. 配置映射文件
<!-- 根據用戶名稱模糊查詢用戶,說明 -->
<select id="queryUserByName" parameterType="string" resultType="cn.itheima.mybatis.po.User">
     select * from `user` where username like #{username}
</select>
 
3.3.1.3. 編寫測試代碼
// 2.測試根據用戶名稱模糊查詢用戶
@Test
public void queryUserByNameTest() throws IOException{
     // 1.加載核心配置文件
     InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    
     // 2.讀取配置文件內容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
    
     // 3.使用sqlSessionFactory對象,創建sqlSession對象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 4.使用sqlSession對象,調用方法執行
     // selectList方法:查詢多條記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     List<Object> list = sqlSession.selectList("test.queryUserByName", "%小明%");
     for(Object o :list){
         System.out.println(o);
     }
    
    // 5.釋放資源
     sqlSession.close();
}
 

 
3.3.1.4. 使用字符串拼接符${},拼接參數
<!-- 根據用戶名稱模糊查詢用戶,說明 -->
<select id="queryUserByName" parameterType="string" resultType="cn.itheima.mybatis.po.User">
     <!-- select * from `user` where username like #{username} -->
    
     <!--  where username like '%小明%',說明:
     使用字符串拼接符${},拼接參數 -->
     select * from `user` where username like '%${value}%'
</select>
 

 
3.3.1.5. 佔位符#{}與字符串拼接符${}區別
1.            佔位符#{},相當於jdbc中的問號?,當參數傳遞的是java簡單類型的時候,花括號中的內容可以是任意字符串。
2.            字符串拼接符 ${},當參數傳遞的是java簡單類型的時候,花括號中的內容只能是:value
3.            sql語句中使用字符串拼接符${},可能引起sql注入的問題。但是mybatis中字符串拼接符可以使用,原因是是後端dao層的開發,項目中參數傳遞經過表現層(action),業務層(service)已經處理好。
 
3.3.2. 新增用戶
3.3.2.1. 準備sql語句
insert into `user`(id,username,birthday,sex,address) values(2,'小李飛刀','2017-11-06','1','來自明朝')
 
3.3.2.2. 配置映射文件
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
 <insert id="insertUser" parameterType="cn.itheima.mybatis.po.User">
    insert into `user`(id,username,birthday,sex,address)
    values(#{id},#{username},#{birthday},#{sex},#{address})
 </insert>
 
3.3.2.3. 編寫測試代碼
// 3.測試新增用戶
@Test
public void insertUserTest(){
     // 1.創建sqlSession對象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,調用方法執行
     // insert方法:新增記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     // 創建用戶對象
     User user  = new User();
     user.setId(3);
     user.setUsername("林詩音");
     user.setBirthday(new Date());
     user.setSex("2");
     user.setAddress("來自大明朝");
    
     sqlSession.insert("test.insertUser", user);
    
     // 3.釋放資源
     sqlSession.close();
    
}
 

 
問題:java程序執行成功,但是數據庫中並沒有林詩音的數據,原因是沒有提交事務。
 
 
3.3.2.4. 提交事務
3.3.2.4.1. 方式一
// 3.測試新增用戶
@Test
public void insertUserTest(){
     // 1.創建sqlSession對象
     SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,調用方法執行
     // insert方法:新增記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     // 創建用戶對象
     User user  = new User();
     user.setId(3);
     user.setUsername("林詩音");
     user.setBirthday(new Date());
     user.setSex("2");
     user.setAddress("來自大明朝");
    
     sqlSession.insert("test.insertUser", user);
    
     // 數據庫提交事務:commit
     sqlSession.commit();
    
     // 3.釋放資源
     sqlSession.close();
    
}
 
3.3.2.4.2. 方式二
// 3.測試新增用戶
@Test
public void insertUserTest(){
     // 1.創建sqlSession對象
     //SqlSession sqlSession = sqlSessionFactory.openSession();
    
     // 創建sqlSession對象,指定自動提交事務。true:表示提交;false:表示不提交。默認是false
     SqlSession sqlSession =  this.sqlSessionFactory.openSession(true);
    
     // 2.使用sqlSession對象,調用方法執行
     // insert方法:新增記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     // 創建用戶對象
     User user  = new User();
     user.setId(4);
     user.setUsername("林詩音");
     user.setBirthday(new Date());
     user.setSex("2");
     user.setAddress("來自大明朝");
    
     sqlSession.insert("test.insertUser", user);
    
     // 數據庫提交事務:commit
     //sqlSession.commit();
    
     // 3.釋放資源
     sqlSession.close();
    
}
 
 
問題:用戶表中id是自增長,不需要傳遞,但是mybatis中如何獲取到新增以後的用戶Id???
 
mysql數據庫查詢新增Id
select LAST_INSERT_ID()
 
3.3.2.5. 獲取新增的用戶Id
3.3.2.5.1. 方式一
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
 <insert id="insertUser" parameterType="cn.itheima.mybatis.po.User">
    <!-- insert into `user`(id,username,birthday,sex,address)
    values(#{id},#{username},#{birthday},#{sex},#{address}) -->
   
    <!-- selectKey標籤:查詢主鍵id,說明
     keyColumn屬性:主鍵字段(表)
     keyProperty屬性:主鍵屬性(pojo
     resultType屬性:指定主鍵字段類型
     order屬性:指定在insert語句之前,還是之後獲取主鍵值.
     BEFORE:在insert語句前;AFTER:在insert語句之後-->
    <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
        select LAST_INSERT_ID()
    </selectKey>
    insert into `user`(username,birthday,sex,address)
    values(#{username},#{birthday},#{sex},#{address})
 </insert>
 

 
3.3.2.5.2. 方式二
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
 <insert id="insertUser" parameterType="cn.itheima.mybatis.po.User"
 useGeneratedKeys="true" keyColumn="id" keyProperty="id">
    <!-- insert into `user`(id,username,birthday,sex,address)
    values(#{id},#{username},#{birthday},#{sex},#{address}) -->
   
    <!-- selectKey標籤:查詢主鍵id,說明
     keyColumn屬性:主鍵字段(表)
     keyProperty屬性:主鍵屬性(pojo
     resultType屬性:指定主鍵字段類型
     order屬性:指定在insert語句之前,還是之後獲取主鍵值.
     BEFORE:在insert語句前;AFTER:在insert語句之後-->
    <!-- <selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
        select LAST_INSERT_ID()
    </selectKey> -->
    insert into `user`(username,birthday,sex,address)
    values(#{username},#{birthday},#{sex},#{address})
 </insert>
 

 
3.3.3. 根據用戶Id修改用戶
3.3.3.1. 準備sql語句
update `user` set username='小李飛刀和林詩音',sex='2' where id=2
 
 
3.3.3.2. 配置映射文件
<!-- 根據用戶id修改用戶,說明:
  update標籤:用於放置修改sql語句-->
  <update id="updateUserById" parameterType="cn.itheima.mybatis.po.User">
    update `user`
    set username=#{username},sex=#{sex} where id=#{id}
  </update>
 
 
3.3.3.3. 編寫測試代碼
// 4.測試根據用戶Id修改用戶
@Test
public void updateUserByIdTest(){
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession(true);
    
     // 2.使用sqlSession對象,調用方法執行
     // update方法:修改記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     // 創建用戶對象
     User user = new User();
     user.setId(3);
     user.setUsername("林詩音和小李飛刀");
     user.setSex("1");
    
     sqlSession.update("test.updateUserById", user);
    
     // 3.釋放資源
     sqlSession.close();
}
 

 
3.3.4. 根據用戶Id刪除用戶
3.3.4.1. 準備sql語句
delete from `user` where id=4
 
 
3.3.4.2. 配置映射文件
 <!-- 根據用戶id刪除用戶,說明:
   delete標籤:用於放置刪除的sql語句-->
   <delete id="deleteUserById" parameterType="int">
        delete from `user` where id=#{id}
   </delete>
 
 
3.3.4.3. 編寫測試代碼
// 5.測試根據用戶Id刪除用戶
@Test
public void deleteUserByIdTest(){
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession(true);
    
     // 2.使用sqlSession對象,調用方法執行
     // delete方法:刪除記錄
     // statement參數:執行的sql語句(名稱空間+sql語句Id)
     // parameter參數:傳入的參數值
     sqlSession.delete("test.deleteUserById", 35);
    
     // 3.釋放資源
     sqlSession.close();
}
 

 
4.   mybatis框架原理

1.      Configuration配置對象:sqlMapConfig.xlUser.xml......
2.      MappedStatement對象:負責輸入輸出映射,ParameterType參數輸入,ResultType返回值輸出
3.      Executor執行器對象:負責執行數據庫的CRUD操作
 
5.   mybatis兩種開發方法
1.      原始的dao開發方法
2.      mapper代理開發方法
 
 
5.1. 原始的dao開發方法
5.1.1. 需求
1.      根據用戶Id查詢用戶
2.      新增用戶
 
5.1.2. 需求實現
5.1.2.1. 準備用戶dao接口
public interface UserDao {
//   1.根據用戶Id查詢用戶
User queryUserById(Integer id);
//   2.新增用戶
void insertUser(User user);
 
}
 
 
5.1.2.2. 實現用戶dao接口
public class UserDaoImpl implements UserDao {
// 定義sqlSessionFactory對象
private SqlSessionFactory sqlSessionFactory;
 
/**
 *
 */
public UserDaoImpl() {
     super();
}
 
/**
 * @param sqlSessionFactory
 */
public UserDaoImpl(SqlSessionFactory sqlSessionFactory) {
     super();
     this.sqlSessionFactory = sqlSessionFactory;
}
 
/* (non-Javadoc)
 * @see cn.itheima.mybatis.dao.UserDao#queryUserById(java.lang.Integer)
 */
public User queryUserById(Integer id) {
     // TODO Auto-generated method stub
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,調用方法執行
     Object user = sqlSession.selectOne("test.queryUserById", id);
    
     // 3.釋放資源
     sqlSession.close();
    
     return (User) user;
}
 
/* (non-Javadoc)
 * @see cn.itheima.mybatis.dao.UserDao#insertUser(cn.itheima.mybatis.po.User)
 */
public void insertUser(User user) {
     // TODO Auto-generated method stub
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession(true);
    
     // 2.使用sqlSession對象,調用方法執行
     sqlSession.insert("test.insertUser", user);
    
     // 3.釋放資源
     sqlSession.close();
 
}
 
}
 
5.1.2.3. 編寫測試代碼
public class UserDaoTest {
private SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException{
    // 1.加載核心配置文件:sqlMapConfig.xml
     // resource屬性:指定核心配置文件位置
     InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    
     // 2.讀取配置文件內容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
     sqlSessionFactory = builder.build(inputStream);
}
// 測試根據用戶Id查詢用戶
@Test
public void queryUserByIdTest(){
    
     // 1.創建用戶dao對象
     UserDao userDao = new UserDaoImpl(sqlSessionFactory);
    
     // 2.使用userDao對象,調用方法執行
     User user = userDao.queryUserById(2);
     System.out.println(user);
    
}
 
}
 

 
測試新增用戶:
// 測試新增用戶
@Test
public void insertUserTest(){
     // 1.創建用戶dao對象
     UserDao userDao = new UserDaoImpl(sqlSessionFactory);
    
     // 2.使用userDao對象,調用方法執行
     // 創建用戶對象
     User user = new User();
     user.setUsername("阿飛");
     user.setSex("1");
     user.setBirthday(new Date());
     user.setAddress("來自大明朝");
    
     System.out.println("執行前:"+user);
     userDao.insertUser(user);
     System.out.println("執行後:"+user);
}
 

 
5.2. mapper代理開發方法
 
5.2.1. 注意事項
1.      要求mapper映射文件中namespace屬性值,必須是mapper接口的全路徑(包名稱+接口名稱)
2.      要求mapper映射文件中sql語句的聲明,與mapper接口方法的聲明一致
2.1.mapper接口返回值類型,與sql語句標籤的resultType屬性指定的類型一致
2.2.mapper接口的方法名稱,與sql語句id屬性值一致
2.3.mapper接口的方法的形參,與sql語句的parameterType屬性指定的類型一致
 
5.2.2. 需求
1.      根據用戶Id查詢用戶
2.      新增用戶
 
5.2.3. 需求實現
5.2.3.1. 準備用戶mapper接口
public interface UserMapper {
//   1.根據用戶Id查詢用戶
User queryUserById(Integer id);
//   2.新增用戶
void insertUser(User user);
 
}
 
5.2.3.2. 準備用戶mapper映射文件
<?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">
<!-- namespace屬性:名稱空間,相當於java中的package,用於放置sql語句衝突 -->
<!--mapper代理開發方法中,namespace屬性值,必須是mapper接口的全路徑  -->
<mapper namespace="cn.itheima.mybatis.mapper.UserMapper">
 
<!-- 根據用戶Id查詢用戶,說明:
 select標籤:用於放置查詢sql語句
 id屬性:唯一標識一條sql語句
 parameterType屬性:輸入參數類型
 resultType屬性:返回值類型
 #{id}:佔位符,相當於jdbc中的問號:?-->
<select id="queryUserById" parameterType="int" resultType="cn.itheima.mybatis.po.User">
     select * from `user` where id=#{id}
</select>
<!-- 新增用戶,說明
insert標籤:用於放置新增sql語句
#{id}:佔位符,當參數傳遞的是pojo的時候,換括號中的內容是pojo的屬性-->
 <insert id="insertUser" parameterType="cn.itheima.mybatis.po.User"
 useGeneratedKeys="true" keyColumn="id" keyProperty="id">
    insert into `user`(username,birthday,sex,address)
    values(#{username},#{birthday},#{sex},#{address})
 </insert>
 
</mapper>
 
 
5.2.3.3. sqlMapConfig.xml,加載UserMapper.xml文件
<!-- 加載mapper映射文件 -->
<mappers>
     <!--加載User.xml文件,說明:
       resource屬性:指定配置文件的位置-->
     <mapper resource="sqlmap/User.xml"/>
     <!-- 加載UserMapper.xml文件 -->
     <mapper resource="sqlmap/UserMapper.xml"/>
</mappers>
 
 
5.2.3.4. 編寫測試代碼
public class UserMapperTest {
private SqlSessionFactory sqlSessionFactory = null;
@Before
public void init() throws IOException{
     // 1.加載核心配置文件:sqlMapConfig.xml
     // resource屬性:指定核心配置文件位置
     InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    
     // 2.讀取配置文件內容
     SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
     // SqlSessionFactory對象:mybatis框架的核心對象,一個項目中只需要一個(單例設計模式)
     sqlSessionFactory = builder.build(inputStream);
}
// 測試根據用戶Id查詢用戶
@Test
public void queryUserByIdTest(){
    
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,獲取mapper代理對象
     // getMapper方法:獲取mapper代理對象
     // type參數:mapper接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
     // 3.使用mapper代理對象,調用方法執行
     User user = mapper.queryUserById(2);
     System.out.println(user);
    
     // 4.釋放資源
     sqlSession.close();
}
 
}
 

 
測試新增用戶:
// 測試新增用戶
@Test
public void insertUserTest(){
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession(true);
    
     // 2.使用sqlSession對象,獲取mapper代理對象
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
     // 3.使用mapper對象,調用方法執行
     // 創建用戶對象
     User user = new User();
     user.setUsername("天機老人");
     user.setSex("1");
     user.setBirthday(new Date());
     user.setAddress("來自大明朝");
    
     mapper.insertUser(user);
    
     // 4.釋放資源
     sqlSession.close();
}
 
5.3. 兩種開發方法總結
1.      原始的dao開發方法:需要開發接口和實現類
2.      mapper代理開發方法:只需要開發接口
3.      企業項目中,推薦使用mapper代理開發
 
6.   mybatis核心配置文件
sqlMapConfig.xml:配置運行環境(數據源),mapper映射文件。
順序
配置標籤名稱
說明
1
properties
屬性
2
settings
配置全局參數
3
typeAliases
類型別名
4
typeHandlers
類型處理器
5
objectFactory
對象工廠
6
plugins
插件
7
environments
環境集合屬性對象
8
databaseIdProvider
多數據庫支持
9
mappers
映射器
說明:
1.        紅色字體內容要求掌握
2.        sqlMapConfig.xml必須是從上往下的配置順序
 
6.1. properties(屬性)
作用:加載屬性文件(比如db.properties)和定義屬性
 
6.1.1. 準備db.properties文件

db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://127.0.0.1:3306/mybatis
db.username=root
db.password=admin
 
6.1.2. 加載db.properties屬性文件
<!--加載屬性文件,說明:
 1.resource屬性:指定本地配置文件的位置
 2.url屬性:指定網絡上的配置文件位置-->
<properties resource="db.properties" >
   </properties>
 
 
6.1.3. 使用db.propertis屬性文件中的屬性
<!-- 運行環境配置 -->
<!-- default屬性:指定使用哪一個運行環境 -->
<environments default="development">
     <!-- id屬性:唯一標識一個運行環境 -->
     <environment id="development">
         <!-- 事務管理器配置,JDBC:mybatis默認使用jdbc事務 -->
         <transactionManager type="JDBC" />
        
         <!-- 數據源配置,POOLED:mybatis提供的連接池 -->
         <dataSource type="POOLED">
             <!-- <property name="driver" value="com.mysql.jdbc.Driver" />
             <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis" />
             <property name="username" value="root" />
             <property name="password" value="admin" /> -->
            
             <!-- 使用db.properties屬性文件的屬性 -->
             <property name="driver" value="${db.driver}" />
             <property name="url" value="${db.url}" />
             <property name="username" value="${db.username}" />
             <property name="password" value="${db.password}" />
         </dataSource>
     </environment>
   </environments>
 
6.1.4. 使用內部property標籤定義屬性
<!--加載屬性文件,說明:
 1.resource屬性:指定本地配置文件的位置
 2.url屬性:指定網絡上的配置文件位置
 3.使用內部property標籤定義屬性
 4.加載順序:首先加載內部property標籤定義的屬性,再加載屬性文件中的屬性,
 如果有相同的屬性,屬性文件中的屬性,覆蓋內部property標籤的屬性-->
<properties resource="db.properties" >
     <property name="db.username" value="root123"/>
     <property name="db.password" value="admin"/>
   </properties>
 
6.2. typeAliases(類型別名)
作用:簡稱。比如中華人民共和國,簡稱中國。
6.2.1. 內置別名
別名
映射類型
_byte
byte
_long
long
_short
short
_int
int
_integer
int
_double
double
_float
float
_boolean
boolean
string
String
byte
Byte
long
Long
short
Short
int
Integer
integer
Integer
double
Double
float
Float
boolean
Boolean
date
Date
decimal
BigDecimal
bigdecimal
BigDecimal
object
Object
map
Map
hashmap
HashMap
list
List
arraylist
ArrayList
collection
Collection
iterator
Iterator
 
說明:
1.      內置別名可以直接使用
2.      別名不區分大小寫
 
6.2.2. 自定義別名
6.2.2.1. 自定義別名方式一
<!-- 自定義別名配置 -->
<typeAliases>
     <!-- 自定義用戶別名配置,說明:
     1.type屬性:別名的類型
     2.默認使用類名稱,作爲別名
     3.alias屬性:指定別名的名稱 -->
     <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/>
</typeAliases>
 
6.2.2.2. 自定義別名方式二
<!-- 自定義別名配置 -->
<typeAliases>
     <!-- 自定義用戶別名配置,說明:
     1.type屬性:別名的類型
     2.默認使用類名稱,作爲別名
     3.alias屬性:指定別名的名稱 -->
     <!-- <typeAlias type="cn.itheima.mybatis.po.User" alias="user"/> -->
    
     <!--包掃描方式配置別名,說明:
      1.name屬性:指定掃描的包
      2.默認使用類名稱,作爲別名
      3.如果有多個包,配置多個package
      4.企業項目中,推薦使用包掃描方式 -->
     <package name="cn.itheima.mybatis.po"/>
</typeAliases>
 
6.3. mappers(映射器)
作用:加載mapper映射文件。
 
6.3.1. 加載mapper映射文件方式一
<!-- 加載mapper映射文件 -->
<mappers>
     <!--加載User.xml文件,說明:
       resource屬性:指定配置文件的位置-->
     <mapper resource="sqlmap/User.xml"/>
     <!-- 加載UserMapper.xml文件 -->
     <mapper resource="sqlmap/UserMapper.xml"/>
   </mappers>
 
 
6.3.2. 加載mapper映射文件方式二
<!-- 加載mapper映射文件 -->
<mappers>
     <!--加載User.xml文件,說明:
       resource屬性:指定配置文件的位置-->
     <mapper resource="sqlmap/User.xml"/>
     <!-- 加載UserMapper.xml文件 -->
     <!-- <mapper resource="sqlmap/UserMapper.xml"/> -->
    
     <!-- 包掃描方式加載mapper映射文件,說明:
     1.前提必須是mapper代理開發方法
     2.要求mapper映射文件,與mapper接口在同一個目錄
     3.要求mapper映射文件的名稱,與mapper接口的名稱一致 -->
     <package name="cn.itheima.mybatis.mapper"/>
   </mappers>
 
 
7.   mybatishibernate比較
7.1. 相同點
都是對jdbc的封裝,都是持久層的框架,都用於dao層的開發。
 
7.2. 不同點
1.      hibernate是對sql語句做了封裝,提供HQL語言操作數據庫,數據庫無關性支持好,在項目需要支持多種數據庫的情況下,代碼開發量較少,sql語句優化困難;mybatis是直接使用sql語句操作數據庫,不支持數據庫無關性,在項目需要支持多種數據庫的情況下,代碼開發量較多,sql語句優化容易。
2.      hibernate是配置java對象與數據庫表的對應關係,多表關聯關係配置複雜。mybatis是配置java對象,與sql語句對應關係,多表關聯關係配置容易。
3.      hibernate是重量級的框架,學習使用門檻高,適合於需求相對穩定,中小型的項目,比如:辦公自動化系統(OA);mybatis是輕量級的框架,學習使用門檻低,適合於需求變化頻繁,大型的項目,比如:互聯網電子商務網站項目。目前在企業項目中,mybatis框架使用更多一些。
 
8.   擴展
8.1. 註解開發
//   3.根據用戶Id查詢用戶,使用註解開發實現
@Select("select * from `user` where id=#{id}")
User queryUserById_1(Integer id);
 
// 測試根據用戶Id查詢用戶,測試註解開發
@Test
public void queryUserById_1Test(){
    
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,獲取mapper代理對象
     // getMapper方法:獲取mapper代理對象
     // type參數:mapper接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
     // 3.使用mapper代理對象,調用方法執行
     User user = mapper.queryUserById_1(2);
     System.out.println(user);
    
     // 4.釋放資源
     sqlSession.close();
   }
 
說明:註解開發,只做瞭解,企業項目中不推薦使用。
 
8.2. 緩存
8.2.1. 一級緩存(sqlSession級別)
// 測試根據用戶Id查詢用戶,測試一級緩存
@Test
public void oneCacheTest(){
    
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,獲取mapper代理對象
     // getMapper方法:獲取mapper代理對象
     // type參數:mapper接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
     // 3.使用mapper代理對象,調用方法執行
     User user = mapper.queryUserById(2);
     System.out.println(user);
    
     System.out.println("-------------------------------------");
    
     User user1 = mapper.queryUserById(2);
     System.out.println(user1);
    
    
     // 4.釋放資源
     sqlSession.close();
   }
 

 
說明:一級緩存mybatis框架就已經默認使用,不需要關心。
 
8.2.2. 二級緩存(mapper級別緩存,在多個SqlSession之間共享)
8.2.2.1. sqlMapConfig.xml中,配置開啓二級緩存
<!-- 全局參數配置 -->
<settings>
     <!-- 配置開啓二級緩存 -->
     <setting name="cacheEnabled" value="true"/>
</settings>
 
 
8.2.2.2. 修改用戶pojo,實現序列化接口
public class User implements java.io.Serializable{
  private Integer id; // int(11) NOT NULL AUTO_INCREMENT,
  private String username; // varchar(32) NOT NULL COMMENT '用戶名稱',
  private Date birthday; // date DEFAULT NULL COMMENT '生日',
  private String sex; // char(1) DEFAULT NULL COMMENT '性別',
  private String address; // varchar(256) DEFAULT NULL COMMENT '地址',
 
8.2.2.3. UserMapper.xml中,開啓使用二級緩存

 
8.2.2.4. 測試二級緩存
// 測試根據用戶Id查詢用戶,測試二級緩存
@Test
public void twoCacheTest(){
    
     // 1.創建sqlSession對象
     SqlSession sqlSession = this.sqlSessionFactory.openSession();
    
     // 2.使用sqlSession對象,獲取mapper代理對象
     // getMapper方法:獲取mapper代理對象
     // type參數:mapper接口的class
     UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
     // 3.使用mapper代理對象,調用方法執行
     User user = mapper.queryUserById(2);
     System.out.println(user);
 
     // 4.釋放資源
     sqlSession.close();
    
     System.out.println("-----------------------------------------");
    
     //  5.創建sqlSession對象
     SqlSession sqlSession1 = this.sqlSessionFactory.openSession();
    
     // 6.使用sqlSession對象,獲取mapper代理對象
     // getMapper方法:獲取mapper代理對象
     // type參數:mapper接口的class
     UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
    
     // 7.使用mapper代理對象,調用方法執行
     User user1 = mapper1.queryUserById(2);
     System.out.println(user1);
 
     // 8.釋放資源
     sqlSession1.close();
}

說明:mybatis框架的二級緩存,只做瞭解,企業項目中不推薦使用。原因是mybatis框架的二級緩存不能實現細粒度的控制。
 
 







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