非本人總結(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)步驟
- 加載數(shù)據(jù)庫驅(qū)動(dòng)。根據(jù)不同的數(shù)據(jù)庫選擇不同的驅(qū)動(dòng)。
- 創(chuàng)建一個(gè)連接。獲得一個(gè)Connection對(duì)象。
- 創(chuàng)建一個(gè)prepareStatement對(duì)象,封裝了sql語句。
- 設(shè)置參數(shù)。
- 執(zhí)行查詢獲得一個(gè)ResultSet對(duì)象。
- 遍歷resultSet對(duì)象。
數(shù)據(jù)庫

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

Mybatis的入門程序
Mybatis的下載
mybatis的代碼由github.comg管理,地址:https://github.com/mybatis/mybatis-3/releases

需求
實(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映射文件。
第六步:編碼。

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ū)別
- Mybatis并不是一個(gè)完全的orm框架。Hibernate是面向?qū)ο螅梢圆皇褂胹ql語句。Mybatis是面向sql語句的。專注的是輸入映射返回值映射以及sql語句的靈活性。
- Mybatis門檻比較低,學(xué)習(xí)起來比較簡(jiǎn)單。查詢性能,hibernate需要對(duì)性能進(jìn)行優(yōu)化,需要一個(gè)高手。Mybatis只需要對(duì)sql優(yōu)化即可。
- Hibernate主要是應(yīng)用在傳統(tǒng)項(xiàng)目,開發(fā)速度很快。Mybatis主要用于互聯(lián)網(wǎng)領(lǐng)域。適用于變化比較快的領(lǐng)域。
- 選擇框架時(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);
}
}
存在的問題
- dao中操作數(shù)據(jù)庫的代碼重復(fù)??梢钥紤]使用模板替代。
- 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屬性名和列名不一致
- 修改sql語句,使用別名保證結(jié)果集中的列名和pojo的屬性名一致。
- 使用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();
}
