天天看點

Java三大架構之Mybatis三大架構之Mybatis

三大架構之Mybatis

MyBatis 本是apache的一個開源項目iBatis, 2010年這個項目由apache software foundation 遷移到了google code,并且改名為MyBatis 。2013年11月遷移到Github。 MyBatis是一個優秀的持久層架構,它對jdbc的操作資料庫的過程進行封裝,使開發者隻需要關注 SQL 本身,而不需要花費精力去處理例如注冊驅動、建立connection、建立statement、手動設定參數、結果集檢索等jdbc繁雜的過程代碼。

Mybatis通過xml或注解的方式将要執行的各種statement(statement、preparedStatement、CallableStatement)配置起來,并通過java對象和statement中的sql進行映射生成最終執行的sql語句,最後由mybatis架構執行sql并将結果映射成java對象并傳回。

Mybatis架構

Java三大架構之Mybatis三大架構之Mybatis

初步接觸Mybatis

mybatis下載下傳:mybaits的代碼由github.com管理,Mybatis下載下傳位址

導入jar包 :加入mybatis核心包、依賴包、資料驅動包。junit-4.9.jar這個包是為測試友善加入的

Java三大架構之Mybatis三大架構之Mybatis

建立配置檔案 :在classpath下建立config目錄(source folder類型)log4j.properties

Java三大架構之Mybatis三大架構之Mybatis
# 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
           
mybatis預設使用log4j作為輸出日志資訊。

第一個mybatis程式

在config下建立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配置将廢除-->
	<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/db_test1?characterEncoding=utf-8" />
				<property name="username" value="root" />
				<property name="password" value="root" />
			</dataSource>
		</environment>
	</environments>
</configuration>
           

建立一個User實體類

private int id;
private String name;
private String password;
private String sex;
private int  age;
           

sql映射檔案User.xml

<?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">
<mapper namespace="test">
</mapper>
           

namespace :命名空間,用于隔離sql語句,後面會講另一層非常重要的作用。

**mybatis架構需要加載映射檔案,将User.xml添加在SqlMapConfig.xm

<mappers>
		<mapper resource="sqlmap/User.xml"/>
</mappers>
           

在User.xml配置根據id擷取使用者資訊

<select id="findUserById" parameterType="int" resultType="com.yun.mybatis.domain.User">
		select * from user where id=#{id}
	</select>
           

parameterType:

定義輸入到sql中的映射類型,#{id}表示使用preparedstatement設定占位符号并将輸入變量id傳到sql。resultType:定義結果映射類型。

測試程式(建立一個測試類)

public class MyTest {
	SqlSessionFactory ssf = null;
	@Before
	public void creatFactory(){
		InputStream input = null;
			try {
				input = Resources.getResourceAsStream("SqlMapConfig.xml");
			} catch (IOException e) {
				e.printStackTrace();
			}
		ssf = new SqlSessionFactoryBuilder().build(input);
	}
	/** 通過id查找*/
	@Test
	public void testFindUserById(){
		SqlSession session =ssf.openSession();
		//System.out.println(session);
		User user = session.selectOne("test.findUserById", 8);
		System.out.println(user);
		session.close();
	}
}
           

根據使用者名查詢

<select id="findUserByName" parameterType="string" resultType="com.yun.mybatis.domain.User">
		select * from user where name like "%${value}%"
</select>
           

parameterType:定義輸入到sql中的映射類型, v a l u e 表 示 使 用 參 數 将 {value}表示使用參數将 value表示使用參數将{value}替換,做字元串的拼接。

注意:如果是取簡單數量類型的參數,括号中的值必須為value

resultType:定義結果映射類型。

測試代碼

@Test
	public void testFindUserByName(){
		SqlSession session =ssf.openSession();
		
		List<User>  userList = session.selectList("test.findUserByName", "xiao");
		System.out.println(userList);
		session.close();
	}
           

#{}和${}

#{}表示一個占位符号,通過#{}可以實作preparedStatement向占位符中設定值,自動進行java類型和jdbc類型轉換,#{}可以有效防止sql注入。 #{}可以接收簡單類型值或pojo屬性值。 如果parameterType傳輸單個簡單類型值,#{}括号中可以是value或其它名稱。一般用在=之後。

表 示 拼 接 s q l 串 , 通 過 {}表示拼接sql串,通過 表示拼接sql串,通過{}可以将parameterType 傳入的内容拼接在sql中且不進行jdbc類型轉換, 可 以 接 收 簡 單 類 型 值 或 p o j o 屬 性 值 , 如 果 p a r a m e t e r T y p e 傳 輸 單 個 簡 單 類 型 值 , {}可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值, 可以接收簡單類型值或pojo屬性值,如果parameterType傳輸單個簡單類型值,{}括号中隻能是value。一般用在like之後。

5.6.2parameterType和resultType

parameterType:指定輸入參數類型,mybatis通過ognl從輸入對象中擷取參數值拼接在sql中。

resultType:指定輸出結果類型,mybatis将sql查詢結果的一行記錄資料映射為resultType指定類型的對象。

5.6.3selectOne和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可以查詢一條或多條記錄

添加使用者

<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
	  insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address})
	</insert>
           
@Test
	public void testInsert() {
		// 資料庫會話執行個體
		SqlSession sqlSession = null;
			// 建立資料庫會話執行個體sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 添加使用者資訊
			User user = new User();
			user.setUsername("張小明");
			user.setAddress("河南鄭州");
			user.setSex("1");
			user.setPrice(1999.9f);
			sqlSession.insert("test.insertUser", user);
			//送出事務
			sqlSession.commit();
			}
           

mysql自增主鍵傳回

  1. 通過修改sql映射檔案,可以将mysql自增主鍵傳回
<insert id="insertUser" parameterType="cn.itcast.mybatis.po.User">
		<!-- selectKey将主鍵傳回,需要再傳回 -->
		<selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">
			select LAST_INSERT_ID()
		</selectKey>
	   insert into user(username,birthday,sex,address) values(#{username},#{birthday},#{sex},#{address});
	</insert>
           
  1. 添加selectKey實作将主鍵傳回

keyProperty:傳回的主鍵存儲在pojo中的哪個屬性

order:selectKey的執行順序,是相對與insert語句來說,由于mysql的自增原理執行完insert語句之後才将主鍵生成,是以這裡selectKey的執行順序為after

resultType:傳回的主鍵是什麼類型

LAST_INSERT_ID():是mysql的函數,傳回auto_increment自增列新記錄id值。

Mysql使用 uuid實作主鍵

需要增加通過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”

删除使用者

  1. 映射檔案
<!-- 删除使用者 -->
	<delete id="deleteUserById" parameterType="int">
		delete from user where id=#{id}
	</delete>
           
  1. 5.8.2測試程式
// 根據id删除使用者
	@Test
	public void testDelete() {
		// 資料庫會話執行個體
		SqlSession sqlSession = null;
			// 建立資料庫會話執行個體sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 删除使用者
			sqlSession.delete("test.deleteUserById",18);
			// 送出事務
			sqlSession.commit();
			sqlSession.close();
	}
           

修改使用者

  1. 映射檔案
<!-- 更新使用者 -->
<update id="updateUser" parameterType="cn.itcast.mybatis.po.User">
	update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
</update>
           
  1. 測試程式
public void testUpdate() {
		// 資料庫會話執行個體
		SqlSession sqlSession = null;
			// 建立資料庫會話執行個體sqlSession
			sqlSession = sqlSessionFactory.openSession();
			// 添加使用者資訊
			User user = new User();
			user.setId(16);
			user.setUsername("張小明");
			user.setAddress("河南鄭州");
			user.setSex("1");
			user.setPrice(1999.9f);
			sqlSession.update("test.updateUser", user);
			// 送出事務
			sqlSession.commit();
			sqlSession.close();
		}
           

1、資料庫連結建立、釋放頻繁造成系統資源浪費進而影響系統性能,如果使用資料庫連結池可解決此問題。

解決:在SqlMapConfig.xml中配置資料連結池,使用連接配接池管理資料庫連結。

2、Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。

解決:将Sql語句配置在XXXXmapper.xml檔案中與java代碼分離。

3、向sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應。

解決:Mybatis自動将java對象映射至sql語句,通過statement中的parameterType定義輸入參數的類型。

4、對結果集解析麻煩,sql變化導緻解析代碼變化,且解析前需要周遊,如果能将資料庫記錄封裝成pojo對象解析比較友善。

解決:Mybatis自動将sql執行結果映射至java對象,通過statement中的resultType定義輸出結果的類型。