Java框架_Mybatis框架_入門增刪改查
一句話介紹Mybatis:
Mybatis是一個優秀的持久層框架,它對jdbc操作資料庫的過程進行封裝,使開發不需要花費精力去處理使用原生JDBC時要進行的操作(註冊驅動、建立connection、statement等)。
一句話概括Mybatis工作機制:
Mybatis通過xml或註解配置statement(拼裝sql),並通過與java物件進行對映生成最終執行的sql語句,交由框架執行後結果對映成java物件並返回。
※一個入門的Mybatis增刪改查案例:
資料庫表結構:
測試資料:
建立的工程結構如下(eclipse):
lib中需要匯入Mybatis所需要的依賴包,並build path,而config目錄下放的是相關的配置檔案:
1.JDBC的配置檔案——jdbc.properties:
2.框架的配置檔案——mybatis.xml
框架的配置檔名稱可以隨便,在xml檔案頭只要引入mybatis框架的約束檔案路徑即可:
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
PS: 上面的mybatis-3-config.dtd即為xml格式檔案的約束檔案,引入它就規定了xml檔案所使用的標籤以及標籤之間的關係。
下面是mybatis框架配置所要用到的基本配置標籤:
1.configuration——根標籤,即所有其他的配置標籤都在包含在configuration中
2.properties——規定了所要載入讀取的指定路徑的properties檔案,比如:
<properties resource="jdbc.properties"></properties>
即代表框架需要從jdbc.propterties中讀取到資料庫連線資訊
3.environments——環境標籤,可以看出這裡的environments是複數的,即mybatis中可以配置多個環境標籤,不同環境標籤使用id屬性區別。之所以支援配置多個環境標籤,是因為有助於將SQL對映成應用於多種資料庫中,enviroments標籤下,需要配置的子標籤如下:
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.DriverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
1.environment標籤——配置單個環境,不同的環境以id區別
2.transactionManager——事務管理器標籤,type屬性可以選擇兩種型別的事務管理器:JDBC/MANAGED
JDBC事務管理機制:直接使用java.sql.Connection物件完成對事務的提交、回滾等操作
MANAGED事務管理機制:使用WEB容器來管理事務
3.dataSource——資料來源,type屬性中可以選擇3種資料來源型別:UNPOOLED/POOLED/JNDI
UNPOOLED:表示Mybatis會為每一次的資料操作都去建立一個新的連線,並關閉它,適用於小規模簡單程式上。
POOLED:Mybatis會去建立一個數據庫連線池,池中的每個連線會被用於資料庫操作,且操作完成時該連線會被返還給連線池。適用於測試開發環境。
JNDI:Mybatis從應用伺服器向配置好的資料來源獲取資料庫連線。適用於生產環境。
在dataSource標籤中,通過property子標籤來配置資料庫的連線資訊(name屬性需要與jdbc.properties中所配置的屬性對應,通過EL表示式取值)
此處我們的框架的配置資訊就寫好了,完整配置如下:
<configuration>
<!-- properties標籤代表載入指定路徑的properties檔案 -->
<properties resource="jdbc.properties"></properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.DriverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
</mappers>
</configuration>
PS:除此之外,最後我們還要有一個mapper標籤,在裡面引入物件和資料庫表的對映檔案,由於對映檔案還沒寫,這在後面再說,先來配置該對映檔案。
在配置對映檔案之前,由於mybatis是將資料庫欄位對映成物件的框架,所以我們還需要有物件實體:
該實體類包含的屬性(一對set/get)名要和資料庫表中的欄位名一一對應,但資料庫表中有的欄位,實體類中不一定要有,看實際需求,這裡就取3個欄位(id,uname,age),而資料庫表中有4個欄位(id,uname,area,age):
此處省略set/get方法
接著再開始配置對映檔案:
1.在config目錄下建立user.xml(這裡先暫時在config目錄下建立,在後面會介紹另一種便於批量引入的對映檔案的建立方式),引入mybatis對映檔案的約束頭:
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
接著是mybatis框架mapper檔案配置所要用到的基本配置標籤:
1.mapper標籤——其屬性namespace,用於對sql進行分類化管理:
<mapper namespace="model.User">
</mapper>
PS:若使用Dao開發方式,對映檔案的namespace任意命名;若使用Mapper介面代理的方式開發,namespace必須為介面的全名(一般規範為XxxDao.xml,然後namespace命名為包路徑.XxxDao)。這兩種開發方式在後面會介紹到,這裡暫時任意填寫。
然後我們在mapper標籤中拼裝要用到的sql語句:
1.通過id來進行查詢:
<select id="findUserById" parameterType="java.lang.Integer" resultType="model.User">
select * from user where id=#{id}
</select>
解釋:
首先是select——表示這是一個對映查詢語句,其中有幾個屬性:
1.id——作為識別符號,可以被用來引用這條語句,是唯一的。
2.parameterType——表明傳入這條語句的引數類的完全限定名或別名,比如根據id查詢,需要傳入的id值是一個int型別,那麼其包裝類的全限定名即為java.lang.Integer。還有需要寫別名的情況在後面會介紹到。
3.resultType——表示這條語句期望返回的型別,比如我通過id查詢,返回的結果需要用一個User實體是接收它,那麼期望型別就是model.User(全限定名稱)。
除了select外,其餘的元素為:
insert-對映插入語句
update-對映更新語句
delete-對映刪除語句
select-對映查詢語句
而對於#{}符號,其實是一個佔位符,表示mybatis框架會接收輸入的引數並賦值到sql語句當中。
這樣,一個完整的對映就完成了,將mapper檔案引入到上面配置檔案的mapper中去:
<mappers>
<!-- 單獨引入mapper檔案 -->
<mapper resource="User.xml"/>
</mappers>
進行測試,步驟如下:
@Test
public void testGetFromId() throws Exception {
//1.獲取核心配置檔案的資料
InputStream in = Resources.getResourceAsStream("mybatis.xml");
//2.獲取會話工廠(會話就是連線)
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//3.獲取會話物件(相當於jdbc當中的connection)
SqlSession session = factory.openSession();
//4.操作資料庫
int id = 2;
User user = (User)session.selectOne("model.User.findUserById",id);
System.out.println(user );
session.close();
}
上述的測試程式碼中,Resources是由Mybatis提供的專門用於讀取配置檔案(即mybatis.xml),並返回一個輸入流物件,由於配置檔案在源目錄下,所以引數直接寫mybatis.xml,不能寫成config/mybatis.xml.因為config本身也是一個源目錄,所有源目錄中的檔案進行編譯後時放在同一個的目錄中的。整個連線的過程其實和JDBC的思路是一樣的。
將會話物件的獲取過程封裝成一個MybatisUtil:
public class MybatisUtil {
private static SqlSessionFactory factory;
static{
//1.獲取核心配置檔案的資料
InputStream in;
try{
in = Resources.getResourceAsStream("mybatis.xml");
//2.建立會話工廠
factory = new SqlSessionFactoryBuilder().build(in);
}catch(IOException e){
e.printStackTrace();
}
}
public static SqlSessionFactory getFactory(){
return factory;
}
}
測試程式碼:
@Test
public void testGetFromId() throws Exception {
SqlSession session = MybatisUtil.getFactory().openSession();
int id = 2;
User user = (User)session.selectOne("model.User.findUserById",id);
System.out.println(user );
session.close();
}
selectOne方法:查詢一條記錄,不能用於查詢多條記錄,否則報錯。其中第一個引數由namespace和對應的id屬性唯一決定,第二個引數表示要傳入到sql語句中的引數。
該方法的返回值是一個SqlSession,需要把它強轉成User型別
測試結果:
一個簡單的查詢案例完成。
需求2:根據使用者名稱查詢使用者資訊(包含模糊查詢like):
<select id="findUserByName" parameterType="java.lang.String" resultType="model.User">
select * from user where uname like '%${value}%'
</select>
注意:這裡使用的不是#{}而是${},${value}表示使用引數將該值替換,用於字串拼接,比如傳進來的引數為test,那麼此處拼接結果為%test%
測試:
@Test
public void testGetFromName() throws Exception {
SqlSession session = MybatisUtil.getFactory().openSession();
String name = "test";
List<User> list = session.selectList("model.User.findUserByName",name);
for (User user : list) {
System.out.println(user);
}
session.close();
}
由於查詢結果可能有多條語句,即可能有多個物件,所以要用一個List<User>來接收
selectList可以查詢一條或多條語句
測試結果:
需求3:新增使用者
<insert id="addUser" parameterType="model.User">
insert into user values(null,#{uname},null,#{age});
</insert>
插入不需要期望返回結果,插入的型別為User,對於不需要插入的值(比如主鍵策略為自增,就不需要插入主鍵)設定為null
測試:
SqlSession session = MybatisUtil.getFactory().openSession();
//mybatis框架預設非自動提交事務,如果進行增刪改操作時,需要手動提交事務
User user = new User();
user.setUname("test05");
user.setAge(22);
session.insert("model.User.addUser",user);
//提交事務
session.commit();
session.close();
注意:mybatis框架預設為非自動提交事務,所以進行增刪改操作時,需要手動提交事務
測試結果:
而在實際需求中,由於主鍵策略為自動遞增,我們有時要拿到插入物件形成記錄的主鍵,這是可以用到主鍵回填標籤:
<insert id="addUser" parameterType="model.User">
<!-- 插入的時候開業使用主鍵回填的策略,LAST_INSERT_ID() -->
<selectKey order="AFTER" keyProperty="id" resultType="int">
select LAST_INSERT_ID()
</selectKey>
insert into user values(null,#{uname},null,#{age});
</insert>
新增selectKey將主鍵返回,其中:
order:selectKey的執行順序,是相對於insert語句來說的,由於mysql的自增原理,執行完insert語句之後才將主鍵生成,所以順序為after
keyProperty:指定返回主鍵儲存在pojo中的哪個屬性
resultType:返回的主鍵型別
LAST_INSERT_ID():這是一個mysql函式,返回auto_increment自增列記錄的id值
需求4:更新使用者
<update id="updateUser" parameterType="model.User">
update user set uname=#{uname},age=#{age} where id=#{id}
</update>
測試:
SqlSession session = MybatisUtil.getFactory().openSession();
User user = new User();
user.setId(2);
user.setUname("test02");
user.setAge(18);
session.update("model.User.updateUser", user);
session.commit();
session.close();
測試結果:
需求5:根據id刪除使用者
<delete id="deleteUser" parameterType="int">
delete from user where id=#{id}
</delete>
測試:
SqlSession session = MybatisUtil.getFactory().openSession();
int id = 5;
session.update("model.User.deleteUser", id);
session.commit();
session.close();