1. 程式人生 > >MyBatis學習(一)

MyBatis學習(一)

es2017 提交 clas char 接口類 數據庫 nbsp transacti 兩個

一、MyBatis簡介

MyBatis是一個對JDBC進行封裝的持久層框架,只需關註SQL本身,而不必去處理(註冊驅動、創建connection、創建statement、手動設置參數、結果集檢查)的代碼。

XML或註解將要執行的statement配置起來,通過Java對象和statement的sql進行映射,生成最終的sql語句,由MyBatis框架執行sql並將結果映射成Java對象返回。

MyBatis和Hibernate的區別:

1、不完全的ORM框架,需要sql語句

2、直接寫sql語句,靈活度高,性能好

3、與數據庫相關(MySQL、Oracle用不同映射文件)

JDBC存在的問題:

1、創建連接connection、釋放資源影響性能(數據庫連接池可解決)

2、(sql、參數、結果集)硬編碼,代碼不易維護

二、MyBatis架構

技術分享

1、SqlMapConfig.xml是核心配置文件,配置運行環境等信息;Mapper.xml是映射配置文件,配置了操作數據庫的sql語句,需要在SqlMapConfig.xml中配置。

2、通過MyBatis環境等配置信息構造會話工廠SqlSessionFactory。

3、由會話工廠SqlSessionFactory創建會話sqlSession,由sqlSession操作數據庫。

4、底層通過Executor執行器接口操作數據庫,接口有兩個實現:基本執行器、緩存執行器

5、Mapped Statement也是一個底層封裝對象,包裝了MyBatis配置信息和sql映射信息等。映射配置文件Mapper.xml中一個sql對應一個Mapped Statement對象,sql的id即是MappedStatement的id。

6、Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、POJO、Executor通過Mapped Statement在執行sql前將輸入的Java對象映射至sql中,輸入參數映射就是JDBC中對prepareStatement設置參數

7、Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、POJO、Executor通過Mapped Statement在執行sql後將輸出結果映射到Java對象中,輸出結果映射過程相當於JDBC中對結果的解析處理過程。

三、MyBatis入門

1、導包

核心包:MyBatis-3.2.7.jar

依賴包:lib下所有包

數據庫驅動包:mysql-connector-java-5.1.17-bin.jar

日誌配置文件:log4j.properties

2、在src下創建核心配置文件SqlMapConfig.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>
    <!-- 和spring整合後 environments配置將廢除-->
    <environments default="development">
        <environmentid="development">
        <!-- 使用jdbc事務管理-->
            <transactionManagertype="JDBC"/>
        <!-- 數據庫連接池-->
            <dataSourcetype="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password "value="root"/>
            </dataSource>
        </environment>
    </environments>
</configuration>

3、創建POJO(JavaBean) User,屬性表與表中字段對應

Public class User {
    privateintid;
    private String username;// 用戶姓名
    private String sex;// 性別
    private Date birthday;// 生日
    private String address;// 地址
        
    setter&getter
}

4、在src下創建映射配置文件User.xml

<?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="test">
</mapper>

namespace用於隔離sql語句

5、加載映射文件User.xml到SqlMapConfig.xml

<mappers>
        <mapperresource="sqlmap/User.xml"/>
</mappers>

四、增刪改查用戶

1、根據ID查詢用戶信息

1.1 User.xml中

<!-- 根據id獲取用戶信息 -->
    <select id="findUserById" parameterType="Integer" resultType="cn.guojie.mybatis.domain.User">   // MyBatis已為Java.lang.Integer用別名Integer
        select * from user where id = #{id}
    </select>

parameterType:入參類型,通過ONGL從輸入對象中獲取參數值拼接到sql中

resultType:返回結果集類型,將sql查詢結果的一行記錄數據映射為resultType指定的類型對象

#{id}:設置占位符,並將入參id傳給sql

1.2 測試

public class UserTest {
    
    //會話工廠,單例,可重復使用
    private SqlSessionFactory sqlSessionFactory;

    @Before  // 在測試方法前執行
    public void createSqlSessionFactory() throws IOException {
        // 讀取核心配置文件
        String resource = "SqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 創建SqlSessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder()
                .build(inputStream);

    }

    // 根據 id查詢用戶信息
    @Test
    public void testFindUserById() {
        // 數據庫會話實例
        SqlSession sqlSession = null;
        try {
            // 創建數據庫會話實例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 查詢單個記錄,根據用戶id查詢用戶信息,查詢多條記錄用selectList,命名空間+.+sql中的id
            User user = sqlSession.selectOne("test.findUserById", 10);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }
}

2、根據用戶名查詢用戶信息

2.1 User.xml中

    <!-- 自定義條件查詢用戶列表 -->
    <select id="findUserByUsername" parameterType="java.lang.String"
            resultType="cn.guojie.mybatis.domain.User">
       select * from user where username like ‘%${value}%‘  // 也可以是"%"#{id}"%"
    </selec

${}:拼接字符串,基本類型必須用value

2.2 測試

// 根據用戶名稱模糊查詢用戶信息
    @Test
    public void testFindUserByUsername() {
        // 數據庫會話實例
        SqlSession sqlSession = null;
        try {
            // 創建數據庫會話實例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 模糊查詢,查詢用戶名為張的用戶
            List<User> list = sqlSession.selectList("test.findUserByUsername", "張");
            System.out.println(list.size());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

#{}和${}的區別:

#{}:占位符,防止SQL註入,通常在=後

${}:拼串,只能是value,將參數拼接到sql中。在頁面或者action中校驗,不可輸入SQL關鍵字和空格來防止SQL註入。通常在like後

3、添加用戶

3.1 User.xml中

<!-- 添加用戶 -->
    <inser tid="insertUser" parameterType="cn.guojie.mybatis.domain.User">
      insert into user(username,birthday,sex,address) 
      values(#{username},#{birthday},#{sex},#{address})
    </insert>

3.2 測試

// 添加用戶信息
    @Test
    public void testInsert() {
        // 數據庫會話實例
        SqlSession sqlSession = null;
        try {
            // 創建數據庫會話實例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 添加用戶信息
            User user = new User();
            user.setUsername("張小明");
            user.setAddress("河南鄭州");
            user.setSex("1");
            user.setPrice(1999.9f);
            sqlSession.insert("test.insertUser", user);
            //提交事務,需要手動提交事務
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

4、MySQL自增主鍵返回

用來查詢上一個插入的ID

<insert id="insertUser" parameterType="cn.guojie.mybatis.domain.User">
   <!-- selectKey將主鍵返回,需要再返回 -->
  <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select LAST_INSERT_ID()
   </selectKey>
   insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address});
</insert>

LAST_INSERT_ID():數據庫海曙,返回自增的主鍵

keyProperty: 將返回的主鍵放入入參id中保存

order:相對於insert語句的執行順序

resultType:id的類型,也就是keyproperties中屬性的類型

5、MySQL中用UUID實現主鍵

<insert id="insertUser" parameterType="cn.guojie.mybatis.domain.User">
  <selectKey resultType="java.lang.String"  order="BEFORE" 
  keyProperty="id">
  select uuid()
  </selectKey>
  insert into user(id,username,birthday,sex,address) values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>

6、刪除用戶

6.1 User.xml中

<!-- 刪除用戶 -->
    <delete id="deleteUserById" parameterType="int">
        delete from user where id=#{id}
    </delete>

6.2 測試

// 根據id刪除用戶
    @Test
    public void testDelete() {
        // 數據庫會話實例
        SqlSession sqlSession = null;
        try {
            // 創建數據庫會話實例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 刪除用戶
            sqlSession.delete("test.deleteUserById",18);
            // 提交事務
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

7、修改用戶

7.1 User.xml

<!-- 更新用戶 -->
<update id="updateUser" parameterType="cn.guojie.mybatis.domain.User">
     update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
        where id=#{id}
</update>

7.2 測試

    @Test
    public void testUpdate() {
        // 數據庫會話實例
        SqlSession sqlSession = null;
        try {
            // 創建數據庫會話實例sqlSession
            sqlSession = sqlSessionFactory.openSession();
            // 添加用戶信息
            User user = new User();
            user.setId(16);
            user.setUsername("張小明");
            user.setAddress("河南鄭州");
            user.setSex("1");
            user.setPrice(1999.9f);
            sqlSession.update("test.updateUser", user);
            // 需要手動提交事務
            sqlSession.commit();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }
    }

SqlSession不是線程安全的,在方法體中創建與銷毀

五、DAO開發

1、原始DAO開發(用得少)

需要DAO接口及其實現類

不足:

(1) 方法中代碼重復(sqlSessionFactory創建SqlSession,調用SqlSession的數據可操作方法)

(2)硬編碼(SqlSession操作方法需要指定statement的id)

2、Mapper動態代理(常用)

只需Mapper接口(相當於DAO接口),MyBatis根據接口定義創建接口的動態代理對象

2.1 開發規範

(1)接口方法名和mapper.xml中id名相同

(2)入參類型和mapper.xml中入參parammeterType相同

(3)返回值類型和mapper.xml的返回類型resultType相同

(4)接口類全路徑(包名+類名)和mapper.xml中命名空間相同

2.2 映射文件UserMapper.xml 放在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">
<mapper namespace="cn.guojie.mybatis.mapper.UserMapper">  ----> 4
<!-- 根據id獲取用戶信息 -->
    <select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">  ----> 1 2 3
        select * from user where id = #{id}
    </select>
<!-- 自定義條件查詢用戶列表 -->
    <select id="findUserByUsername" parameterType="java.lang.String"
            resultType="cn.guojie.mybatis.domain.User">
       select * from user where username like ‘%${value}%‘ 
    </select>
<!-- 添加用戶 -->
    <inser tid="insertUser"parameter Type="cn.guojie.mybatis.domain.User">
    <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
        select LAST_INSERT_ID() 
    </selectKey>
      insert into user(username,birthday,sex,address) 
      values(#{username},#{birthday},#{sex},#{address})
    </insert>

</mapper>

2.3 UserMapper接口  和映射文件放在同一目錄

Public interface UserMapper {
    //根據用戶id查詢用戶信息
    public User findUserById(int id) throws Exception;
    //查詢用戶列表
    public List<User> findUserByUsername(String username) throws Exception;
    //添加用戶信息
    publicvoid insertUser(User user)throws Exception; 
}

2.4 加載UserMapper.xml

<!-- 加載映射文件 -->
<mappers>
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>

2.5 測試

Public class UserMapperTest {

    private SqlSessionFactory sqlSessionFactory;
    
    @Before
    protectedvoid setUp() throws Exception {
        // 加載mybatis配置文件
        String resource = "sqlMapConfig.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        // 創建sessionFactory
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    Public void testFindUserById() throws Exception {
        // 獲取session
        SqlSession session = sqlSessionFactory.openSession();
        // 獲取mapper接口的代理對象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        // 調用代理對象方法
        User user = userMapper.findUserById(1);
        System.out.println(user);
        // 關閉session
        session.close();
        
    }

    @Test
    public void testFindUserByUsername() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = userMapper.findUserByUsername("張");
        System.out.println(list.size());

    }

  @Test
  Public void testInsertUser() throws Exception {
        //獲取session
        SqlSession session = sqlSessionFactory.openSession();
        //獲取mapper接口的代理對象
        UserMapper userMapper = session.getMapper(UserMapper.class);
        //要添加的數據
        User user = new User();
        user.setUsername("張三");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("北京市");
        //通過mapper接口添加用戶
        userMapper.insertUser(user);
        //提交
        session.commit();
        //關閉session
        session.close();
    }
}

六、核心配置文件SqlMapConfig.xml

1、<properties>

在src下定義db.properties,其中不能有空格

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

SqlMapConfig.xml中引用

<properties resource="db.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
</properties>

2、<typeAliases> 別名

<typeAliases>
    <!-- 單個別名定義 -->
    <typeAliasalias="user"type="cn.itcast.mybatis.po.User"/>
    <!-- 批量別名定義,掃描整個包下的類,別名為類名(首字母大寫或小寫都可以) -->  // 常用
    <packagename="cn.guojie.mybatis.domain"/>
    <packagename="其它包"/>
</typeAliases>

3、<mapper>映射

resource=UserMapper.xml的類路徑

class=UserMapper接口的類路徑,要求mapper接口和mapper.xml同名且在同一目錄中

<package class="接口 " /> 註冊包下所有接口(常用),要求mapper接口和mapper.xml同名且在同一目錄中

MyBatis學習(一)