Mybatis學習記錄(一)--Mybatis入門
一.傳統資料庫解決方案
對於資料庫的連線,在java中簡單的就是直接使用JDBC來控制資料庫.傳統的jdbc方式按照以下幾步來操作資料庫.
1.載入驅動 2. 建立並獲取連線 3. 建立jdbc statement物件 4.設定sql語句 5.設定sql語句引數
6.執行sql並返回resultset結果 7.取出結果並釋放連線
傳統的方法存在以下幾點問題:
1. 資料庫連結建立、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用資料庫連結池可解決此問題。
2. Sql語句在程式碼中硬編碼,造成程式碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java程式碼。
3.
4. 對結果集解析存在硬編碼(查詢列名),sql變化導致解析程式碼變化,系統不易維護,如果能將資料庫記錄封裝成pojo物件解析比較方便。
那麼mybatis等框架的出現就是用來解決這些問題,解決方案就是重新對jdbc進行封裝.
二.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整體結構
1. SqlMapConfig.xml:mybatis的全域性配置檔案,配置了mybatis的執行環境等資訊。
mapper.xml檔案即sql對映檔案,檔案中配置了操作資料庫的sql語句。此檔案需要在SqlMapConfig.xml中載入。
2. SqlSessionFactry:會話工廠,用於建立會話
3. SqlSession:會話,主要來進行資料庫操作
4. Executor:mybatis底層自定義了Executor執行器介面操作資料庫,Executor介面有兩個實現,一個是基本執行器、一個是快取執行器。
5. Mapped Statement也是mybatis一個底層封裝物件,它包裝了mybatis配置資訊及sql對映資訊等。mapper.xml檔案中一個sql對應一個Mapped Statement物件,sql的id即是Mapped statement的id。
6.
7. Mapped Statement對sql執行輸出結果進行定義,包括HashMap、基本型別、pojo,Executor通過Mapped Statement在執行sql後將輸出結果對映至java物件中,輸出結果對映過程相當於jdbc程式設計中對結果的解析處理過程。
四.mybatis下載
五.mybatis入門程式
1.基本配置
首先匯入mysql的包,mybatis的包,log4j的包
為了演示入門程式效果,所以在資料庫中建立一張User表
在程式碼中寫上model類
public class User {
private int id;
private String username;
private String password;
private String nickname;
private int status;
//省略get和set方法
@Override
public String toString() {
return "id:"+id+"username:"+username+"password:"+password+"nickname:"+nickname;
}
}
2.配置log4j
使用log4j可以在除錯mybatis的過程中省去很多麻煩,還可以直觀的看到mybatis的sql語句.
首先把log4j的jar包匯入到專案中,然後建立log4j.properties檔案,按照官方文件寫入配置
# Global logging configuration
#在開發環境中要設定為DEBUG,不然不會打印出資訊
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
這樣在執行過程中mybatis就會在控制檯打出相應的日誌了.
3.配置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>
<!-- 和spring整合後 environments配置將廢除,交給spring管理-->
<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/shopdemo?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="7946521" />
</dataSource>
</environment>
</environments>
<!--配置mappeer對映-->
<mappers>
<mapper resource="mapper/User.xml"/>
</mappers>
</configuration>
4.根據id查詢使用者(精確查詢單條資料)
根據mybatis整體流程,配置完SqlMapConfig.xml之後是建立相應的model類的對映.這裡我們為User建立User.xml檔案,並寫上sql語句
<?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">
<!--名稱空間,用於隔離sql語句,後面會講另一層非常重要的作用。-->
<mapper namespace="test">
<!--根據id查詢出使用者資訊(查詢一條資料)-->
<select id="findUserById" parameterType="int" resultType="com.aust.model.User">
SELECT * FROM user WHERE id=#{id}
</select>
</mapper>
- id:標識當前sql,mybatis把sql語句封裝到MappedStatement中,所以可以稱為Statement的唯一標識
- parameterType:指定輸入引數型別,mybatis通過ognl從輸入物件中獲取引數值拼接在sql中。
- resultType:指定輸出結果型別,mybatis將sql查詢結果的一行記錄資料對映為resultType指定型別的物件。select下指定將單條資料對映成java物件
接下來在SqlMapConfig.xml中配置mapper對映,再其裡面加入下面配置
<!--配置mappeer對映-->
<mappers>
<mapper resource="mapper/User.xml"/>
</mappers>
然後寫junit測試
//測試取出單個
@Test
public void findUserTest(){
//用於載入mybatis配置檔案的輸入流
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
System.out.println("載入mybatis配置檔案出錯");
e.printStackTrace();
}
//獲取會話工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//獲取會話
SqlSession session = factory.openSession();
//執行查詢單條記錄,返回的型別就是resultType
//第一個引數命名規則為: 名稱空間+Statement id
User u = session.selectOne("test.findUserById",1);
//查詢完要釋放會話
session.close();
System.out.println(u.toString());
}
結果
5.根據姓名查詢使用者(模糊查詢多條資料)
和上面一樣的操作,先寫sql語句
<!--根據名稱進行模糊查詢(查詢出多條資料)-->
<select id="findUserByName" parameterType="java.lang.String" resultType="com.aust.model.User">
<!--markdown顯示不出來美元符號,,,-->
SELECT * from user WHERE nickname LIKE '%美元符號{value}%'
</select>
這裡和上面區別大的是使用了${}來配置,不過本質都是ognl來獲取的
- #{}表示一個佔位符號,通過#{}可以實現preparedStatement向佔位符中設定值,自動進行java型別和jdbc型別轉換,#{}可以有效防止sql注入。 #{}可以接收簡單型別值或pojo屬性值。 如果parameterType傳輸單個簡單型別值,#{}括號中可以是value或其它名稱。
- 美元符號{}表示拼接sql串,通過美元符號{}可以將parameterType傳入的內容拼接在sql中且不進行jdbc型別轉換, 所以可能引起sql注入,美元符號{}可以接收簡單型別值或pojo屬性值,如果parameterType傳輸單個簡單型別值,美元符號{}括號中只能是value。
寫junit測試類
//測試取出多個
@Test
public void findUserByNameTest(){
//用於載入mybatis配置檔案的輸入流
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
System.out.println("載入mybatis配置檔案出錯");
e.printStackTrace();
}
//獲取會話工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//獲取會話
SqlSession session = factory.openSession();
//查詢多條資料返回值為list集合,list裡面的型別是resultType配置的型別
List<User> users = session.selectList("test.findUserByName","張");
session.close();
System.out.println(users);
}
測試結果
6.插入一個使用者,並返回自增主鍵
自增主鍵的返回,可以使用mysql的SELECT last_insert_id()函式,不過該sql要在insert語句之後才能執行
<!--插入一個使用者-->
<insert id="insertUser" parameterType="com.aust.model.User">
<selectKey keyProperty="id" resultType="java.lang.Integer" order="AFTER" >
SELECT last_insert_id()
</selectKey>
INSERT INTO user(username,password,nickname,status) VALUE (#{username},#{password},#{nickname},#{status})
</insert>
- keyProperty:返回的主鍵儲存在pojo中的哪個屬性
- order:selectKey的執行順序,是相對與insert語句來說,由於mysql的自增原理執行完insert語句之後才將主鍵生成,所以這裡selectKey的執行順序為after
- resultType:返回的主鍵是什麼型別
- LAST_INSERT_ID():是mysql的函式,返回auto_increment自增列新記錄id值。
junit測試
//測試插入資料
@Test
public void insertUserTest(){
//用於載入mybatis配置檔案的輸入流
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
System.out.println("載入mybatis配置檔案出錯");
e.printStackTrace();
}
//獲取會話工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//獲取會話
SqlSession session = factory.openSession();
User u = new User();
u.setUsername("niuli");
u.setPassword("123456");
u.setNickname("牛李");
u.setStatus(2);
//返回的是受影響的行數
int a = session.insert("test.insertUser",u);
System.out.println(a);
//提交事務
session.commit();
session.close();
//獲取主鍵
System.out.println("u id"+u.getId());
}
測試結果
7.mybatis對於非自增主鍵
非自增主鍵和自增主鍵差不多,只是獲取的函式和方式不同
需要增加通過select uuid()得到uuid值
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
<selectKey resultType="java.lang.String" order="BEFORE"
keyProperty="id">
select uuid()
</selectKey>
insert into user(id,username,birthday,sex,address)
values(#{id},#{username},#{birthday},#{sex},#{address})
</insert>
注意這裡使用的order是“BEFORE”
8.更新和刪除使用者
更新和刪除操作差不多,就一起寫了
<!--刪除一個使用者-->
<delete id="deleteUser" parameterType="int">
DELETE FROM user WHERE id =#{id}
</delete>
<!--更新使用者-->
<update id="updateUser" parameterType="com.aust.model.User">
UPDATE user SET username=#{username},password=#{password},nickname=#{nickname} WHERE id = #{id}
</update>
junit測試
//測試刪除使用者
@Test
public void deleteUserTest(){
//用於載入mybatis配置檔案的輸入流
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
System.out.println("載入mybatis配置檔案出錯");
e.printStackTrace();
}
//獲取會話工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//獲取會話
SqlSession session = factory.openSession();
//返回的是受影響的行數
int a = session.delete("test.deleteUser",10);
System.out.println(a);
//提交事務
session.commit();
session.close();
}
//測試更新使用者
@Test
public void updateUserTest(){
//用於載入mybatis配置檔案的輸入流
InputStream is = null;
try {
is = Resources.getResourceAsStream("SqlMapperConfig.xml");
} catch (IOException e) {
System.out.println("載入mybatis配置檔案出錯");
e.printStackTrace();
}
//獲取會話工廠
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//獲取會話
SqlSession session = factory.openSession();
User u = new User();
u.setId(1);
u.setUsername("niuli");
u.setPassword("123456");
u.setNickname("牛李");
u.setStatus(2);
//返回的是受影響的行數
int a = session.update("test.updateUser",u);
System.out.println(a);
//提交事務
session.commit();
session.close();
//獲取主鍵
}
一個mybatis的基本入門程式結束,專案結構如下
專案示例: