文檔版本 | 開發工具 | 測試平臺 | 工程名字 | 日期 | 作者 | 備註 |
---|---|---|---|---|---|---|
V1.0 | 2016.06.25 | lutianfei | none |
內容梳理
第一天:基礎知識(重點,內容量多)
- 對原生態jdbc程序(單獨使用jdbc開發)問題總結
- mybatis框架原理 (掌握)
- mybatis入門程序
- 用戶的增、刪、改、查
- mybatis開發dao兩種方法:
- 原始dao開發方法(程序需要編寫dao接口和dao實現類)(掌握)
- mybaits的mapper接口(相當於dao接口)代理開發方法(掌握)
- mybatis配置文件SqlMapConfig.xml
- mybatis核心:
- mybatis輸入映射(掌握)
- mybatis輸出映射(掌握)
- mybatis的動態sql(掌握)
第二天:高級知識
- 訂單商品數據模型分析
- 高級結果集映射(一對一、一對多、多對多)
- mybatis延遲加載
- mybatis查詢緩存(一級緩存、二級緩存)
- mybaits和spring進行整合(掌握)
- mybatis逆向工程
POJO : 名稱解釋
原生態jdbc程序中問題總結
1、數據庫連接,使用時就創建,不使用立即釋放,對數據庫進行頻繁連接開啓和關閉,造成數據庫資源浪費,影響 數據庫性能。
- 設想:使用數據庫連接池管理數據庫連接。
2、將sql語句硬編碼到java代碼中,如果sql 語句修改,需要重新編譯java代碼,不利於系統維護。
- 設想:將sql語句配置在xml配置文件中,即使sql變化,不需要對java代碼進行重新編譯。
3、向preparedStatement中設置參數,對佔位符號位置和設置參數值,硬編碼在java代碼中,不利於系統維護。
- 設想:將sql語句及佔位符號和參數全部配置在xml中。
4、從resutSet中遍歷結果集數據時,存在硬編碼,將獲取表的字段進行硬編碼,不利於系統維護。
- 設想:將查詢的結果集,自動映射成java對象。
Mybatis框架
MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,並且改名爲MyBatis,實質上Mybatis對ibatis進行一些改進。
MyBatis是一個優秀的持久層框架,它對jdbc的操作數據庫的過程進行封裝,使開發者只需要關注 SQL 本身,而不需要花費精力去處理例如註冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc繁雜的過程代碼。
Mybatis通過xml或註解的方式將要執行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,並通過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis框架執行sql並將結果映射成java對象並返回。
mybatis可以將向 preparedStatement中的輸入參數自動進行輸入映射,將查詢結果集靈活映射成java對象。(輸出映射)
MyBatis框架示意圖
mapper.xml文件即sql映射文件,文件中配置了操作數據庫的sql語句。此文件需要在SqlMapConfig.xml中加載。
通過mybatis環境等配置信息構造SqlSessionFactory即會話工廠
由會話工廠創建sqlSession即會話,操作數據庫需要通過sqlSession進行。
mybatis底層自定義了Executor執行器接口操作數據庫,Executor接口有兩個實現,一個是基本執行器、一個是緩存執行器。
Mapped Statement也是mybatis一個底層封裝對象,它包裝了mybatis配置信息及sql映射信息等。mapper.xml文件中一個sql對應一個Mapped Statement對象,sql的id即是Mapped statement的id。
Mapped Statement對sql執行輸入參數進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql前將輸入的java對象映射至sql中,輸入參數映射就是jdbc編程中對preparedStatement設置參數。
Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本類型、pojo,Executor通過Mapped Statement在執行sql後將輸出結果映射至java對象中,輸出結果映射過程相當於jdbc編程中對結果的解析處理過程。
MyBatis入門程序
需求
- 根據用戶id(主鍵)查詢用戶信息
- 根據用戶名稱模糊查詢用戶信息
- 添加用戶
- 刪除用戶
- 更新用戶
3.1 環境
- java環境:jdk1.7.0_72
- eclipse:indigo
- mysql:5.1
mybatis運行環境(jar包):
- 從 https://github.com/mybatis/mybatis-3/releases 下載,3.2.7版本
- 從 https://github.com/mybatis/mybatis-3/releases 下載,3.2.7版本
lib下:依賴包
- mybatis-3.2.7.jar:核心包
- mybatis-3.2.7.pdf,操作指南
創建mysql數據庫
先導入sql_table.sql,再導入 sql_data.sql腳本
- sql_table.sql:記錄表結構
- sql_data.sql:記錄測試數據,在實際企業開發中,最後提供一個初始化數據腳本
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
工程結構
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>
<!-- </a>和spring整合後 environments配置將廢除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事務管理-->
<transactionManager type="JDBC" />
<!-- 數據庫連接池-->
<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="mysql" />
</dataSource>
</environment>
</environments>
</configuration>
根據用戶id(主鍵)查詢用戶信息
創建po類
- Po類作爲mybatis進行sql映射使用,po類通常與數據庫表對應,User.java如下:
Public class User {
private int id;
private String username;// 用戶姓名
private String sex;// 性別
private Date birthday;// 生日
private String address;// 地址
get/set... toString
映射文件
映射文件命名:
- User.xml(原始ibatis命名)
- MyBatis的mapper代理開發映射文件名稱叫
XXXMapper.xml
- 比如:UserMapper.xml、ItemsMapper.xml
在映射文件中配置sql語句
- 在classpath下的sqlmap目錄下創建sql映射文件Users.xml:
- namespace : 命名空間,用於隔離sql語句,後面會講另一層非常重要的作用。
配置參數說明
- id:標識 映射文件中的 sql 將sql語句封裝到mappedStatement對象中,所以將id稱爲statement的id
- parameterType:指定輸入 參數的類型,這裏指定int型
#{}
表示一個佔位符號
#{id}
:其中的id表示接收輸入 的參數,參數名稱就是id,如果輸入 參數是簡單類型,#{}中的參數名可以任意,可以value或其它名稱
- resultType:指定sql輸出結果的所映射的java對象類型,select指定resultType表示將單條記錄映射成的java對象。
<?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進行分類化管理,理解sql隔離
注意:使用mapper代理方法開發,namespace有特殊重要的作用
-->
<mapper namespace="test">
<!-- 在 映射文件中配置很多sql語句 -->
<!-- 需求:通過id查詢用戶表的記錄 -->
<!-- 通過 select執行數據庫查詢
id:標識 映射文件中的 sql
將sql語句封裝到mappedStatement對象中,所以將id稱爲statement的id
parameterType:指定輸入 參數的類型,這裏指定int型
#{}表示一個佔位符號
#{id}:其中的id表示接收輸入 的參數,參數名稱就是id,如果輸入 參數是簡單類型,#{}中的參數名可以任意,可以value或其它名稱
resultType:指定sql輸出結果 的所映射的java對象類型,select指定resultType表示將單條記錄映射成的java對象。
-->
<select id="findUserById" parameterType="int" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE id=#{value}
</select>
在SqlMapConfig.xml加載映射文件
- 在sqlMapConfig.xml中加載User.xml;
- parameterType:定義輸入到sql中的映射類型,
#{id}
表示使用preparedstatement
設置佔位符號並將輸入變量id傳到sql。 - resultType:定義結果映射類型。
<!-- 加載 映射文件 -->
<mappers>
<mapper resource="sqlmap/User.xml"/>
<!--通過resource方法一次加載一個映射文件 -->
<!-- <mapper resource="mapper/UserMapper.xml"/> -->
</mappers>
測試程序編寫
public class MybatisFirst {
// 根據id查詢用戶信息,得到一條記錄結果
@Test
public void findUserByIdTest() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通過工廠得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession操作數據庫
// 第一個參數:映射文件中statement的id,等於=namespace+"."+statement的id
// 第二個參數:指定和映射文件中所匹配的parameterType類型的參數
// sqlSession.selectOne結果 是與映射文件中所匹配的resultType類型的對象
// selectOne查詢出一條記錄
User user = sqlSession.selectOne("test.findUserById", 1);
System.out.println(user);
// 釋放資源
sqlSession.close();
}
}
根據用戶名稱模糊查詢用戶信息
映射文件
- 使用User.xml,添加根據用戶名稱模糊查詢用戶信息的sql語句。
- resultType:指定就是單條記錄所映射的java對象 類型
- ${}:表示拼接sql串,將接收到參數的內容不加任何修飾拼接在sql中。
- 使用${}拼接sql,會引起sql注入
value:接收輸入參數的內容,如果傳入類型是簡單類型, {}中只能使用value
<!-- 根據用戶名稱模糊查詢用戶信息,可能返回多條
resultType:指定就是單條記錄所映射的java對象 類型
${}:表示拼接sql串,將接收到參數的內容不加任何修飾拼接在sql中。
使用${}拼接sql,引起 sql注入
${value}:接收輸入 參數的內容,如果傳入類型是簡單類型,${}中只能使用value
-->
<select id="findUserByName" parameterType="java.lang.String" resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE username LIKE '%${value}%'
</select>
程序代碼
// 根據用戶名稱模糊查詢用戶列表
@Test
public void findUserByNameTest() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通過工廠得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// list中的user和映射文件中resultType所指定的類型一致
List<User> list = sqlSession.selectList("test.findUserByName", "小明");
System.out.println(list);
sqlSession.close();
}
知識點回顧
#{}
和${}
#{}
表示一個佔位符號,通過#{}
可以實現preparedStatement向佔位符中設置值,自動進行java類型和jdbc類型轉換,#{}
可以有效防止sql注入。#{}
可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}
括號中可以是value或其它名稱。${}
表示拼接sql串,通過${}
可以將parameterType 傳入的內容拼接在sql中且不進行jdbc類型轉換,${}
可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,${}
括號中只能是value。
parameterType和resultType
- parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中獲取參數值拼接在sql中。
- resultType:指定輸出結果類型,mybatis將sql查詢結果的一行記錄數據映射爲resultType指定類型的對象。
selectOne和selectList
- selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:
- org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3 at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:70)
- selectList可以查詢一條或多條記錄。
- selectOne查詢一條記錄,如果使用selectOne查詢多條記錄則拋出異常:
添加用戶
- 在 User.xml中配置添加用戶的Statement
- 程序代碼
// 添加用戶信息
@Test
public void insertUserTest() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通過工廠得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 插入用戶對象
User user = new User();
user.setUsername("王小軍");
user.setBirthday(new Date());
user.setSex("1");
user.setAddress("河南鄭州");
sqlSession.insert("test.insertUser", user);
// 提交事務
sqlSession.commit();
// 獲取用戶信息主鍵
System.out.println(user.getId());
// 關閉會話
sqlSession.close();
}
- 自增主鍵返回
- mysql自增主鍵,執行insert提交之前自動生成一個自增主鍵。
通過mysql函數獲取到剛插入記錄的自增主鍵:
- LAST_INSERT_ID()
- 是insert之後調用此函數。
將插入數據的主鍵返回,返回到user對象中
- SELECT LAST_INSERT_ID():得到剛insert進去記錄的主鍵值,只適用與自增主鍵
- keyProperty:將查詢到主鍵值設置到parameterType指定的對象的哪個屬性
- order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來說它的執行順序
- resultType:指定SELECT LAST_INSERT_ID()的結果類型
修改insertUser定義:
<!-- 添加用戶
parameterType:指定輸入 參數類型是pojo(包括 用戶信息)
#{}中指定pojo的屬性名,接收到pojo對象的屬性值,mybatis通過OGNL獲取對象的屬性值
-->
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<!--
將插入數據的主鍵返回,返回到user對象中
SELECT LAST_INSERT_ID():得到剛insert進去記錄的主鍵值,只適用與自增主鍵
keyProperty:將查詢到主鍵值設置到parameterType指定的對象的哪個屬性
order:SELECT LAST_INSERT_ID()執行順序,相對於insert語句來說它的執行順序
resultType:指定SELECT LAST_INSERT_ID()的結果類型
-->
<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user ( username,birthday,sex,address) value(#{username},#{birthday},#{sex},#{address})
</insert>
- 非自增主鍵返回(使用uuid())
使用mysql的uuid()函數生成主鍵,需要修改表中id字段類型爲string,長度設置成35位。
執行思路:
- 先通過uuid()查詢到主鍵,將主鍵輸入 到sql語句中。
- 執行uuid()語句順序相對於insert語句之前執行。
<!--
使用mysql的uuid()生成主鍵
執行過程:
首先通過uuid()得到主鍵,將主鍵設置到user對象的id屬性中
其次在insert執行時,從user對象中取出id屬性值
-->
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT uuid()
</selectKey>
insert into user ( id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
- 通過oracle的序列生成主鍵:
<selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String">
SELECT 序列名.nextval()
</selectKey>
insert into user ( id,username,birthday,sex,address) value(#{id},#{username},#{birthday},#{sex},#{address})
刪除用戶
- 映射文件
<!-- 刪除 用戶
根據id刪除用戶,需要輸入 id值
-->
<delete id="deleteUser" parameterType="java.lang.Integer">
delete from user where id=#{id}
</delete>
- 代碼
// 根據id刪除 用戶信息
@Test
public void deleteUserTest() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通過工廠得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 傳入id刪除 用戶
sqlSession.delete("test.deleteUser", 39);
// 提交事務
sqlSession.commit();
// 關閉會話
sqlSession.close();
}
更新用戶
- 映射文件
<!-- 根據id更新用戶
分析:
需要傳入用戶的id
需要傳入用戶的更新信息
parameterType指定user對象,包括 id和更新信息,注意:id必須存在
#{id}:從輸入 user對象中獲取id屬性值
-->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
where id=#{id}
</update>
- 代碼
// 更新用戶信息
@Test
public void updateUserTest() throws IOException {
// mybatis配置文件
String resource = "SqlMapConfig.xml";
// 得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
// 創建會話工廠,傳入mybatis的配置文件信息
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 通過工廠得到SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 更新用戶信息
User user = new User();
//必須設置id
user.setId(41);
user.setUsername("王大軍");
user.setBirthday(new Date());
user.setSex("2");
user.setAddress("河南鄭州");
sqlSession.update("test.updateUser", user);
// 提交事務
sqlSession.commit();
// 關閉會話
sqlSession.close();
}
入門程序總結
- parameterType
- 在映射文件中通過parameterType指定輸入 參數的類型。
resultType
- 在映射文件中通過resultType指定輸出結果的類型。
#{}
和${}
#{}
表示一個佔位符號
,#{}
接收輸入參數,類型可以是簡單類型,pojo、hashmap。
- 如果接收簡單類型,
#{}
中可以寫成value或其它名稱。
- 如果接收簡單類型,
#{}
接收pojo對象值,通過OGNL讀取對象中的屬性值,通過屬性.屬性.屬性…的方式獲取對象屬性值。${}
表示一個拼接符號
,會引用sql注入,所以不建議使用${}
。${}
接收輸入參數,類型可以是簡單類型,pojo、hashmap。- 如果接收簡單類型,
${}
中只能寫成value。 ${}
接收pojo對象值,通過OGNL讀取對象中的屬性值,通過屬性.屬性.屬性…的方式獲取對象屬性值。
mybatis和hibernate本質區別和應用場景
- hibernate:是一個標準ORM框架(對象關係映射)。入門門檻較高的,不需要程序寫sql,sql語句自動生成了。對sql語句進行優化、修改比較困難的。
應用場景:
- 適用與需求變化不多的中小型項目,比如:後臺管理系統,erp、orm、oa。。
mybatis:專注是sql本身,需要程序員自己編寫sql語句,sql修改、優化比較方便。mybatis是一個不完全 的ORM框架,雖然程序員自己寫sql,mybatis 也可以實現映射(輸入映射、輸出映射)。
應用場景:
- 適用與需求變化較多的項目,比如:互聯網項目。
企業進行技術選型,以低成本 高回報作爲技術選型的原則,根據項目組的技術力量進行選擇。