Mybatis--day01

非本人總結(jié)的筆記,抄點(diǎn)筆記復(fù)習(xí)復(fù)習(xí)。感謝傳智博客及黑馬程序猿
成長(zhǎng)

什么是Mybatis

? MyBatis 本是apache的一個(gè)開源項(xiàng)目iBatis, 2010年這個(gè)項(xiàng)目由apache software foundation遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。 MyBatis是一個(gè)優(yōu)秀的持久層框架,它對(duì)jdbc的操作數(shù)據(jù)庫的過程進(jìn)行封裝,使開發(fā)者只需要關(guān)注 SQL 本身,而不需要花費(fèi)精力去處理例如注冊(cè)驅(qū)動(dòng)、創(chuàng)建connection、創(chuàng)建statement、手動(dòng)設(shè)置參數(shù)、結(jié)果集檢索等jdbc繁雜的過程代碼。
? Mybatis通過xml或注解的方式將要執(zhí)行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,并通過java對(duì)象和statement中的sql進(jìn)行映射生成最終執(zhí)行的sql語句,最后由mybatis框架執(zhí)行sql并將結(jié)果映射成java對(duì)象并返回。

單獨(dú)使用jdbc開發(fā)存在的問題

實(shí)現(xiàn)步驟

  1. 加載數(shù)據(jù)庫驅(qū)動(dòng)。根據(jù)不同的數(shù)據(jù)庫選擇不同的驅(qū)動(dòng)。
  2. 創(chuàng)建一個(gè)連接。獲得一個(gè)Connection對(duì)象。
  3. 創(chuàng)建一個(gè)prepareStatement對(duì)象,封裝了sql語句。
  4. 設(shè)置參數(shù)。
  5. 執(zhí)行查詢獲得一個(gè)ResultSet對(duì)象。
  6. 遍歷resultSet對(duì)象。

數(shù)據(jù)庫

數(shù)據(jù)庫

代碼實(shí)現(xiàn)

存在的問題

  1. 數(shù)據(jù)庫驅(qū)動(dòng)存在硬編碼的問題。寫到配置文件中來解決。
  2. 數(shù)據(jù)庫連接串、用戶名、密碼存在硬編碼的問題。
  3. Sql語句硬編碼
  4. 參數(shù)設(shè)置不靈活
  5. 查詢結(jié)果最好是返回一個(gè)pojo對(duì)象或者是pojo列表。
  6. 每次查詢都需要開啟連接關(guān)閉連接。浪費(fèi)性能。需要使用數(shù)據(jù)庫連接池。

Mybatis框架架構(gòu)

Mybatis框架架構(gòu)

Mybatis的入門程序

Mybatis的下載

mybatis的代碼由github.comg管理,地址:https://github.com/mybatis/mybatis-3/releases

目錄結(jié)構(gòu)

需求

實(shí)現(xiàn)以下功能:
根據(jù)用戶id查詢一個(gè)用戶信息
根據(jù)用戶名稱模糊查詢用戶信息列表
添加用戶
更新用戶
刪除用戶

入門程序?qū)崿F(xiàn)

工程搭建

第一步:創(chuàng)建一個(gè)java工程。
第二步:導(dǎo)入jar包。包括mybatis的jar包、mybatis依賴的jar包、mysql的數(shù)據(jù)庫驅(qū)動(dòng)。
第三步:創(chuàng)建一個(gè)log4j.properties。方便查看sql語句用的。
第四步:創(chuàng)建一個(gè)SqlMapConfig.xml。配置數(shù)據(jù)庫連接池。
第五步:創(chuàng)建Mapper映射文件。
第六步:編碼。

項(xiàng)目

SqlMapConfig.xml

在classpath下創(chuàng)建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">
        <environment id="development">
            <!-- 使用jdbc事務(wù)管理 -->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池 -->
            <dataSource type="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>
    
    <mappers>
    
    </mappers>
</configuration>

Mapper映射文件

習(xí)慣上mapper映射文件的名稱和數(shù)據(jù)庫的表名一致。Ibatis時(shí)代的習(xí)慣。

<?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的作用就是sql語句隔離,后面還有其他用途。 -->
<mapper namespace="test">
</mapper>

在SqlMapConfig.xml中加載mapper映射文件

<!-- 加載Mapper映射文件 -->
<mappers>
    <!-- resource從classpath下開始查找 -->
    <mapper resource="sqlmap/user.xml"/>
</mappers>

根據(jù)用戶id查詢一個(gè)用戶信息

創(chuàng)建一個(gè)POJO保存返回結(jié)果

POJO的屬性要求和數(shù)據(jù)庫中的字段相對(duì)應(yīng)

public class User {

    private int id;
    private String username;// 用戶姓名
    private String sex;// 性別
    private Date birthday;// 生日
    private String address;// 地址
    
    //set和get方法
}

Sql語句

select * from user where id = 10

Mapper文件

需要把sql語句寫到user.xml這個(gè)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的作用就是sql語句隔離,后面還有其他用途。 -->
<mapper namespace="test">
    <!-- 
        select:如果是一個(gè)select語句就需要使用select節(jié)點(diǎn)。
        id就是一個(gè)sql語句的id,代表一個(gè)sql語句。起個(gè)名字叫做StatementId。
        parameterType:參數(shù)的類型
        resultType:返回結(jié)果的類型,可以是pojo類型,需要pojo的全限定名。
        #{}:是一個(gè)占位符。相當(dāng)于jdbc中的“?”,括號(hào)內(nèi)容的名稱,如果是簡(jiǎn)單數(shù)據(jù)類型可以隨便起。
     -->
    <select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
        SELECT * from user where id = #{id}
    </select>
</mapper>

查詢方法

/**
* 根據(jù)id查詢用戶信息
*/
@Test
public void getUserById() throws Exception {
    //創(chuàng)建一SqlSessionFactory
    //把配置文件讀取到流中
    InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    //創(chuàng)建SqlSessionFactory對(duì)象
    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //創(chuàng)建sqlsession對(duì)象
    SqlSession sqlSession = sessionFactory.openSession();
    //查詢一條記錄使用selectOne方法
    //第一個(gè)參數(shù):statementID
    //第二個(gè)參數(shù):sql語句用到的參數(shù)
    User user = sqlSession.selectOne("test.getUserById", 10);
    System.out.println(user);
    //關(guān)閉sqlsession
    sqlSession.close();
}

根據(jù)用戶名查詢用戶

Sql語句

SELECT * from user where username LIKE '%張三%'

第一種方法

Mapper文件

<!-- 根據(jù)用戶名查詢用戶 -->
<!-- resultType是返回結(jié)果中一條記錄的類型 -->
<select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
    SELECT * from user where username LIKE #{name}
</select>

測(cè)試方法

@Test
public void getUserByName() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    //返回結(jié)果是多條記錄使用selectList
    List<User> userList = sqlSession.selectList("test.getUserByName", "%張三%");
    System.out.println(userList);
    sqlSession.close();
}

第二種方法

Mapper文件

<!-- 根據(jù)用戶名查詢用戶 -->
<!-- resultType是返回結(jié)果中一條記錄的類型 -->
<!-- ${}:字符串拼接指令??梢云囱b成一個(gè)完整的sql語句。缺點(diǎn)不能防止sql注入
  ${}內(nèi)部的名稱,如果是簡(jiǎn)單數(shù)據(jù)類型,必須是value
  -->
<select id="getUserByName" parameterType="string" resultType="cn.itcast.pojo.User">
    <!-- SELECT * from user where username LIKE #{name} -->
    SELECT * from user where username LIKE '%${value}%'
</select>

測(cè)試方法

@Test
public void getUserByName() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    //返回結(jié)果是多條記錄使用selectList
    //List<User> userList = sqlSession.selectList("test.getUserByName", "%張三%");
    List<User> userList = sqlSession.selectList("test.getUserByName", "張三");
    System.out.println(userList);
    sqlSession.close();
}

添加用戶

Sql語句

INSERT INTO user`(username,birthday,sex,address) VALUES('','','','')

Mapper文件

<!-- 添加用戶 -->
<!-- 取對(duì)象中的屬性直接使用#{}來取,括號(hào)中的名稱必須是對(duì)象的屬性名 -->
<insert id="insertUser" parameterType="cn.itcast.pojo.User">
        INSERT INTO `user`(username,birthday,sex,address) 
        VALUES(#{username},#{birthday},#{sex},#{address})
</insert>

測(cè)試方法

@Test
public void insertUser() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //添加用戶
        User user = new User();
        user.setUsername("入云龍");
        user.setSex("1");
        user.setAddress("天津薊縣");
        user.setBirthday(new Date());
        sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
}

主鍵返回

在mysql中可以使用SELECT LAST_INSERT_ID();方法取當(dāng)前事務(wù)中最后生成的id。在mybatis可以使用主鍵返回方法,把主鍵取出來返回給java程序。

<!-- 添加用戶 -->
    <!-- 取對(duì)象中的屬性直接使用#{}來取,括號(hào)中的名稱必須是對(duì)象的屬性名 -->
    <insert id="insertUser" parameterType="cn.itcast.pojo.User">
        <!-- keyProperty:user對(duì)象的主鍵屬性
            resultType:主鍵的數(shù)據(jù)類型
            order:取主鍵語句的執(zhí)行時(shí)機(jī)。BEFORE:在插入之前執(zhí)行     AFTER:插入之后執(zhí)行
          -->
        <selectKey keyProperty="id" resultType="int" order="AFTER">
            <!-- mysql取主鍵的函數(shù) -->
            SELECT LAST_INSERT_ID();
        </selectKey>
        INSERT INTO `user`(username,birthday,sex,address) 
        VALUES(#{username},#{birthday},#{sex},#{address})
    </insert>

修改用戶

Sql語句

UPDATE USER SET username = ' ', birthday= ' ', sex= ' ', address = '' WHERE id= 10

Mapper文件

<!-- 修改用戶信息 -->
<update id="updateUser" parameterType="cn.itcast.pojo.User">
    UPDATE USER
    SET username = #{username},
    birthday = #{birthday},
    sex = #{sex},
    address = #{address}
    WHERE
    id = #{id}
</update>

測(cè)試方法

@Test
    public void updateUser() throws Exception {
        SqlSession sqlSession = sessionFactory.openSession();
        //取用戶信息
        User user = sqlSession.selectOne("test.getUserById", 28);
        user.setUsername("武松");
        user.setAddress("清河縣");
        sqlSession.update("test.updateUser", user);
        //提交修改
        sqlSession.commit();
        sqlSession.close();
    }

刪除用戶

Sql語句

DELETE from user where id=10

Mapper文件

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

測(cè)試方法

@Test
public void deleteUserById() {
    SqlSession sqlSession = sessionFactory.openSession();
    sqlSession.delete("test.deleteUserById", 28);
    sqlSession.commit();
    sqlSession.close();
}

Mybatis和Hibernate的區(qū)別

  1. Mybatis并不是一個(gè)完全的orm框架。Hibernate是面向?qū)ο螅梢圆皇褂胹ql語句。Mybatis是面向sql語句的。專注的是輸入映射返回值映射以及sql語句的靈活性。
  2. Mybatis門檻比較低,學(xué)習(xí)起來比較簡(jiǎn)單。查詢性能,hibernate需要對(duì)性能進(jìn)行優(yōu)化,需要一個(gè)高手。Mybatis只需要對(duì)sql優(yōu)化即可。
  3. Hibernate主要是應(yīng)用在傳統(tǒng)項(xiàng)目,開發(fā)速度很快。Mybatis主要用于互聯(lián)網(wǎng)領(lǐng)域。適用于變化比較快的領(lǐng)域。
  4. 選擇框架時(shí),根據(jù)團(tuán)隊(duì)的技術(shù)儲(chǔ)備。選擇比較熟悉的框架。

使用Mybatis開發(fā)dao的方法

Sqlsession應(yīng)用范圍

Sqlsession

本身是線程不安全的,最佳應(yīng)用范圍應(yīng)該是方法級(jí)別。

SqlsessionFactory

工廠類,創(chuàng)建Sqlsession的。此對(duì)象應(yīng)該是單例模式出現(xiàn)在系統(tǒng)中,一個(gè)系統(tǒng)中只有一個(gè)SqlsessionFactory對(duì)象。

SqlsessionFactoryBuilder

當(dāng)做一個(gè)工具類使用,創(chuàng)建完SqlsessionFactory對(duì)象就不用了。

傳統(tǒng)方式

接口+實(shí)現(xiàn)類的方式

Dao

public class UserDaoImpl implements UserDao {
    
    private SqlSessionFactory sessionFactory;
    
    //構(gòu)造方法中注入SqlSessionFactory對(duì)象。
    public UserDaoImpl(SqlSessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public User getUserById(int id) {
        
        SqlSession sqlSession = sessionFactory.openSession();
        User user = sqlSession.selectOne("test.getUserById", id);
        sqlSession.close();
        return user;
    }

    @Override
    public List<User> getUserByName(String name) {
        SqlSession sqlSession = sessionFactory.openSession();
        List<User> userList = sqlSession.selectList("test.getUserByName", name);
        sqlSession.close();
        return userList;
    }

    @Override
    public void insertUser(User user) {
        SqlSession sqlSession = sessionFactory.openSession();
        sqlSession.insert("test.insertUser", user);
        sqlSession.commit();
        sqlSession.close();
    }

}

測(cè)試方法

public class UserDaoTest {
    
    private SqlSessionFactory sessionFactory;
    
    @Before
    public void init() throws Exception {
        // 創(chuàng)建一SqlSessionFactory
        // 把配置文件讀取到流中
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 創(chuàng)建SqlSessionFactory對(duì)象
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void testGetUserById() {
        UserDao userDao = new UserDaoImpl(sessionFactory);
        User user = userDao.getUserById(10);
        System.out.println(user);
    }

    @Test
    public void testGetUserByName() {
        UserDao userDao = new UserDaoImpl(sessionFactory);
        List<User> list = userDao.getUserByName("張三");
        System.out.println(list);
    }

    @Test
    public void testInsertUser() {
        UserDao userDao = new UserDaoImpl(sessionFactory);
        User user = new User();
        user.setUsername("武大郎");
        user.setBirthday(new Date());
        user.setSex("1");
        user.setAddress("清河縣");
        userDao.insertUser(user);
    }

}

存在的問題

  1. dao中操作數(shù)據(jù)庫的代碼重復(fù)??梢钥紤]使用模板替代。
  2. statementId存在硬編碼的問題。

使用Mapper代理的方法開發(fā)dao

只寫接口不寫實(shí)現(xiàn)類

開發(fā)規(guī)范

1、mapper文件的命名規(guī)則推薦是“表名+Mapper.xml”。接口文件的名稱和mapper映射文件的名稱一致。
2、Mapper文件的namespace必須是接口的全限定名。
3、StatementID必須和接口中方法的名稱一致。
4、接口的參數(shù)類型必須和parameterType一致。
5、接口的返回值類型必須和ResultType一致。

代碼實(shí)現(xiàn)

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的作用就是sql語句隔離.
 如果使用Mapper代理形式開發(fā),namespace必須是接口的全限定名-->
<mapper namespace="cn.mapper.UserMapper">
    <!-- 
        select:如果是一個(gè)select語句就需要使用select節(jié)點(diǎn)。
        id就是一個(gè)sql語句的id,代表一個(gè)sql語句。起個(gè)名字叫做StatementId。
        parameterType:參數(shù)的類型
        resultType:返回結(jié)果的類型,可以是pojo類型,需要pojo的全限定名。
        #{}:是一個(gè)占位符。相當(dāng)于jdbc中的“?”,括號(hào)內(nèi)容的名稱,如果是簡(jiǎn)單數(shù)據(jù)類型可以隨便起。
     -->
    <select id="getUserById" parameterType="int" resultType="cn.itcast.pojo.User">
        SELECT * from user where id = #{id}
    </select>
</mapper>

接口:

import cn.xx.pojo.User;

public interface UserMapper{
    Uasr getUserById(int id);
}

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">
        <environment id="development">
            <!-- 使用jdbc事務(wù)管理 -->
            <transactionManager type="JDBC" />
            <!-- 數(shù)據(jù)庫連接池 -->
            <dataSource type="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>
    <!-- 加載Mapper映射文件 -->
    <mappers>
        <!-- resource從classpath下開始查找 -->
        <mapper resource="sqlmap/user.xml" />
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

測(cè)試方法

@Test
public void testGetUserById() {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    User user = userMapper.getUserById(10);
    System.out.println(user);
    sqlSession.close();
}

@Test
public void testGetUserByName() {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> list = userMapper.getUserByName("張三");
    System.out.println(list);
    sqlSession.close();
}

Mapper代理形式是官方推薦的使用方法。也是企業(yè)開發(fā)中最常用的方法。

SqlMapConfig.xml

配置內(nèi)容

SqlMapConfig.xml中配置的內(nèi)容和順序如下:

properties(屬性)

settings(全局配置參數(shù))

typeAliases(類型別名)

typeHandlers(類型處理器)

objectFactory(對(duì)象工廠)

plugins(插件)

environments(環(huán)境集合屬性對(duì)象)

? environment(環(huán)境子屬性對(duì)象)

? transactionManager(事務(wù)管理)

? dataSource(數(shù)據(jù)源)

mappers(映射器)

注意:Mybatis的配置文件配置項(xiàng)是有順序的,不能打亂。

Properties

<!-- 屬性配置 -->
<!-- 可以使用resource加載外部配置文件 -->
<properties resource="db.properties">
    <property name="JDBC_DRIVER" value="com.mysql.jdbc.Driver"/>
    <property name="JDBV_URL" value="jdbc:mysql://localhost:3306/mybatis"/>
    <property name="JDBC_USER" value="root"/>
    <property name="JDBC_PASSWORD" value="root"/>
</properties>

如果同時(shí)使用的話,加載順序是先加載內(nèi)部的屬性,然后再加載外部的屬性。如果有重名的屬性會(huì)覆蓋。最終生效的是外部的屬性文件。

Settings

Mybatis的全局屬性配置

<settings>
    <setting name="cacheEnabled" value="false"/>
    <setting name="lazyLoadingEnabled" value="true"/>
</settings>

配置項(xiàng)參見

Setting(設(shè)置) Description(描述) Valid Values(驗(yàn)證值組) Default(默認(rèn)值)
cacheEnabled 在全局范圍內(nèi)啟用或禁用緩存配置任何映射器在此配置下。 true | false TRUE
lazyLoadingEnabled 在全局范圍內(nèi)啟用或禁用延遲加載。禁用時(shí),所有協(xié)會(huì)將熱加載。 true | false TRUE
aggressiveLazyLoading 啟用時(shí),有延遲加載屬性的對(duì)象將被完全加載后調(diào)用懶惰的任何屬性。否則,每一個(gè)屬性是按需加載。 true | false TRUE
multipleResultSetsEnabled 允許或不允許從一個(gè)單獨(dú)的語句(需要兼容的驅(qū)動(dòng)程序)要返回多個(gè)結(jié)果集。 true | false TRUE
useColumnLabel 使用列標(biāo)簽,而不是列名。在這方面,不同的驅(qū)動(dòng)有不同的行為。參考驅(qū)動(dòng)文檔或測(cè)試兩種方法來決定你的驅(qū)動(dòng)程序的行為如何。 true | false TRUE
useGeneratedKeys 允許JDBC支持生成的密鑰。兼容的驅(qū)動(dòng)程序是必需的。此設(shè)置強(qiáng)制生成的鍵被使用,如果設(shè)置為true,一些驅(qū)動(dòng)會(huì)不兼容性,但仍然可以工作。 true | false FALSE
autoMappingBehavior 指定MyBatis的應(yīng)如何自動(dòng)映射列到字段/屬性。NONE自動(dòng)映射。 PARTIAL只會(huì)自動(dòng)映射結(jié)果沒有嵌套結(jié)果映射定義里面。 FULL會(huì)自動(dòng)映射的結(jié)果映射任何復(fù)雜的(包含嵌套或其他)。 NONE, PARTIAL, FULL PARTIAL
defaultExecutorType 配置默認(rèn)執(zhí)行人。SIMPLE執(zhí)行人確實(shí)沒有什么特別的。 REUSE執(zhí)行器重用準(zhǔn)備好的語句。 BATCH執(zhí)行器重用語句和批處理更新。 SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout 設(shè)置驅(qū)動(dòng)程序等待一個(gè)數(shù)據(jù)庫響應(yīng)的秒數(shù)。 Any positive integer Not Set (null)
safeRowBoundsEnabled 允許使用嵌套的語句RowBounds。 true | false FALSE
mapUnderscoreToCamelCase 從經(jīng)典的數(shù)據(jù)庫列名A_COLUMN啟用自動(dòng)映射到駱駝標(biāo)識(shí)的經(jīng)典的Java屬性名aColumn。 true | false FALSE
localCacheScope MyBatis的使用本地緩存,以防止循環(huán)引用,并加快反復(fù)嵌套查詢。默認(rèn)情況下(SESSION)會(huì)話期間執(zhí)行的所有查詢緩存。如果localCacheScope=STATMENT本地會(huì)話將被用于語句的執(zhí)行,只是沒有將數(shù)據(jù)共享之間的兩個(gè)不同的調(diào)用相同的SqlSession。 SESSION | STATEMENT SESSION
dbcTypeForNull 指定為空值時(shí),沒有特定的JDBC類型的參數(shù)的JDBC類型。有些驅(qū)動(dòng)需要指定列的JDBC類型,但其他像NULL,VARCHAR或OTHER的工作與通用值。 JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods 指定觸發(fā)延遲加載的對(duì)象的方法。 A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage 指定所使用的語言默認(rèn)為動(dòng)態(tài)SQL生成。 A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
callSettersOnNulls 指定如果setter方法或地圖的put方法時(shí),將調(diào)用檢索到的值是null。它是有用的,當(dāng)你依靠Map.keySet()或null初始化。注意原語(如整型,布爾等)不會(huì)被設(shè)置為null。 true | false FALSE
logPrefix 指定的前綴字串,MyBatis將會(huì)增加記錄器的名稱。 Any String Not set
logImpl 指定MyBatis的日志實(shí)現(xiàn)使用。如果此設(shè)置是不存在的記錄的實(shí)施將自動(dòng)查找。 SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING Not set
proxyFactory 指定代理工具,MyBatis將會(huì)使用創(chuàng)建懶加載能力的對(duì)象。 CGLIB | JAVASSIST

typeAliases

別名配置

Mybatis中定義的別名

別名 映射的類型
_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
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
map Map

自定義別名

<!-- 別名配置 -->
<typeAliases>
        <!-- type:類的全限定名
            alias:別名
            別名不區(qū)分大小寫
         -->
        <!-- <typeAlias type="cn.itcast.pojo.User" alias="user"/> -->
        <!-- 可以使用package批量定義別名,name屬性就是pojo類所在的包名的全限定名
            別名就是類名,不區(qū)分大小寫。
         -->
    <package name="cn.itcast.pojo"/>
</typeAliases>

Mappers

加載Mapper映射文件

<!-- 加載Mapper映射文件 -->
    <mappers>
        <!-- resource從classpath下開始查找 -->
        <mapper resource="sqlmap/user.xml"/>
        <!-- <mapper resource="mapper/UserMapper.xml"/> -->
        <!-- url配置的是文件的全路徑 -->
        <!-- <mapper url="file:///D:\傳智播客\10.課堂筆記\0413\mybatis\day01\source\MybatisSecond0413\config\mapper\UserMapper.xml"/> -->
        <!-- class指定接口的全限定名,要求Mapper映射文件和接口在同一個(gè)目錄下,且名稱相同。 -->
        <!-- <mapper class="cn.itcast.mapper.UserMapper"/> -->
        <!-- mapper接口所在包的全限定名,mybatis會(huì)掃描包下的接口,加載和接口同名的mapper映射文件 -->
        <package name="cn.itcast.mapper"/>
    </mappers>

Mapper映射文件

輸入?yún)?shù)映射

基礎(chǔ)數(shù)據(jù)類型

Integer、String、float等

POJO類型參數(shù)

例如添加用戶、修改用戶時(shí)使用user對(duì)象作為參數(shù)

POJO的包裝類型

POJO中有一個(gè)屬性,類型是POJO。

使用場(chǎng)合:查詢條件復(fù)雜的時(shí)候,可以使用POJO的包裝類型

QueryVo

? |-user

? |-item

創(chuàng)建一個(gè)QueryVo

package cn.itcast.pojo;

public class QueryVo {

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
}

使用QueryVo查詢

需求:根據(jù)用戶id查詢用戶信息

QueryVo

? |-User

? |-id

Sql語句:select * from user where id=1

Mapper文件:

<select id="getUserByQueryVo" parameterType="QueryVo" resultType="user">
        <!-- 取屬性名稱使用“.”的方式來取 -->
        select * from user where id=#{user.id}
</select>

接口定義:

public interface UserMapper{
    User getUserByQueryVo(User user);   
}

測(cè)試方法:

@Test
public void testGetUserByQueryVo() {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //創(chuàng)建一個(gè)QueryVo對(duì)象
    QueryVo queryVo = new QueryVo();
    //創(chuàng)建一個(gè)user對(duì)象
    User user = new User();
    user.setId(10);
    queryVo.setUser(user);
        
    User userResult = userMapper.getUserByQueryVo(queryVo);
    System.out.println(userResult);
        
    sqlSession.close();
}

Map類型

使用map作為參數(shù)進(jìn)行映射。Map是key-value形式。綁定的時(shí)候應(yīng)該使用#{key}。

返回值映射

返回基礎(chǔ)數(shù)據(jù)類型

返回值是一個(gè)int或者String

Sql語句

select count(*) from user

Mapper 文件

<!-- 查詢用戶數(shù)量 -->
<select id="getUserCount" resultType="int">
    select count(*) from user
</select>

方法定義

public interface UserMapper {
    int getUserCount();
}

測(cè)試方法

@Test
public void testGetUserCount() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    int count = userMapper.getUserCount();
    System.out.println(count);
    sqlSession.close();
}

要求sql語句的查詢結(jié)果必須是一條記錄,可以是多個(gè)列,多個(gè)列的情況下只取第一列的內(nèi)容返回。

POJO類型的返回結(jié)果

根據(jù)用戶id查詢用戶信息。返回一個(gè)user對(duì)象就是一個(gè)pojo。

POJO的List結(jié)果

根據(jù)用戶名查詢用戶信息返回一個(gè)用戶列表就是一個(gè)pojoList。

返回一個(gè)Map類型

Pojo要求返回的結(jié)果中列名和pojo的屬性名要一致。

如果返回結(jié)果是map類型,那么key就是列名,value就是就是此列的值。

Pojo屬性名和列名不一致

  1. 修改sql語句,使用別名保證結(jié)果集中的列名和pojo的屬性名一致。
  2. 使用ResultMap

ResultMap入門

resultMap定義

<!-- resultMap的定義 -->
<!-- type:接收返回結(jié)果的數(shù)據(jù)類型,此處為user -->
<resultMap type="user" id="userResultMap">
    <!-- 
     id:為主鍵列
     column:結(jié)果集中的主鍵列的列名
     property:對(duì)應(yīng)user對(duì)象中保存主鍵屬性。
     -->
    <id column="id" property="id"/>
    <!-- 普通列 -->
    <result column="uname" property="username"/>
    <result column="bday" property="birthday"/>
    <result column="sex" property="sex"/>
    <result column="addr" property="address"/>
</resultMap>
<!-- resultMap屬性指定一個(gè)resultMap的id -->
<select id="getUserResultMap" resultMap="userResultMap">
    select id, username uname, birthday bday, sex, address addr from user
</select>

接口定義

public interface UserMapper{
    List<User> getUserResultMap();
}

測(cè)試方法

@Test
public void testGetUserResultMap() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> list = userMapper.getUserResultMap();
    System.out.println(list);
    sqlSession.close();
}

動(dòng)態(tài)sql

If

需求:根據(jù)參數(shù)的不同調(diào)整查詢條件

Mapper文件

<select id="getUserList" parameterType="user" resultType="user">
    select * from user
    where 0=0
    <if test="id!=null and id != 0">
        and id = #{id}
    </if>
    <if test="username != null and username != '' ">
        and username like '%${username}%'
    </if>
</select>

接口定義

public interface UserMapper{
    List<User> getUserList(User user);
}

測(cè)試方法

@Test
public void testGetUserList() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //創(chuàng)建user對(duì)象作為查詢條件
    User user = new User();
    user.setId(1);
    user.setUsername("張三");
    List<User> userList = userMapper.getUserList(user);
    System.out.println(userList);
    sqlSession.close();
}

Where

可以根據(jù)條件動(dòng)態(tài)的添加where關(guān)鍵字,并且可以去掉多余的and

<select id="geUserList" parameterType="user" resultType="user">
    select * from user
    <where>
        <if test="id != null and id != 0">
            and id = #{id}
        </if>
        <if test="username != null and username != ''">
            and username like '%${username}%'
        </if>
    </where>
</select>

Foreach

創(chuàng)建QueryVo對(duì)象

public class QueryVo {
    private User user;
    private int[] ids;
    //省略get和set方法
}

Mapper文件

<select id="getUserList" parameterType="QueryVo" resultType="user">
        select * from user
        <where>
            <if test="user!=null">
                <if test="user.id!=null and user.id != 0">
                    and id = #{user.id}
                </if>
                <if test="user.username != null and user.username != '' ">
                    and username like '%${user.username}%'
                </if>
            </if>
            <if test="ids!=null">
                <!-- 
                collection:QueryVo中的集合屬性ids
                open:前綴
                close:后綴
                item:循環(huán)的變量名稱
                separator:分隔符
                 -->
                <foreach collection="ids" open="and id in(" close=")" item="id" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
</select>

接口定義

public interface UserMapper{
    List<User> getUserList(QueryVo queryVo);
}

測(cè)試方法

@Test
public void testGetUserList() throws Exception {
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //創(chuàng)建user對(duì)象作為查詢條件
    User user = new User();
    //user.setId(1);
    //user.setUsername("張三");
    QueryVo queryVo = new QueryVo();
    queryVo.setUser(user);
    int[] ids = {1,10,16,22,24};
    queryVo.setIds(ids);
    List<User> userList = userMapper.getUserList(queryVo);
    System.out.println(userList);
    sqlSession.close();
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容