MyBatis(一) 概述與SQL定製、對象映射


1、MyBatis概述

一、mybatis簡介

MyBatis 是支持定製化 SQL、存儲過程以及高級映射的優秀的持久層框架。javascript

MyBatis 避免了幾乎全部的 JDBC 代碼和手動設置參數以及獲取結果集。php

MyBatis可使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對象)映射成數據庫中的記錄.html

二、mybatis歷史

原是apache的一個開源項目iBatis, 2010年6月這個項目由apache software foundation 遷移到了google code,隨着開發團隊轉投Google Code旗下,ibatis3.x正式改名爲Mybatis ,代碼於2013年11月遷移到Github(下載地址見後)。java

iBATIS一詞來源於「internet」和「abatis」的組合,是一個基於Java的持久層框架。iBATIS提供的持久層框架包括SQL Maps和Data Access Objects(DAO)mysql

三、爲何要使用mybatis

MyBatis是一個半自動化的持久化層框架。web

jdbc編程---當咱們使用jdbc持久化的時候,sql語句被硬編碼到java代碼中。這樣耦合度過高。代碼不易於維護。在實際項目開發中會常常添加sql或者修改sql,這樣咱們就只能到java代碼中去修改。sql

Hibernate和JPA數據庫

長難複雜SQL,對於Hibernate而言處理也不容易apache

內部自動生產的SQL,不容易作特殊優化。編程

基於全映射的全自動框架,javaBean存在大量字段時沒法只映射部分字段。致使數據庫性能降低。

對開發人員而言,核心sql仍是須要本身優化

sql和java編碼分開,功能邊界清晰,一個專一業務、一個專一數據。

可使用簡單的XML或註解用於配置和原始映射,將接口和Java的POJO映射成數據庫中的記錄。成爲業務代碼+底層數據庫的媒介

四、理解 SqlSession及其子父類的含義!

SqlSession的使用範圍

  • SqlSession中封裝了對數據庫的操做,如:查詢、插入、更新、刪除等。
  • SqlSession經過SqlSessionFactory建立。
  • SqlSessionFactory是經過SqlSessionFactoryBuilder進行建立。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder用於建立SqlSessionFacoty,SqlSessionFacoty一旦建立完成就不須要SqlSessionFactoryBuilder了,由於SqlSession是經過SqlSessionFactory建立的。因此能夠將SqlSessionFactoryBuilder當成一個工具類使用,最佳使用範圍是方法範圍即方法體內局部變量。

SqlSessionFactory

SqlSessionFactory是一個接口,接口中定義了openSession的不一樣重載方法,SqlSessionFactory的最佳使用範圍是整個應用運行期間,一旦建立後能夠重複使用,一般以單例模式管理SqlSessionFactory。

SqlSession

SqlSession是一個面向用戶的接口,sqlSession中定義了數據庫操做方法。
每一個線程都應該它本身的SqlSession實例。SqlSession的實例不能共享使用,它也是線程不安全的。所以最佳的範圍是請求或方法範圍。絕對不能將SqlSession實例的引用放在一個類的靜態字段或實例字段中。

2、MyBatis的Hello示例程序

一、建立一個數據庫和一個單表

drop database if exists mybatis;
create database mybatis;
use mybatis;
 ## 建立單表
####################################################################
create table t_user(
	`id` int primary key auto_increment,
	`last_name`	varchar(50),
	`sex` int
);

insert into t_user(`last_name`,`sex`) values('wsp168',1);

select * from t_user;

二、搭建mybatis開發環境

建立一個java工程

導 入 需 要 的 jar 包:

log4j-1.2.17.jar
    mybatis-3.4.1.jar
    mysql-connector-java-5.1.7-bin.jar

三、建立Pojo對象User

不調用接口方法,直接映射到xml文件中!

package com.webcode.pojo; public class User { private Integer id; private String lastName; private Integer sex; 。。。。。。。。。。 } 

四、在src目錄建立mybatis-config.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> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/webcode/pojo/UserMapper.xml"/> </mappers> </configuration>

配置文件代碼獲取方法

五、建立UserMapper.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"> <!-- namespace名稱空間 取值通常有兩種狀況: 一種狀況是:使用javaBean的全類名 二種狀況是:使用Mapper接口的全類名 --> <mapper namespace="com.webcode.pojo.User"> <!-- select標籤用來配置一個select語句 id 用來配置一個惟一的標識 resultType 是查詢完以後一條記錄對應轉換成爲的javaBean對象 #{id}是佔位符 --> <select id="selectUserById" resultType="com.webcode.pojo.User"> select id,last_name lastName,sex from t_user where id = #{id} </select> </mapper>

 

六、傳統mybatis的hello world 示例代碼

 

package com.webcode.pojo.test; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Test; import com.webcode.pojo.User; public class UserTest { @Test public void testselectUserById() throws IOException { //從配置文件讀取指定的資源,以輸入流的形式返回 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); // 經過sqlSessionFactoryBuilder建立SqlSessionFactory(從輸入流獲取鏈接條件,建立鏈接工廠) SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); System.out.println(sqlSessionFactory); //從工廠中獲取一個鏈接(當作是數據庫鏈接池便可),至關於 之前的Connection對象,每次用來都用關閉 SqlSession openSession = sqlSessionFactory.openSession(); try { /*由相對路徑映射到xml文件中的id,調動執行sql語句, 並以resultType定義的類型返回到請求端或者是客戶端*/ User user = openSession.selectOne("com.webcode.pojo.User.selectUserById",1); System.out.println(user); } catch (Exception e) { e.printStackTrace(); } finally { openSession.close();//釋放資源 } } }

 

打印結果:     User [id=1, lastName=wsp168, sex=1]

代碼流程:

關於Mybatis的配置文件提示功能:

 

關於log4j的提示:

若是不想看到,解決方案爲:

只要在應用的classpath中建立一個名稱爲log4j.properties的文件, 文件的具體內容以下:

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# 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

注意:

7.加入log4j配置

導入‘log4j-1.2.17.jar’包

在工程下的config文件夾中建立 "log4j.properties"文件

\u4E0B\uFF1A 

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# MyBatis logging configuration...
# 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 [main] - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@61832929
DEBUG [main] - Opening JDBC Connection
DEBUG [main] - Created connection 1585787493.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e853265]
DEBUG [main] - ==>  Preparing: select id,last_name lastName,sex from t_user where id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
User [id=1, lastName=wsp168, sex=1]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e853265]
DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e853265]
DEBUG [main] - Returned connection 1585787493 to pool.

流程圖解:

3、傳統方式mybatis的增,刪,改,查實現

一、UserDao:

package com.webcode.dao; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import com.webcode.pojo.User; /** * @author 鮀城小帥 * */ /** * * 注意:在建立鏈接時,底層自動對事務commit作了false定義,而沒有提交的事務會自動回滾。 * 在執行CRUD時要手動提交事務,即,在執行語句後,session.commit(); * */ public class UserDao { private SqlSessionFactory sqlSessionFactory; /* * 建立sql會話工廠方法 * */ public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } /* * 根據id查詢用戶 * */ public User queryUserById(Integer id) { SqlSession openSession = sqlSessionFactory.openSession(); try { return openSession.selectOne("com.webcode.pojo.User.selectUserById",id); } catch (Exception e) { e.printStackTrace(); } finally { openSession.close();//釋放資源 } return null; } /* * 查詢全部用戶 * */ public List<User> queryUsers(){ SqlSession session = sqlSessionFactory.openSession(); try { return session.selectList("com.webcode.pojo.User.queryUsers"); } catch (Exception e) { e.printStackTrace(); } finally { session.close();//釋放資源 } return null; } /* * 添加用戶 * */ public int saveUser(User user) { SqlSession session = sqlSessionFactory.openSession(); try { int result = session.insert("com.webcode.pojo.User.saveUser",user); session.commit();//提交事務 return result; } catch (Exception e) { e.printStackTrace(); } finally { session.close();//釋放資源 } return -1; } /* * 根據id刪除用戶 * */ public int deleteUserById(Integer id) { SqlSession openSession = sqlSessionFactory.openSession(); try { int delete = openSession.delete("com.webcode.pojo.User.deleteUserById",id); openSession.commit();//手動提交事務 return delete; } catch (Exception e) { e.printStackTrace(); } finally { openSession.close();//釋放資源 } return -1; } /* * 修改用戶 * */ public int updateUser(User user) { SqlSession openSession = sqlSessionFactory.openSession(); try { int update = openSession.update("com.webcode.pojo.User.updateUsers",user); openSession.commit();//手動提交事務 return update; } catch (Exception e) { // TODO: handle exception }finally { openSession.close();//釋放資源 } return -1; } } 

二、編寫UserMapper.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"> <!-- namespace名稱空間 取值通常有兩種狀況: 一種狀況是:使用javaBean的全類名 二種狀況是:使用Mapper接口的全類名 --> <mapper namespace="com.webcode.pojo.User"> <!-- select標籤用來配置一個select語句 id 用來配置一個惟一的標識 resultType 是查詢完以後一條記錄對應轉換成爲的javaBean對象 #{id}是佔位符 --> <select id="selectUserById" resultType="com.webcode.pojo.User"> select id,last_name lastName,sex from t_user where id = #{id} </select> <!-- 查詢所有的User對象 --> <select id="queryUsers" resultType="com.webcode.pojo.User"> select id,last_name lastName,sex from t_user </select> <!-- parameterTypr參數類型(可選) useGeneratedKeys="true" 使用(或返回)數據庫生成的主鍵 keyProperty="id" 把數據庫返回的主鍵值注入到bean對象的id屬性中 --> <insert id="saveUser" parameterType="com.webcode.pojo.User" > <!-- selectKey標籤能夠定義一些查詢語句,這些語句能夠選擇性地在大標籤的sql語句以前或以後執行 咱們但願,經過執行一個查詢,把最後一次生成的id返回。 order屬性配置執行的順序 BEFORE 以前 AFTER 以後 keyProperty="id" 把數據庫返回的主鍵值注入到bean對象的id屬性中 resultType="int" 設置selectKey查詢以後返回的類型是什麼 int 表示Integer類型 --> <selectKey order="AFTER" keyProperty="id" resultType="int"> select last_insert_id() </selectKey> insert into t_user (`last_name`,`sex`) values(#{lastName},#{sex}) </insert> <!-- <insert id="saveUser" parameterType="com.webcode.pojo.User" --> <!-- useGeneratedKeys="true" keyProperty="id"> --> <!-- insert into t_user (`last_name`,`sex`) values(#{lastName},#{sex}) --> <!-- </insert> --> <!-- 根據id刪除一個用戶 --> <delete id="deleteUserById" parameterType="int"> delete from t_user where id=#{id} </delete> <update id="updateUser" parameterType="com.webcode.pojo.User"> update t_user set last_name = #{lastName},sex=#{sex} where id=#{id} </update> </mapper>

映射關係圖解:

三、編寫UserDao測試

package com.webcode.dao.test; import static org.junit.Assert.*; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.BeforeClass; import org.junit.Test; import com.webcode.dao.UserDao; import com.webcode.pojo.User; /** * @author 鮀城小帥 * */ public class UserDaoTest { private static UserDao userDao; @BeforeClass public static void setUpBeforeClass() throws Exception { SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder() .build(Resources.getResourceAsStream("mybatis-config.xml")); userDao = new UserDao(); userDao.setSqlSessionFactory(sqlSessionFactory); } @Test public void testQueryUserById() { System.out.println(userDao.queryUserById(1)); } @Test public void testQueryUsers() { userDao.queryUsers().forEach(System.out::println); } @Test public void testSaveUser() { userDao.saveUser(new User(null, "xxx", 1)); } @Test public void testDeleteUserById() { userDao.deleteUserById(3); } @Test public void testUpdateUser() { userDao.updateUser(new User(3,"aaa",0)); } } 

四、插入記錄並返回主鍵

打印結果:

五、插入記錄並返回主鍵

<!-- parameterType類型(可選) -->
  <insert id="saveUser" parameterType="com.webcode.pojo.User" keyProperty="id"        useGeneratedKeys="true" >
  		<!--   parameterType 參數類型(可選)
			useGeneratedKeys="true"		使用(或返回)數據庫生成的主鍵
			keyProperty="id"	把數據庫返回的主鍵值注入到bean對象的id屬性中
	 -->
  		insert into t_user(`last_name`,`sex`) values(#{lastName},#{sex})
  </insert>

六、標籤的使用

<!-- parameterType類型(可選) -->
  <insert id="saveUser" parameterType="com.webcode.pojo.User" > <!-- selectKey標籤能夠定義一些查詢語句,這些語句能夠選擇性地在大標籤的sql語句以前或以後執行 咱們但願,經過執行一個查詢,把最後一次生成的id返回。 order屬性配置執行的順序 BEFORE 以前 AFTER 以後 keyProperty="id" 把數據庫返回的主鍵值注入到bean對象的id屬性中 resultType="int" 設置selectKey查詢以後返回的類型是什麼 int 表示Integer類型 --> <selectKey order="AFTER" keyProperty="id" resultType="int"> select last_insert_id </selectKey> insert into t_user(`last_name`,`sex`) values(#{lastName},#{sex}) </insert> 

4、Mapper 接口方式的 mybatis 的增,刪,改,查實現

一、Mapper 接口編程的命名習慣

  1. JavaBean對象是                User
  2. Mapper接口的名稱是:         UserMapper
  3. sql語句的配置文件命名:       UserMapper.xml
  1. JavaBean對象是                Book
  2. Mapper接口的名稱是:         BookMapper
  3. sql語句的配置文件命名:       BookMapper.xml

二、Mapper接口開發有四個開發規範 必須遵照

一、名稱空間必須是接口的全類名
二、方法名必須與id值一致
三、parameterType必須與方法參數類型一致
四、resultType必須與方法返回值一致(是指javaBean對象)

三、編寫 Mapper 接口

public interface UserMapper {

	public User queryUserById(Integer id);

	public List<User> queryUsers();

	public int saveUser(User user);

	public int deleteUserById(Integer id);

	public int updateUser(User user);
	
}

四、UserMapper.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名稱空間值必須是Mapper接口的全類名
   -->
<mapper namespace="com.webcode.mapper.UserMapper">
<!-- 	
		Mapper接口方案須要注意的第二點事項是:
			方法名,必需要和id值一致
		Mapper接口方案須要注意的第三點事項是:
			返回值類型必須一致
		Mapper接口方案須要注意的第四點事項是:
			參數類型也必須一致(寫就必須一致)
 -->
	<select id="queryUserById" resultType="com.webcode.pojo.User" parameterType="int">
		select id,last_name lastName,sex from t_user where id = #{id}
	</select>
<!-- 	public List<User> queryUsers(); -->
	<select id="queryUsers" resultType="com.webcode.pojo.User">
		select id,last_name lastName,sex from t_user
	</select>

<!-- 	public int saveUser(User user);
			普通類型能夠忽略(主要是javaBean對象)
 -->
	<insert id="saveUser" parameterType="com.webcode.pojo.User" useGeneratedKeys="true" keyProperty="id">
		insert into t_user(last_name,sex) values(#{lastName},#{sex})
	</insert>

<!-- 	public int deleteUserById(Integer id); -->
	<delete id="deleteUserById">
		delete from t_user where id = #{id}
	</delete>
<!-- 	public int updateUser(User user); -->
  	<update id="updateUser" parameterType="com.webcode.pojo.User">
  		update t_user set last_name = #{lastName},sex = #{sex} where id = #{id}
  	</update>
</mapper>

五、編寫UserMapper測試

package com.webcode.mapper.test; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import com.webcode.mapper.UserMapper; import com.webcode.pojo.User; import org.junit.BeforeClass; import org.junit.Test; public class UserMapperTest { static SqlSessionFactory sqlSessionFactory; @BeforeClass public static void setUpBeforeClass() throws Exception { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } @Test public void testQueryUserById() { SqlSession session = sqlSessionFactory.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); System.out.println(mapper.queryUserById(1)); } catch (Exception e) { e.printStackTrace(); }finally { session.close(); } } @Test public void testQueryUsers() { SqlSession session = sqlSessionFactory.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); mapper.queryUsers().forEach(System.out::println); } catch (Exception e) { e.printStackTrace(); }finally { session.close(); } } @Test public void testSaveUser() { SqlSession session = sqlSessionFactory.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); int saveUser = mapper.saveUser(new User(null,"吳",11)); session.commit(); System.out.println(saveUser); } catch (Exception e) { e.printStackTrace(); }finally { session.close(); } } @Test public void testDeleteUserById() { SqlSession openSession = sqlSessionFactory.openSession(); try { UserMapper mapper = openSession.getMapper(UserMapper.class); int deleteUserById = mapper.deleteUserById(2); openSession.commit(); System.out.println(deleteUserById); } catch (Exception e) { e.printStackTrace(); }finally { openSession.close(); } } @Test public void testUpdateUser() { SqlSession session = sqlSessionFactory.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); int updateUser = mapper.updateUser(new User(1,"少",33)); session.commit(); System.out.println(updateUser); }catch (Exception e) { e.printStackTrace(); }finally { session.close(); } } } 

5、mybatis的核心配置之properties

<!-- 
		properties標籤能夠用來定義多組鍵值對
			每一個property標籤是一組鍵值對 
		properties標籤還能夠引入單獨的屬性配置文件
			resource="jdbc.properties" 引入classpath路徑下的jdbc.properties配置文件
		源碼目錄,就是classPath路徑
		
		properties標籤在引入外部屬性配置文件和內部定義屬性的時候。外部會替換掉內部定義的值。
	-->
	<properties resource="jdbc.properties">
		<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
		<property name="username" value="root"/>
	</properties>
相關文章
相關標籤/搜索