1. 程式人生 > >Java框架_Mybatis框架_入門增刪改查

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();