1. 學習計划
1、輸入映射和輸出映射
a) 輸入參數映射
b) 返回值映射
2、動態sql
a) If標簽
b) Where標簽
c) Sql片段
d) Foreach標簽
3、關聯查詢
a) 一對一關聯
b) 一對多關聯
4、Mybatis整合spring
a) 如何整合spring
b) 使用原始的方式開發dao
c) 使用Mapper接口動態代理
5、Mybatis逆向工程(掌握)
2. 輸入映射和輸出映射
Mapper.xml映射文件中定義了操作數據庫的sql,每個sql是一個statement,映射文件是mybatis的核心。
2.1. 環境准備
1. 復制昨天的工程,按照下圖進行

2.如下圖粘貼,並更名

3.只保留Mapper接口開發相關的文件,其他的刪除
最終效果如下圖:

4.如下圖修改SqlMapConfig.xml配置文件。Mapper映射器只保留包掃描的方式

2.2. parameterType(輸入類型)
2.2.1. 傳遞簡單類型
參考第一天內容。
使用#{}占位符,或者${}進行sql拼接。
2.2.2. 傳遞pojo對象
參考第一天的內容。
Mybatis使用ognl表達式解析對象字段的值,#{}或者${}括號中的值為pojo屬性名稱。
2.2.3. 傳遞pojo包裝對象
開發中通過可以使用pojo傳遞查詢條件。
查詢條件可能是綜合的查詢條件,不僅包括用戶查詢條件還包括其它的查詢條件(比如查詢用戶信息的時候,將用戶購買商品信息也作為查詢條件),這時可以使用包裝對象傳遞輸入參數。
包裝對象:Pojo類中的一個屬性是另外一個pojo。
需求:根據用戶名模糊查詢用戶信息,查詢條件放到QueryVo的user屬性中。
2.2.3.1. 編寫QueryVo
public class QueryVo { // 包含其他的pojo private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
2.2.3.2. Sql語句
SELECT * FROM user WHERE username LIKE '%張%'
2.2.3.3. Mapper.xml文件
在UserMapper.xml中配置sql,如下圖。

2.2.3.4. Mapper接口
在UserMapper接口中添加方法,如下圖:

2.2.3.5. 測試方法
在UserMapeprTest增加測試方法,如下:
@Test public void testQueryUserByQueryVo() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行查詢,使用包裝對象 QueryVo queryVo = new QueryVo(); // 設置user條件 User user = new User(); user.setUsername("張"); // 設置到包裝對象中 queryVo.setUser(user); // 執行查詢 List<User> list = userMapper.queryUserByQueryVo(queryVo); for (User u : list) { System.out.println(u); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
2.2.3.6. 效果
測試結果如下圖:

2.3. resultType(輸出類型)
2.3.1. 輸出簡單類型
需求:查詢用戶表數據條數
sql:SELECT count(*) FROM `user`
2.3.1.1. Mapper.xml文件
在UserMapper.xml中配置sql,如下圖:

2.3.1.2. Mapper接口
在UserMapper添加方法,如下圖:

2.3.1.3. 測試方法
在UserMapeprTest增加測試方法,如下:
@Test public void testQueryUserCount() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行查詢用戶數據條數 int count = userMapper.queryUserCount(); System.out.println(count); // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
2.3.1.4. 效果
測試結果如下圖:

注意:輸出簡單類型必須查詢出來的結果集有一條記錄,最終將第一個字段的值轉換為輸出類型。
2.3.2. 輸出pojo對象
參考第一天內容
2.3.3. 輸出pojo列表
參考第一天內容。
2.4. resultMap
resultType可以指定將查詢結果映射為pojo,但需要pojo的屬性名和sql查詢的列名一致方可映射成功。
如果sql查詢字段名和pojo的屬性名不一致,可以通過resultMap將字段名和屬性名作一個對應關系 ,resultMap實質上還需要將查詢結果映射到pojo對象中。
resultMap可以實現將查詢結果映射為復雜類型的pojo,比如在查詢結果映射對象中包括pojo和list實現一對一查詢和一對多查詢。
需求:查詢訂單表order的所有數據
sql:SELECT id, user_id, number, createtime, note FROM `order`
2.4.1. 聲明pojo對象
數據庫表如下圖:

Order對象:
public class Order { // 訂單id private int id; // 用戶id private Integer userId; // 訂單號 private String number; // 訂單創建時間 private Date createtime; // 備注 private String note; get/set。。。 }
2.4.2. Mapper.xml文件
創建OrderMapper.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"> <!-- namespace:命名空間,用於隔離sql,還有一個很重要的作用,Mapper動態代理開發的時候使用,需要指定Mapper的類路徑 --> <mapper namespace="cn.itcast.mybatis.mapper.OrderMapper"> <!-- 查詢所有的訂單數據 --> <select id="queryOrderAll" resultType="order"> SELECT id, user_id, number, createtime, note FROM `order` </select> </mapper>
2.4.3. Mapper接口
編寫接口如下:
public interface OrderMapper { /** * 查詢所有訂單 * * @return */ List<Order> queryOrderAll(); }public interface OrderMapper { /** * 查詢所有訂單 * * @return */ List<Order> queryOrderAll(); }
2.4.4. 測試方法
編寫測試方法OrderMapperTest如下:
public class OrderMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void init() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); this.sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testQueryAll() { // 獲取sqlSession SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 獲取OrderMapper OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); // 執行查詢 List<Order> list = orderMapper.queryOrderAll(); for (Order order : list) { System.out.println(order); } } }
2.4.5. 效果
測試效果如下圖:

發現userId為null
解決方案:使用resultMap
2.4.6. 使用resultMap
由於上邊的mapper.xml中sql查詢列(user_id)和Order類屬性(userId)不一致,所以查詢結果不能映射到pojo中。
需要定義resultMap,把orderResultMap將sql查詢列(user_id)和Order類屬性(userId)對應起來
改造OrderMapper.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"> <!-- namespace:命名空間,用於隔離sql,還有一個很重要的作用,Mapper動態代理開發的時候使用,需要指定Mapper的類路徑 --> <mapper namespace="cn.itcast.mybatis.mapper.OrderMapper"> <!-- resultMap最終還是要將結果映射到pojo上,type就是指定映射到哪一個pojo --> <!-- id:設置ResultMap的id --> <resultMap type="order" id="orderResultMap"> <!-- 定義主鍵 ,非常重要。如果是多個字段,則定義多個id --> <!-- property:主鍵在pojo中的屬性名 --> <!-- column:主鍵在數據庫中的列名 --> <id property="id" column="id" /> <!-- 定義普通屬性 --> <result property="userId" column="user_id" /> <result property="number" column="number" /> <result property="createtime" column="createtime" /> <result property="note" column="note" /> </resultMap> <!-- 查詢所有的訂單數據 --> <select id="queryOrderAll" resultMap="orderResultMap"> SELECT id, user_id, number, createtime, note FROM `order` </select> </mapper>
2.4.7. 效果
只需要修改Mapper.xml就可以了,再次測試結果如下:

3. 動態sql
通過mybatis提供的各種標簽方法實現動態拼接sql。
需求:根據性別和名字查詢用戶
查詢sql:
SELECT id, username, birthday, sex, address FROM `user` WHERE sex = 1 AND username LIKE '%張%'
3.1. If標簽
3.1.1. Mapper.xml文件
UserMapper.xml配置sql,如下:
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE sex = #{sex} AND username LIKE '%${username}%' </select>
3.1.2. Mapper接口
編寫Mapper接口,如下圖:

3.1.3. 測試方法
在UserMapperTest添加測試方法,如下:
@Test public void testQueryUserByWhere() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 User user = new User(); user.setSex("1"); user.setUsername("張"); List<User> list = userMapper.queryUserByWhere(user); for (User u : list) { System.out.println(u); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
3.1.4. 效果
測試效果如下圖:

如果注釋掉 user.setSex("1"),測試結果如下圖:

測試結果二很顯然不合理。
按照之前所學的,要解決這個問題,需要編寫多個sql,查詢條件越多,需要編寫的sql就更多了,顯然這樣是不靠譜的。
解決方案,使用動態sql的if標簽
3.1.5. 使用if標簽
改造UserMapper.xml,如下:
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` WHERE 1=1 <if test="sex != null and sex != ''"> AND sex = #{sex} </if> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> </select>
注意字符串類型的數據需要要做不等於空字符串校驗。
3.1.6. 效果

如上圖所示,測試OK
3.2. Where標簽
上面的sql還有where 1=1 這樣的語句,很麻煩
可以使用where標簽進行改造
改造UserMapper.xml,如下
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> SELECT id, username, birthday, sex, address FROM `user` <!-- where標簽可以自動添加where,同時處理sql語句中第一個and關鍵字 --> <where> <if test="sex != null"> AND sex = #{sex} </if> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> </where> </select>
3.2.1. 效果
測試效果如下圖:

3.3. Sql片段
Sql中可將重復的sql提取出來,使用時用include引用即可,最終達到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出來,作為sql片段,如下:
<!-- 根據條件查詢用戶 --> <select id="queryUserByWhere" parameterType="user" resultType="user"> <!-- SELECT id, username, birthday, sex, address FROM `user` --> <!-- 使用include標簽加載sql片段;refid是sql片段id --> SELECT <include refid="userFields" /> FROM `user` <!-- where標簽可以自動添加where關鍵字,同時處理sql語句中第一個and關鍵字 --> <where> <if test="sex != null"> AND sex = #{sex} </if> <if test="username != null and username != ''"> AND username LIKE '%${username}%' </if> </where> </select> <!-- 聲明sql片段 --> <sql id="userFields"> id, username, birthday, sex, address </sql>
如果要使用別的Mapper.xml配置的sql片段,可以在refid前面加上對應的Mapper.xml的namespace
例如下圖

3.4. foreach標簽
向sql傳遞數組或List,mybatis使用foreach解析,如下:
根據多個id查詢用戶信息
查詢sql:
SELECT * FROM user WHERE id IN (1,10,24)
3.4.1. 改造QueryVo
如下圖在pojo中定義list屬性ids存儲多個用戶id,並添加getter/setter方法

3.4.2. Mapper.xml文件
UserMapper.xml添加sql,如下:
<!-- 根據ids查詢用戶 --> <select id="queryUserByIds" parameterType="queryVo" resultType="user"> SELECT * FROM `user` <where> <!-- foreach標簽,進行遍歷 --> <!-- collection:遍歷的集合,這里是QueryVo的ids屬性 --> <!-- item:遍歷的項目,可以隨便寫,,但是和后面的#{}里面要一致 --> <!-- open:在前面添加的sql片段 --> <!-- close:在結尾處添加的sql片段 --> <!-- separator:指定遍歷的元素之間使用的分隔符 --> <foreach collection="ids" item="item" open="id IN (" close=")" separator=","> #{item} </foreach> </where> </select>
測試方法如下圖:
@Test public void testQueryUserByIds() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 QueryVo queryVo = new QueryVo(); List<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(10); ids.add(24); queryVo.setIds(ids); List<User> list = userMapper.queryUserByIds(queryVo); for (User u : list) { System.out.println(u); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
3.4.3. 效果
測試效果如下圖:

其他實現:

底層原理:傳遞進去的user並沒有被引用,而是重新創建一個map把user里面的值存在map里面,傳入如果是數組那就會放在array中,如果是List就會放在list中。

4. 關聯查詢
4.1. 商品訂單數據模型

4.2. 一對一查詢
需求:查詢所有訂單信息,關聯查詢下單用戶信息。
注意:因為一個訂單信息只會是一個人下的訂單,所以從查詢訂單信息出發關聯查詢用戶信息為一對一查詢。如果從用戶信息出發查詢用戶下的訂單信息則為一對多查詢,因為一個用戶可以下多個訂單。
sql語句:
SELECT o.id, o.user_id userId, o.number, o.createtime, o.note, u.username, u.address FROM `orders` o LEFT JOIN `user` u ON o.user_id = u.id
4.2.1. 方法一:使用resultType
使用resultType,改造訂單pojo類,此pojo類中包括了訂單信息和用戶信息
這樣返回對象的時候,mybatis自動把用戶信息也注入進來了
4.2.1.1. 改造pojo類
OrderUser類繼承Order類后OrderUser類包括了Order類的所有字段,只需要定義用戶的信息字段即可,如下圖:

4.2.1.2. Mapper.xml
在UserMapper.xml添加sql,如下
<!-- 查詢訂單,同時包含用戶數據 --> <select id="queryOrderUser" resultType="orderUser"> SELECT o.id, o.user_id userId, o.number, o.createtime, o.note, u.username, u.address FROM `order` o LEFT JOIN `user` u ON o.user_id = u.id </select>
4.2.1.3. Mapper接口
在UserMapper接口添加方法,如下圖:

4.2.1.4. 測試方法:
在UserMapperTest添加測試方法,如下:
@Test public void testQueryOrderUser() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 List<OrderUser> list = userMapper.queryOrderUser(); for (OrderUser ou : list) { System.out.println(ou); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
4.2.1.5. 效果
測試結果如下圖:

4.2.1.6. 小結
定義專門的pojo類作為輸出類型,其中定義了sql查詢結果集所有的字段。此方法較為簡單,企業中使用普遍。
4.2.2. 方法二:使用resultMap
使用resultMap,定義專門的resultMap用於映射一對一查詢結果。
4.2.2.1. 改造pojo類
在Order類中加入User屬性,user屬性中用於存儲關聯查詢的用戶信息,因為訂單關聯查詢用戶是一對一關系,所以這里使用單個User對象存儲關聯查詢的用戶信息。
改造Order如下圖:

4.2.2.2. Mapper.xml
這里resultMap指定orderUserResultMap,如下:
<resultMap type="order" id="orderUserResultMap"> <id property="id" column="id" /> <result property="userId" column="user_id" /> <result property="number" column="number" /> <result property="createtime" column="createtime" /> <result property="note" column="note" /> <!-- association :配置一對一屬性 --> <!-- property:order里面的User屬性名 --> <!-- javaType:屬性類型 --> <association property="user" javaType="user"> <!-- id:聲明主鍵,表示user_id是關聯查詢對象的唯一標識--> <id property="id" column="user_id" /> <result property="username" column="username" /> <result property="address" column="address" /> </association> </resultMap> <!-- 一對一關聯,查詢訂單,訂單內部包含用戶屬性 --> <select id="queryOrderUserResultMap" resultMap="orderUserResultMap"> SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.address FROM `order` o LEFT JOIN `user` u ON o.user_id = u.id </select>
4.2.2.3. Mapper接口
編寫UserMapper如下圖:

4.2.2.4. 測試方法
在UserMapperTest增加測試方法,如下:
@Test public void testQueryOrderUserResultMap() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 List<Order> list = userMapper.queryOrderUserResultMap(); for (Order o : list) { System.out.println(o); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
4.2.2.5. 效果
測試效果如下圖:

4.3. 一對多查詢
案例:查詢所有用戶信息及用戶關聯的訂單信息。
用戶信息和訂單信息為一對多關系。
sql語句:
SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id
4.3.1. 修改pojo類
在User類中加入List<Order> orders屬性,如下圖:

4.3.2. Mapper.xml
在UserMapper.xml添加sql,如下:
<resultMap type="user" id="userOrderResultMap"> <id property="id" column="id" /> <result property="username" column="username" /> <result property="birthday" column="birthday" /> <result property="sex" column="sex" /> <result property="address" column="address" /> <!-- 配置一對多的關系 --> <collection property="orders" javaType="list" ofType="order"> <!-- 配置主鍵,是關聯Order的唯一標識 --> <id property="id" column="oid" /> <result property="number" column="number" /> <result property="createtime" column="createtime" /> <result property="note" column="note" /> </collection> </resultMap> <!-- 一對多關聯,查詢訂單同時查詢該用戶下的訂單 --> <select id="queryUserOrder" resultMap="userOrderResultMap"> SELECT u.id, u.username, u.birthday, u.sex, u.address, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN `order` o ON u.id = o.user_id </select>
4.3.3. Mapper接口
編寫UserMapper接口,如下圖:

4.3.4. 測試方法
在UserMapperTest增加測試方法,如下
@Test public void testQueryUserOrder() { // mybatis和spring整合,整合之后,交給spring管理 SqlSession sqlSession = this.sqlSessionFactory.openSession(); // 創建Mapper接口的動態代理對象,整合之后,交給spring管理 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 使用userMapper執行根據條件查詢用戶 List<User> list = userMapper.queryUserOrder(); for (User u : list) { System.out.println(u); } // mybatis和spring整合,整合之后,交給spring管理 sqlSession.close(); }
4.3.5. 效果
測試效果如下圖:

5. Mybatis整合spring
5.1. 整合思路
1、SqlSessionFactory對象應該放到spring容器中作為單例存在。
2、傳統dao的開發方式中,應該從spring容器中獲得sqlsession對象。
3、Mapper代理形式中,應該從spring容器中直接獲得mapper的代理對象。
4、數據庫的連接以及數據庫連接池事務管理都交給spring容器來完成。
5.2. 整合需要的jar包
1、spring的jar包
2、Mybatis的jar包
3、Spring+mybatis的整合包。
4、Mysql的數據庫驅動jar包。
5、數據庫連接池的jar包。
jar包位置如下所示:

5.3. 整合的步驟
5.3.1. 創建工程
如下圖創建一個java工程:

5.3.2. 導入jar包
前面提到的jar包需要導入,如下圖:

5.3.3. 加入配置文件
- mybatisSpring的配置文件
- 的配置文件sqlmapConfig.xml
a) 數據庫連接及連接池
b) 事務管理(暫時可以不配置)
c) sqlsessionFactory對象,配置到spring容器中
d) mapeer代理對象或者是dao實現類配置到spring容器中。
創建資源文件夾config拷貝加入配置文件,如下圖

5.3.3.1. SqlMapConfig.xml
配置文件是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> <!-- 設置別名 --> <typeAliases> <!-- 2. 指定掃描包,會把包內所有的類都設置別名,別名的名稱就是類名,大小寫不敏感 --> <package name="cn.itcast.mybatis.pojo" /> </typeAliases> </configuration>
5.3.3.2. applicationContext.xml
SqlSessionFactoryBean屬於mybatis-spring這個jar包
對於spring來說,mybatis是另外一個架構,需要整合jar包。
在項目中加入mybatis-spring-1.2.2.jar的源碼,如下圖


效果,如下圖所示,圖標變化,表示源碼加載成功:

整合Mybatis需要的是SqlSessionFactoryBean,位置如下圖:

applicationContext.xml,配置內容如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 加載配置文件 --> <context:property-placeholder location="classpath:db.properties" /> <!-- 數據庫連接池 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 配置mybatis核心配置文件 --> <property name="configLocation" value="classpath:SqlMapConfig.xml" /> <!-- 配置數據源 --> <property name="dataSource" ref="dataSource" /> </bean> </beans>
5.3.3.3. db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root
5.3.3.4. 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
5.3.3.5. 效果:
加入的配置文件最終效果如下:

5.4. Dao的開發
兩種dao的實現方式:
1、原始dao的開發方式
2、使用Mapper代理形式開發方式
a) 直接配置Mapper代理
b) 使用掃描包配置Mapper代理
需求:
- 實現根據用戶id查詢
- 實現根據用戶名模糊查詢
- 添加用戶
5.4.1. 創建pojo
public class User { private int id; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 get/set。。。 }
5.4.2. 傳統dao的開發方式
原始的DAO開發接口+實現類來完成。
需要dao實現類需要繼承SqlsessionDaoSupport類
5.4.2.1. 實現Mapper.xml
編寫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"> <!-- 根據用戶id查詢 --> <select id="queryUserById" parameterType="int" resultType="user"> select * from user where id = #{id} </select> <!-- 根據用戶名模糊查詢用戶 --> <select id="queryUserByUsername" parameterType="string" resultType="user"> select * from user where username like '%${value}%' </select> <!-- 添加用戶 --> <insert id="saveUser" parameterType="user"> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
5.4.2.2. 加載Mapper.xml
在SqlMapConfig如下圖進行配置:

5.4.2.3. 實現UserDao接口
public interface UserDao { /** * 根據id查詢用戶 * * @param id * @return */ User queryUserById(int id); /** * 根據用戶名模糊查詢用戶列表 * * @param username * @return */ List<User> queryUserByUsername(String username); /** * 保存 * * @param user */ void saveUser(User user); }
5.4.2.4. 實現UserDaoImpl實現類
編寫DAO實現類,實現類必須集成SqlSessionDaoSupport
SqlSessionDaoSupport提供getSqlSession()方法來獲取SqlSession
public class UserDaoImpl extends SqlSessionDaoSupport implements UserDao { @Override public User queryUserById(int id) { // 獲取SqlSession SqlSession sqlSession = super.getSqlSession(); // 使用SqlSession執行操作 User user = sqlSession.selectOne("queryUserById", id); // 不要關閉sqlSession return user; } @Override public List<User> queryUserByUsername(String username) { // 獲取SqlSession SqlSession sqlSession = super.getSqlSession(); // 使用SqlSession執行操作 List<User> list = sqlSession.selectList("queryUserByUsername", username); // 不要關閉sqlSession return list; } @Override public void saveUser(User user) { // 獲取SqlSession SqlSession sqlSession = super.getSqlSession(); // 使用SqlSession執行操作 sqlSession.insert("saveUser", user); // 不用提交,事務由spring進行管理 // 不要關閉sqlSession } }
5.4.2.5. 配置dao
把dao實現類配置到spring容器中,如下圖

5.4.2.6. 測試方法
創建測試方法,可以直接創建測試Junit用例。
如下圖所示進行創建。



編寫測試方法如下:
public class UserDaoTest { private ApplicationContext context; @Before public void setUp() throws Exception { this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testQueryUserById() { // 獲取userDao UserDao userDao = this.context.getBean(UserDao.class); User user = userDao.queryUserById(1); System.out.println(user); } @Test public void testQueryUserByUsername() { // 獲取userDao UserDao userDao = this.context.getBean(UserDao.class); List<User> list = userDao.queryUserByUsername("張"); for (User user : list) { System.out.println(user); } } @Test public void testSaveUser() { // 獲取userDao UserDao userDao = this.context.getBean(UserDao.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三國"); userDao.saveUser(user); System.out.println(user); } }
5.4.3. Mapper代理形式開發dao
5.4.3.1. 實現Mapper.xml
編寫UserMapper.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="cn.itcast.mybatis.mapper.UserMapper"> <!-- 根據用戶id查詢 --> <select id="queryUserById" parameterType="int" resultType="user"> select * from user where id = #{id} </select> <!-- 根據用戶名模糊查詢用戶 --> <select id="queryUserByUsername" parameterType="string" resultType="user"> select * from user where username like '%${value}%' </select> <!-- 添加用戶 --> <insert id="saveUser" parameterType="user"> <selectKey keyProperty="id" keyColumn="id" order="AFTER" resultType="int"> select last_insert_id() </selectKey> insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address}) </insert> </mapper>
5.4.3.2. 實現UserMapper接口
public interface UserMapper { /** * 根據用戶id查詢 * * @param id * @return */ User queryUserById(int id); /** * 根據用戶名模糊查詢用戶 * * @param username * @return */ List<User> queryUserByUsername(String username); /** * 添加用戶 * * @param user */ void saveUser(User user); }
5.4.3.3. 方式一:配置mapper代理
在applicationContext.xml添加配置
MapperFactoryBean也是屬於mybatis-spring整合包
<!-- Mapper代理的方式開發方式一,配置Mapper代理對象 --> <bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- 配置Mapper接口 --> <property name="mapperInterface" value="cn.itcast.mybatis.mapper.UserMapper" /> <!-- 配置sqlSessionFactory --> <property name="sqlSessionFactory" ref="sqlSessionFactory" /> </bean>
5.4.3.4. 測試方法
public class UserMapperTest { private ApplicationContext context; @Before public void setUp() throws Exception { this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testQueryUserById() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); User user = userMapper.queryUserById(1); System.out.println(user); } @Test public void testQueryUserByUsername() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); List<User> list = userMapper.queryUserByUsername("張"); for (User user : list) { System.out.println(user); } } @Test public void testSaveUser() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三國"); userMapper.saveUser(user); System.out.println(user); } }
5.4.3.5. 方式二:掃描包形式配置mapper
<!-- Mapper代理的方式開發方式二,掃描包方式配置代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置Mapper接口 --> <property name="basePackage" value="cn.itcast.mybatis.mapper" /> </bean>
每個mapper代理對象的id就是類名,首字母小寫
6. Mybatis逆向工程
使用官方網站的Mapper自動生成工具mybatis-generator-core-1.3.2來生成po類和Mapper映射文件
6.1. 導入逆向工程
使用課前資料已有逆向工程,如下圖:

6.1.1. 復制逆向工程到工作空間中
復制的效果如下圖:

6.1.2. 導入逆向工程到eclipse中
如下圖方式進行導入:



6.2. 修改配置文件
在generatorConfig.xml中配置Mapper生成的詳細信息,如下圖:

注意修改以下幾點:
- 修改要生成的數據庫表
- pojo文件所在包路徑
- Mapper所在的包路徑
配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自動生成的注釋 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--數據庫連接的信息:驅動類、連接地址、用戶名、密碼 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root" password="root"> </jdbcConnection> <!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver" connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg" userId="yycg" password="yycg"> </jdbcConnection> --> <!-- 默認false,把JDBC DECIMAL 和 NUMERIC 類型解析為 Integer,為 true時把JDBC DECIMAL 和 NUMERIC 類型解析為java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO類的位置 --> <javaModelGenerator targetPackage="cn.itcast.ssm.po" targetProject=".\src"> <!-- enableSubPackages:是否讓schema作為包的后綴 --> <property name="enableSubPackages" value="false" /> <!-- 從數據庫返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件生成的位置 --> <sqlMapGenerator targetPackage="cn.itcast.ssm.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema作為包的后綴 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="cn.itcast.ssm.mapper" targetProject=".\src"> <!-- enableSubPackages:是否讓schema作為包的后綴 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定數據庫表 --> <table schema="" tableName="user"></table> <table schema="" tableName="order"></table> </context> </generatorConfiguration>
6.3. 生成逆向工程代碼
找到下圖所示的java文件,執行工程main主函數,


刷新工程,發現代碼生成,如下圖:

6.4. 測試逆向工程代碼
1. 復制生成的代碼到mybatis-spring工程,如下圖

2. 修改spring配置文件
在applicationContext.xml修改
<!-- Mapper代理的方式開發,掃描包方式配置代理 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 配置Mapper接口,如果需要加載多個包,直接寫進來,中間用,分隔 --> <!-- <property name="basePackage" value="cn.itcast.mybatis.mapper" /> --> <property name="basePackage" value="cn.itcast.ssm.mapper" /> </bean>
3. 編寫測試方法:
public class UserMapperTest { private ApplicationContext context; @Before public void setUp() throws Exception { this.context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); } @Test public void testInsert() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); User user = new User(); user.setUsername("曹操"); user.setSex("1"); user.setBirthday(new Date()); user.setAddress("三國"); userMapper.insert(user); } @Test public void testSelectByExample() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); // 創建User對象擴展類,用戶設置查詢條件 UserExample example = new UserExample(); example.createCriteria().andUsernameLike("%張%"); // 查詢數據 List<User> list = userMapper.selectByExample(example); System.out.println(list.size()); } @Test public void testSelectByPrimaryKey() { // 獲取Mapper UserMapper userMapper = this.context.getBean(UserMapper.class); User user = userMapper.selectByPrimaryKey(1); System.out.println(user); } }
注意:
- 逆向工程生成的代碼只能做單表查詢
- 不能在生成的代碼上進行擴展,因為如果數據庫變更,需要重新使用逆向工程生成代碼,原來編寫的代碼就被覆蓋了。
- 一張表會生成4個文件
