框架 day65 Mybatis入門(基礎知識:框架原理,入門[curd],開發dao層,全局與映射配置)
來源:程序員人生 發布時間:2016-08-01 17:50:14 閱讀次數:2430次
Mybatis
基礎知識(1)
第1天:基礎知識(重點)
mybatis介紹
mybatis框架原理(掌握)
mybaits入門程序(掌握)
用戶信息進行增、刪、改、查
mybatis開發dao層方法:(掌握)
原始dao開發方法(dao接口和實現類需要程序員編寫)
mapper代理開發方法(程序員只需要編寫接口)
SqlMapConfig.xml(mybatis全局配置文件)(掌握)
mybatis輸入映照(掌握)
mybatis輸出映照(掌握)
mybatis動態sql(掌握)
1 Mybatis是甚么?
MyBatis 本是apache的1個開源項目iBatis,
2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis,實質上Mybatis對ibatis進行1些改進。
MyBatis是1個優秀的持久層框架,它對jdbc的操作數據庫的進程進行封裝,使開發者只需要關注 SQL本身,而不需要花費精力去處理例如注冊驅動、創建connection、創建statement、手動設置參數、結果集檢索等jdbc復雜的進程代碼。
Mybatis通過xml或注解的方式將要履行的各種statement(statement、preparedStatemnt、CallableStatement)配置起來,并通過java對象和statement中的sql進行映照生成終究
履行的sql語句,最后由mybatis框架履行sql并將結果映照成java對象并返回。
2 分析原生態jdbc程序中存在的問題
2.1 原生態Jdbc程序代碼
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//1、加載
數據庫驅動
Class.forName("com.mysql.jdbc.Driver");
//2、通過驅動管理類獲得
數據庫鏈接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf⑻", "root", "root");
//3、定義sql語句 ?表示占位符
String sql = "select * from user where username = ?";
//4、獲得預處理statement
preparedStatement = connection.prepareStatement(sql);
//5、設置參數,第1個參數為sql語句中參數的序號(從1開始),第2個參數為設置的參數值
preparedStatement.setString(1, "王5");
//6、向
數據庫發出sql履行查詢,查詢出結果集
resultSet = preparedStatement.executeQuery();
//7、遍歷查詢結果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+" "+resultSet.getString("username"));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//8、釋放資源
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(preparedStatement!=null){
try {
preparedStatement.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
2.2 Jdbc問題總結
1數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。
解決:在SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。
2Sql語句寫在代碼中造成代碼不容易保護,實際利用sql變化的可能較大,sql變動需要改變java代碼。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。
3向sql語句傳參數麻煩,由于sql語句的where條件不1定,可能多也可能少,占位符需要和參數逐一對應。
解決:Mybatis自動將java對象映照至sql語句,通過statement中的parameterType定義輸入參數的類型。
4對結果集解析麻煩,sql變化致使解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。
解決:Mybatis自動將sql履行結果映照至java對象,通過statement中的resultType定義輸出結果的類型。
3 Mybatis框架原理
3.1 框架圖
3.2 分析結論
1、 mybatis配置文件,包括Mybatis全局配置文件和Mybatis映照文件,其中全局配置文件配置了數據源、事務等信息;映照文件配置了SQL履行相干的 信息。
2、 mybatis通過讀取配置文件信息(全局配置文件和映照文件),構造出SqlSessionFactory,即會話工廠。
3、 通過SqlSessionFactory,可以創建SqlSession即會話。Mybatis是通過SqlSession來操作數據庫的。
4、 SqlSession本身不能直接操作數據庫,它是通過底層的Executor履行器接口來操作數據庫的。Executor接口有兩個實現類,1個是普通履行器,1個是緩存履行器(默許)。
5、 Executor履行器要處理的SQL信息是封裝到1個底層對象MappedStatement中。該對象包括:SQL語句、輸入參數映照信息、輸出結果集映照信息。其中輸入參數和輸出結果的映照類型包括java的簡單類型、HashMap集合對象、POJO對象類型。
4 Mybatis入門程序
Mybatis課程的所有代碼程序將通過1個定單商品案例來進行講授。
4.1 需求
對用戶信息的增刪改查操作。
1、 根據用戶ID來查詢用戶信息;
2、 根據用戶名稱來模糊查詢用戶信息列表;
3、 添加用戶;
4、 刪除用戶;
5、 修改用戶。
4.2 環境準備
l Jdk環境:jdk1.7.0_72
l Ide環境:eclipse indigo
l 數據庫環境:MySQL 5.1
l Mybatis:3.2.7
4.2.1 數據庫初始化
4.2.1.1 數據庫腳本
sql_table.sql:創建表語句、存儲進程、觸發器
sql_data.sql:系統初始化數據
4.2.1.2 數據庫表
定單商品案例的數據庫腳本中,總共包括4張表,其中入門程序只使用user表:
4.2.2 下載mybatis
mybaits的代碼,由github.com管理
下載地址:https://github.com/mybatis/mybatis⑶/releases
4.3 工程搭建(3步)
4.3.1 第1步:創建java工程
用eclipse創建1個java工程,jdk使用1.7.0_72。
4.3.2 第2步:加入jar包
加入以下4部份jar包,其中junit的jar包,是非必須的。
l Mybatis核心包
l Mybatis依賴包
l MySQL驅動包
l Junit單元測試包(單元測試需要的包)
4.3.3 第3步:添加log4j.properties文件
Mybatis使用的日志包是log4j的,所以需要添加log4j.properties。
在classpath下創建log4j.properties以下:
文件內容可以從mybatis⑶.2.7.pdf中拷貝
# 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
日志級別在開發階段設置成DEBUG,在生產階段設置成INFO或ERROR。
4.4 編程步驟
1、 創建PO類,根據需求創建;
2、 創建全局配置文件SqlMapConfig.xml;
3、 編寫映照文件;
4、 加載映照文件,在SqlMapConfig.xml中進行加載;
5、 編寫測試程序,即編寫Java代碼,連接并操作數據庫。
思路:
a) 讀取配置文件;
b) 通過SqlSessionFactoryBuilder創建SqlSessionFactory會話工廠。
c) 通過SqlSessionFactory創建SqlSession。
d) 調用SqlSession的操作數據庫方法。
e) 關閉SqlSession。
4.5 代碼開發
4.5.1 創建PO類
創建的po類的屬性要和數據庫中表的列名1致(如果表中的列名是帶有下劃線,那末po類中對應的的屬性名要采取駝峰式命名)
User.java類以下:
Public class User {
private int id;
private String username;// 用戶姓名
private String sex;// 性別
private Date birthday;// 生日
private String address;// 地址
get/set……
4.5.2 創建SqlMapConfig.xml配置文件
在classpath下,創建SqlMapConfig.xml文件
SqlMapConfig.xml(文件頭可以從mybatis⑶.2.7.pdf文檔的2.1.2小節中拷貝):
4.5.3 需求開發
在classpath下,創建sqlmap文件夾。在sqlmap目錄下,創建User.xml映照文件。
Mybatis的映照文件頭(可以從mybatis⑶.2.7.pdf文件中拷貝):
4.5.3.1 根據用戶ID來查詢用戶信息
4.5.3.1.1 編寫映照文件
在User.xml中添加以下代碼:
SELECT * FROM USER WHERE id = #{id}
4.5.3.1.2 加載映照文件
在SqlMapConfig.xml中,添加以下代碼:
4.5.3.1.3 編寫測試程序
public class MybatisFirst {
@Test
public void findUserByIdTest() throws Exception{
//1、讀取配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
//2、根據配置文件創建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3、SqlSessionFactory創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4、SqlSession履行statement,并返回映照結果
//第1個參數:statement的id,建議:namespace.statementId(確保唯1)
//第2個參數:入參的值,它的類型要和映照文件中對應的statement的入參類型1致
User user = sqlSession.selectOne("findUserById", 1);
//打印輸出結果集
System.out.println(user);
//5、關閉SqlSession
sqlSession.close();
}
}
4.5.3.2 根據用戶名稱來模糊查詢用戶信息列表
4.5.3.2.1 編寫映照文件
在User.xml中,添加以下內容:
SELECT * FROM USER WHERE username LIKE '%${value}%'
4.5.3.2.2 加載映照文件
已配置,此處無需再次配置。
4.5.3.2.3 編寫測試程序
@Test
public void findUsersByNameTest() throws Exception {
// 1、讀取配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2、根據配置文件創建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3、SqlSessionFactory創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4、SqlSession履行statement,并返回映照結果
// 第1個參數:statement的id,建議:namespace.statementId(確保唯1)
// 第2個參數:入參的值,它的類型要和映照文件中對應的statement的入參類型1致
Listusers = sqlSession.selectList("test.findUsersByName", "小明");
// 打印輸出結果集
System.out.println(users);
// 5、關閉SqlSession
sqlSession.close();
}
4.5.3.3 添加用戶
4.5.3.3.1 編寫映照文件
INSERT INTO USER(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address})
4.5.3.3.2 加載映照文件
已配置,此處無需再次配置。
4.5.3.3.3 編寫測試程序
注意:增刪改操作要對SqlSession履行commit操作。
@Test
public void insertUserTest() throws Exception {
// 1、讀取配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2、根據配置文件創建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 3、SqlSessionFactory創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4、SqlSession履行statement,并返回映照結果
//構建user參數,沒有賦值的屬性采取默許值
User user = new User();
user.setUsername("東哥1");
user.setAddress("清河寶盛西里");
// 第1個參數:statement的id,建議:namespace.statementId(確保唯1)
// 第2個參數:入參的值,它的類型要和映照文件中對應的statement的入參類型1致
sqlSession.insert("insertUser", user);
//切記:增刪改操作時,要履行commit操作
sqlSession.commit();
// 5、關閉SqlSession
sqlSession.close();
}
4.5.3.3.4 自增主鍵返回
思路:
? MySQL自增主鍵,是指在insert之前MySQL會自動生成1個自增的主鍵。
? 我們可以通過MySQL的函數獲得到剛插入的自增主鍵:
LAST_INSERT_ID()
? 這個函數是在insert語句以后去調用。
修改映照文件:
SELECT LAST_INSERT_ID()INSERT INTO USER(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address})
4.5.3.3.5 非自增主鍵返回之UUID
注意:使用mysql的uuid()函數生成主鍵,需要修改表中id字段類型為string,長度設置成35位。
SELECT UUID()INSERT INTO USER(id,username,sex,birthday,address) VALUES (#{id},#{username},#{sex},#{birthday},#{address})
4.5.3.3.6 非自增主鍵返回之序列(oracle)返回(了解)
SELECT user_seq.nextval() FROM dualINSERT INTO USER(id,username,sex,birthday,address) VALUES (#{id},#{username},#{sex},#{birthday},#{address})
4.5.3.4 刪除用戶
4.5.3.4.1 編寫映照文件
DELETE FROM USER WHERE id= #{id}
4.5.3.4.2 加載映照文件
已配置,此處無需再次配置。
4.5.3.4.3 編寫測試程序
略
4.5.3.5 修改用戶
4.5.3.5.1 編寫映照文件
UPDATE USER SET username LIKE ‘%${username}%’,sex=#{sex} WHERE id=#{id}
4.5.3.5.2 加載映照文件
已配置,此處無需再次配置。
4.5.3.5.3 編寫測試程序
@Test
public void updateUserTest() throws Exception{
// 1、讀取配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2、根據配置文件創建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 3、SqlSessionFactory創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 4、SqlSession履行statement,并返回映照結果
//構建user參數,沒有賦值的屬性采取默許值
User user = new User();
user.setId(28);
user.setUsername("東哥11");
user.setAddress("清河寶盛西里");
// 第1個參數:statement的id,建議:namespace.statementId(確保唯1)
// 第2個參數:入參的值,它的類型要和映照文件中對應的statement的入參類型1致
sqlSession.update("test.updateUser", user);
//切記:增刪改操作時,要履行commit操作
sqlSession.commit();
// 5、關閉SqlSession
sqlSession.close();
}
4.6 小結
4.6.1 parameterType和resultType
parameterType指定輸入參數的java類型,可以填寫別名或Java類的全限定名。
resultType指定輸出結果的java類型,可以填寫別名或Java類的全限定名。
4.6.2 #{}和${}
#{}:相當于預處理中的占位符?。
#{}里面的參數表示接收java輸入參數的名稱。
#{}可以接受HashMap、簡單類型、POJO類型的參數。
當接受簡單類型的參數時,#{}里面可以是value,也能夠是其他。
#{}可以避免SQL注入。
${}:相當于拼接SQL串,對傳入的值不做任何解釋的原樣輸出。
${}會引發SQL注入,所以要謹慎使用。
${}可以接受HashMap、簡單類型、POJO類型的參數。
當接受簡單類型的參數時,${}里面只能是value。
4.6.3 selectOne和selectList
selectOne:只能查詢0或1條記錄,大于1條記錄的話,會報錯:
selectList:可以查詢0或N條記錄
4.7 mybatis與hibernate的區分及各自利用場景
Mybatis技術特點:
通過直接編寫SQL語句,可以直接對SQL進行性能的優化;
學習門坎低,學習本錢低。只要有SQL基礎,就能夠學習mybatis,而且很容易上手;
由于直接編寫SQL語句,所以靈活多變,代碼保護性更好。
不能支持數據庫無關性,即數據庫產生變更,要寫多套代碼進行支持,移植性不好。
需要編寫結果映照。
Hibernate技術特點:
標準的orm框架,程序員不需要編寫SQL語句。
具有良好的數據庫無關性,即數據庫產生變化的話,代碼無需再次編寫。
學習門坎高,需要對數據關系模型有良好的基礎,而且在設置OR映照的時候,需要斟酌好性能和對象模型的權衡。
程序員不能自主的去進行SQL性能優化。
Mybatis利用場景:
需求多變的互聯網項目,例如電商項目。
Hibernate利用場景:
需求明確、業務固定的項目,例如OA項目、ERP項目等。
5 Mybatis開發dao
Mybatis在項目中主要使用的地方就是開發dao(數據訪問層),所以下面講授1下mybatis開發dao的方法。有兩種方式:原始dao開發方式、mapper代理開發方式(推薦)。
5.1 需求
1、 根據用戶ID來查詢用戶信息;
2、 根據用戶名稱來模糊查詢用戶信息列表;
3、 添加用戶;
5.2 原始dao開發方式
5.2.1 思路
程序員需要寫dao接口和dao實現類。
5.2.2 編程步驟
1、 根據需求創建po類
2、 編寫全局配置文件
3、 根據需求編寫映照文件
4、 加載映照文件
5、 編寫dao接口
6、 編寫dao實現類
7、 編寫測試代碼
5.2.3 程序編寫
步驟中的1、2、3、4都在入門程序中進行了編寫,此處不需要重新編寫。
5.2.3.1 開發dao接口
public interface UserDao {
//根據用戶ID來查詢用戶信息
public User findUserById(int id);
//根據用戶名稱來模糊查詢用戶信息列表
public ListfindUsersByName(String username);
//添加用戶
public void insertUser(User user);
}
5.2.3.2 開發dao實現類
5.2.3.2.1 SqlSession使用范圍
通過入門程序,大家可以看出,在測試代碼中,有大量的重復代碼。所以我們第1反應就是想給它抽取出共性的部份,但是SqlSession、SqlSessionFactory、SqlSessionFactoryBuilder有著各自的生命周期,由于這些生命周期的不同,抽取時要有針對性的處理。
所以在抽取之前,我們先來了解并總結下它們3個的生命周期。
5.2.3.2.1.1 SqlSessionFactoryBuilder
它的作用只是通過配置文件創建SqlSessionFactory,所以只要創建出SqlSessionFactory,它就能夠燒毀了。所以說,它的生命周期是在方法以內。
5.2.3.2.1.2 SqlSessionFactory
它的作用是創建SqlSession的工廠,工廠1旦創建,除非利用停掉,不要燒毀。
所以說它的生命周期是在利用范圍內。這里可以通過單例模式來管理它。
在mybatis整合spring以后,最好的處理方式是把SqlSessionFactory交由spring來做單例管理。
5.2.3.2.1.3 SqlSession
SqlSession是1個面向用戶(程序員)的接口,它的默許實現是DefaultSqlSession。
Mybatis是通過SqlSession來操作數據庫的。SqlSession中不但包括要處理的SQL信息,還包括1些數據信息,所以說它是線程不安全的,因此它最好的生命周期范圍是在方法體以內。
5.2.3.2.2 Dao實現類代碼
需要向dao實現類中注入SqlSessionFactory,在方法體內通過SqlSessionFactory創建SqlSession
要注意SqlSession和SqlSessionFactory的生命周期。
public class UserDaoImpl implements UserDao {
//注入SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
//使用構造方法來初始化SqlSessionFactory
public UserDaoImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory = sqlSessionFactory;
}
@Override
public User findUserById(int id) {
//通過工廠,在方法內部獲得SqlSession,這樣就能夠避免線程不安全
SqlSession sqlSession = sqlSessionFactory.openSession();
//返回結果集
return sqlSession.selectOne("test.findUserById", id);
}
@Override
public ListfindUsersByName(String username) {
//通過工廠,在方法內部獲得SqlSession,這樣就能夠避免線程不安全
SqlSession sqlSession = sqlSessionFactory.openSession();
return sqlSession.selectList("test.findUsersByName", username);
}
@Override
public void insertUser(User user) {
//通過工廠,在方法內部獲得SqlSession,這樣就能夠避免線程不安全
SqlSession sqlSession = sqlSessionFactory.openSession();
sqlSession.insert("test.insertUser", user);
}
}
5.2.3.3 編寫測試代碼
略
5.2.4 問題總結
原始dao開發存在1些問題:
? 存在1定量的模板代碼。比如:通過SqlSessionFactory創建SqlSession;調用SqlSession的方法操作數據庫;關閉Sqlsession。
? 存在1些硬編碼。調用SqlSession的方法操作數據庫時,需要指定statement的id,這里存在了硬編碼。
5.3 Mapper代理開發方式(推薦)
Mapper代理的開發方式,程序員只需要編寫mapper接口(相當于dao接口)便可。Mybatis會自動的為mapper接口生成動態代理實現類。
不過要實現mapper代理的開發方式,需要遵守1些開發規范。
5.3.1 開發規范
1、 mapper接口的全限定名要和mapper映照文件的namespace的值相同。
2、 mapper接口的方法名稱要和mapper映照文件中的statement的id相同;
3、 mapper接口的方法參數只能有1個,且類型要和mapper映照文件中statement的parameterType的值保持1致。
4、 mapper接口的返回值類型要和mapper映照文件中statement的resultType值或resultMap中的type值保持1致;
通過規范式的開發mapper接口,可以解決原始dao開發當中存在的問題:
1、 模板代碼已去掉;
2、 剩下去不掉的操作數據庫的代碼,其實就是1行代碼。這行代碼中硬編碼的部份,通過第1和第2個規范就能夠解決。
5.3.2 編程步驟
1、 根據需求創建po類
2、 編寫全局配置文件
3、 根據需求編寫映照文件
4、 加載映照文件
5、 編寫mapper接口
6、 編寫測試代碼
5.3.3 程序編寫
步驟中的1、2都在入門程序中進行了編寫,此處不需要重新編寫。
5.3.3.1 編寫mapper映照文件
重新定義mapper映照文件UserMapper.xml(內容同Users.xml,除namespace的值),放到新創建的目錄mapper下。
SELECT * FROM USER WHERE id = #{id}
SELECT * FROM USER WHERE username LIKE '%${value}%'
SELECT LAST_INSERT_ID()INSERT INTO USER(username,sex,birthday,address) VALUES (#{username},#{sex},#{birthday},#{address})
5.3.3.2 加載mapper映照文件
5.3.3.3 編寫mapper接口
內容同UserDao接口1樣:
public interface UserMapper {
//根據用戶ID來查詢用戶信息
public User findUserById(int id);
//根據用戶名稱來模糊查詢用戶信息列表
public ListfindUsersByName(String username);
//添加用戶
public void insertUser(User user);
}
5.3.3.4 編寫測試代碼
public class UserMapperTest {
// 聲明全局的SqlSessionFactory
private SqlSessionFactory sqlSessionFactory;
@Before
public void setUp() throws Exception {
// 1、讀取配置文件
String resource = "SqlMapConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 2、根據配置文件創建SqlSessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
@Test
public void testFindUserById() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 調用mapper對象的方法
User user = userMapper.findUserById(1);
System.out.println(user);
// 關閉SqlSession
sqlSession.close();
}
@Test
public void testFindUsersByName() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 調用mapper對象的方法
Listlist = userMapper.findUsersByName("小明");
System.out.println(list);
// 關閉SqlSession
sqlSession.close();
}
@Test
public void testInsertUser() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//構造User對象
User user = new User();
user.setUsername("東哥4");
user.setAddress("清河寶盛西里4");
// 調用mapper對象的方法
userMapper.insertUser(user);
System.out.println(user.getId());
//履行SqlSession的commit操作
sqlSession.commit();
// 關閉SqlSession
sqlSession.close();
}
}
6 Mybatis全局配置文件
SqlMapConfig.xml是mybatis的全局配置文件,它的名稱可以是任意命名的。
6.1 全部配置內容
SqlMapConfig.xml的配置內容溫柔序以下(順序不能亂):
Properties(屬性)
Settings(全局參數設置)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環境信息集合)
environment(單個環境信息)
transactionManager(事物)
dataSource(數據源)
mappers(映照器)
6.2 經常使用配置詳解
6.2.1 Properties
SqlMapConfig.xml文件中可以援用java屬性文件中的配置信息
db.properties配置信息以下:
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
db.username=root
db.password=root
SqlMapConfig.xml使用properties標簽后,以下所示:
使用${},可以援用已加載的java配置文件中的信息。
注意:mybatis將依照下面的順序加載屬性:
* Properties標簽體內定義的屬性首先被讀取
* Properties援用的屬性會被讀取,如果發現上面已有同名的屬性了,那后面會覆蓋前面的值
* parameterType接收的值會最后被讀取,如果發現上面已有同名的屬性了,那后面會覆蓋前面的值
所以說,mybatis讀取屬性的順序由高到低分別是:parameterType接收的屬性值、properties援用的屬性、properties標簽內定義的屬性。
6.2.2 Settings
mybatis全局配置參數,全局參數將會影響mybatis的運行行動。
6.2.3 typeAliases
別名是使用是為了在映照文件中,更方便的去指定入參和結果集的類型,不再用寫很長的1段全限定名。
6.2.3.1 mybatis支持的別名
6.2.3.2 自定義別名
SqlMapConfig.xml配置信息以下:
6.2.4 mappers
映照器的配置有4種方式
6.2.4.1
使用相對類路徑的資源
如:
6.2.4.2
使用完全限定路徑
如:
6.2.4.3
使用mapper接口的全限定名
如:
注意:此種方法要求mapper接口和mapper映照文件要名稱相同,且放到同1個目錄下;
6.2.4.4(推薦)
注冊指定包下的所有映照文件
如:
注意:此種方法要求mapper接口和mapper映照文件要名稱相同,且放到同1個目錄下;
7 Mybatis映照文件(核心)
7.1 輸入映照
7.1.1 ParameterType
指定輸入參數的java類型,可使用別名或類的全限定名。它可以接收簡單類型、POJO、HashMap。
7.1.1.1 傳遞簡單類型
參考入門需求:根據用戶ID查詢用戶信息。
7.1.1.2 傳遞POJO對象
參考入門需求:添加用戶。
7.1.1.3 傳遞POJO包裝對象
開發中通過pojo傳遞查詢條件 ,查詢條件是綜合的查詢條件,不但包括用戶查詢條件還包括其它的查詢條件(比如將用戶購買商品信息也作為查詢條件),這時候可使用包裝對象傳遞輸入參數。
7.1.1.3.1 需求
綜合查詢用戶信息,需要傳入查詢條件復雜,比如(用戶信息、定單信息、商品信息)。
7.1.1.3.2 定義包裝對象
1般User.java類要和數據表表字段1致,最好不要在這里面添加其他字段,第2天學習mybatis的逆向工程時,會根據表結構,生成po類,如果在po類中擴大字段,此時會被覆蓋掉。
所以針對要擴大的po類,我們需要創建1個擴大類,來繼承它。
定義POJO包裝類:
7.1.1.3.3 編寫Mapper接口
//通過包裝類來進行復雜的用戶信息綜合查詢
public ListfindUserList(UserQueryVO userQueryVO);
7.1.1.3.4 編寫mapper映照文件
SELECT * FROM USER WHERE sex=#{userExt.sex} AND username LIKE '%${userExt.username}%'
注意:入參的類型變成UserQueryVO、結果集的類型變成UserExt,#{}里面的參數變成UserQueryVO對象中的userExt屬性的sex和username子屬性。
7.1.1.3.5 編寫測試代碼
@Test
public void findUserListTest() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//構造userQueryVO對象
UserQueryVO userQueryVO = new UserQueryVO();
// 構造UserExt對象
UserExt userExt = new UserExt();
userExt.setSex("1");
userExt.setUsername("小明");
userQueryVO.setUserExt(userExt);
// 調用mapper對象的方法
Listlist = userMapper.findUserList(userQueryVO);
System.out.println(list);
// 關閉SqlSession
sqlSession.close();
}
7.1.1.4 傳遞HashMap()
同傳遞POJO對象1樣,map的key相當于pojo的屬性。
7.1.1.4.1 映照文件
select * from user where id=#{id} and username like '%${username}%'
上邊紅色標注的是hashmap的key。
7.1.1.4.2 測試代碼
Public void testFindUserByHashmap()throws Exception{
//獲得session
SqlSession session = sqlSessionFactory.openSession();
//獲限mapper接口實例
UserMapper userMapper = session.getMapper(UserMapper.class);
//構造查詢條件Hashmap對象
HashMap map = new HashMap();
map.put("id", 1);
map.put("username", "管理員");
//傳遞Hashmap對象查詢用戶列表
Listlist = userMapper.findUserByHashmap(map);
//關閉session
session.close();
}
異常測試:
傳遞的map中的key和sql中解析的key不1致。
測試結果沒有報錯,只是通過key獲得值為空。
7.2 輸出映照
7.2.1 resultType
先帶著同學們看下本來resultType作為輸出結果映照時,它的特點,如何再把列名改成別名,看看是不是還能不能映照成功。
通過演示,我們得出以下結論:
7.2.1.1 使用方法
使用resultType進行結果映照時,查詢的列名和映照的pojo屬性名完全1致,該列才能映照成功。
如果查詢的列名和映照的pojo屬性名全部不1致,則不會創建pojo對象;
如果查詢的列名和映照的pojo屬性名有1個1致,就會創建pojo對象。
7.2.1.2 輸出簡單類型
當輸出結果只有1列時,可使用ResultType指定簡單類型作為輸出結果類型。
7.2.1.2.1 需求
綜合查詢用戶總數,需要傳入查詢條件復雜,比如(用戶信息、定單信息、商品信息)。
7.2.1.2.2 Mapper映照文件
SELECT count(1) FROM USER WHERE sex = #{userExt.sex} AND username LIKE '%${userExt.username}%'
7.2.1.2.3 Mapper接口
//綜合查詢用戶信息總數。學習:resultType輸出簡單類型
public int findUsersCount(QueryUserVO vo);
7.2.1.2.4 測試代碼
@Test
public void testFindUsersCount() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//構造userQueryVO對象
UserQueryVO userQueryVO = new UserQueryVO();
// 構造UserExt對象
UserExt userExt = new UserExt();
userExt.setSex("1");
userExt.setUsername("小明");
userQueryVO.setUserExt(userExt);
int count = mapper.findUsersCount(userQueryVO);
System.out.println(count); // 關閉SqlSession
sqlSession.close();
}
7.2.1.3 輸出POJO單個對象和列表
注意:輸出單個pojo對象和pojo列表(盛放pojo對象)時,mapper映照文件中的resultType的類型是1樣的,mapper接口的方法返回值不同。
7.2.1.3.1 Mapper映照文件
Mapper映照文件是同1個
SELECT * FROM USER WHERE username LIKE '%${value}%'
7.2.1.3.2 Mapper接口
下面看下mapper接口的不同的地方
1、 輸出單個pojo對象
//根據用戶名稱來模糊查詢用戶信息
public User findUsersByName(String username);
2、 輸出pojo列表
//根據用戶名稱來模糊查詢用戶信息列表
public ListfindUsersByName(String username);
總結:一樣的mapper映照文件,返回單個對象和對象列表時,mapper接口在生成動態代理的時候,會根據返回值的類型,決定調用selectOne方法還是selectList方法。
7.2.2 resultMap
resultMap可以進行高級結果映照(1對1、1對多映照,第2天講授)。
7.2.2.1 使用方法
如果查詢出來的列名和屬性名不1致,通過定義1個resultMap將列名和pojo屬性名之間作1個映照關系。
1、 定義resultMap
2、 使用resultMap作為statement的輸出映照類型。
7.2.2.2 需求
把下面SQL的輸出結果集進行映照
SELECT id id_,username username_,sex sex_FROM USER WHERE id = 1
7.2.2.3 Mapper映照文件
定義resultMap:
定義statement:
SELECT id id_,username username_,sex sex_ FROM USER WHERE id = #{id}
7.2.2.4 Mapper接口定義
//根據ID查詢用戶信息(學習resultMap)
public User findUserByIdResultMap(int id);
定義Statement使用resultMap映照結果集時,Mapper接口定義方法的返回值類型為mapper映照文件中resultMap的type類型。
7.2.2.5 測試代碼
@Test
public void findUserByIdResultMapTest() {
// 創建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
// 通過SqlSession,獲得mapper接口的動態代理對象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 調用mapper對象的方法
User user = userMapper.findUserByIdResultMap(1);
System.out.println(user);
// 關閉SqlSession
sqlSession.close();
}
7.3 動態SQL(重點)
通過Mybatis提供的各種動態標簽實現動態拼接sql,使得mapper映照文件在編寫SQL時更加靈活,方便。經常使用動態SQL標簽有:if、where、foreach;
7.3.1 If和where
? If標簽:作為判斷入參來使用的,如果符合條件,則把if標簽體內的SQL拼接上。
注意:用if進行判斷是不是為空時,不但要判斷null,也要判斷空字符串‘’;
? Where標簽:會去掉條件中的第1個and符號。
7.3.1.1 需求
用戶信息綜合查詢列表和用戶信息綜合查詢總數這兩個statement的定義使用動態SQL。
7.3.1.2 映照文件
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈