框架是一款半成品軟件,咱們能夠基於這個半成品軟件繼續開發,來完成咱們個性化的需求!java
框架:大工具,咱們利用工具,能夠快速開發項目 (mybatis也是一個jar包,不過提供的功能更加多)mysql
jar包:小工具sql
如圖:數據庫
生活中的例子,好比蓋房子apache
張三想蓋紅色的房子,他須要先給架構搭起來,而後再給房子圖上紅色api
李四想蓋藍色的房子,他也須要先給架構搭起來,而後再給房子圖上藍色session
好比不少人都須要蓋房子,那麼確定會有不少重複性的工做,好比說基礎架構mybatis
這時候就有公司出了一個解決方案,準備好了房子的架構(上圖左下角黑色的),誰須要蓋房子,只須要藉助於公司提供的架構,在這個基礎之上進行裝修,塗色便可架構
ORM(Object Relational Mapping): 對象關係映射app
object:指的是實體對象,javabean
relational:指的是關係型數據庫,好比mysql
Mapping: 映射,一 一對應的關係
指的是持久化數據和實體對象的映射模式,爲了解決面向對象與關係型數據庫存在的互不匹配的現象的技術。
如圖:
簡單說,ORM 就是經過實例對象的語法,完成關係型數據庫的操做的技術,是"對象-關係映射"(Object/Relational Mapping) 的縮寫
ORM 把數據庫映射成對象,具體映射關係以下圖:
原始 JDBC 的操做問題分析
1. 頻繁建立和銷燬數據庫的鏈接會形成系統資源浪費從而影響系統性能
sql 語句在代碼中硬編碼,若是要修改 sql 語句,就須要修改 java 代碼,形成代碼不易維護
查詢操做時,須要手動將結果集中的數據封裝到實體對象中
增刪改查操做須要參數時,須要手動將實體對象的數據設置到 sql 語句的佔位符
原始 JDBC 的操做問題解決方案
1. 使用數據庫鏈接池初始化鏈接資源
將 sql 語句抽取到配置文件中
使用反射、內省等底層技術,將實體與表進行屬性與字段的自動映射
經過分析原始jdbc操做存在的問題,以及對應的解決方案,那麼在對應的解決方案在徹底可使用MyBatis替代
mybatis 是一個優秀的基於java的持久層框架,它內部封裝了jdbc,使開發者只須要關注sql語句自己,而不須要花費精力去處理加載驅動、建立鏈接、建立statement等繁雜的過程
mybatis經過xml或註解的方式將要執行的各類 statement配置起來,並經過java對象和statement中sql的動態參數進行映射生成最終執行的sql語句
最後mybatis框架執行sql並將結果映射爲java對象並返回。採用ORM思想解決了實體和數據庫映射的問題,對jdbc 進行了封裝,屏蔽了jdbc api 底層訪問細節,使咱們不用與jdbc api 打交道,就能夠完成對數據庫的持久化操做
MyBatis官網地址:http://www.mybatis.org/mybatis-3/
MyBatis開發步驟:
①添加MyBatis的jar包
②建立Student數據表
③編寫Student實體類
④編寫映射文件StudentMapper.xml
⑤編寫核心文件MyBatisConfig.xml
⑥編寫測試類
0) 新建java項目:mybatis01
1) 導入MyBatis的jar包 (在」今日資料\jar包「 中,將jar包導入項目libs下)
mysql-connector-java-5.1.37-bin.jar
mybatis-3.5.3.jar
log4j-1.2.17.jar
2) 建立student數據表
3) 編寫Student實體
package com.itheima.bean;
public class Student {
private Integer id;
private String name;
private Integer age;
//省略get個set方法
}
4) 新建測試類
package com.itheima.dao;
public class StudentTest01 {
/*
查詢所有
*/
5) 編寫src/StudentMapper.xml映射文件
6) 編寫MyBatis核心文件: src/MyBatisConfig.xml
框架
框架是一款半成品軟件,咱們能夠基於框架繼續開發,從而完成一些個性化的需求。
ORM
對象關係映射,數據和實體對象的映射。
MyBatis
是一個優秀的基於 Java 的持久層框架,它內部封裝了 JDBC。
org.apache.ibatis.io.Resources:加載資源的工具類
mybatis的前身就是ibatis
核心方法
若是不使用Resources,那咱們能夠本身使用類加載器(可是麻煩)
//InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
InputStream is = StudentTest01.class.getClassLoader().getResourceAsStream("MyBatisConfig.xml");
org.apache.ibatis.session.SqlSessionFactoryBuilder:獲取 SqlSessionFactory 工廠對象的功能類
核心方法
經過加載mybatis的核心文件的輸入流的形式構建一個SqlSessionFactory對象
InputStream inputStream = Resources.getResourceAsStream("MyBatisConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory fact ory = builder.build(inputStream);
org.apache.ibatis.session.SqlSessionFactory:獲取 SqlSession 構建者對象的工廠接口。
核心api
代碼
//3.經過SqlSession工廠對象獲取SqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
//4.執行映射配置文件中的sql語句,並接收結果
List<Student> list = sqlSession.selectList("StudentMapper.selectAll");
說明:由於咱們的代碼是執行了一個查詢的語句,因此不用處理事務
org.apache.ibatis.session.SqlSession:構建者對象接口。用於執行 SQL、管理事務、接口代理。
核心api
SqlSession 實例在 MyBatis 中是很是強大的一個類。在這裏你會看到全部執行語句、提交或回滾事務和獲取映射器實例的方法
做用:
經過SqlSession對象,主要用途執行sql語句,對數據庫進行操做
本質:
SqlSession 能夠理解爲至關於一個數據庫鏈接(Connection 對象),你能夠在一個事務裏面執行多條 SQL,而後經過它的 commit、rollback 等方法,提交或者回滾事務
因此它應該存活在一個業務請求中,處理完整個請求後,應該關閉這條鏈接,讓它歸還給SqlSessionFactory,不然數據庫資源就很快被耗費精光,系統就會癱瘓,因此用 try...catch...finally... 語句來保證其正確關閉
Resources
加載資源的工具類
SqlSessionFactoryBuilder
獲取 SqlSessionFactory 工廠對象的功能類
SqlSessionFactory
獲取 SqlSession 構建者對象的工廠接口
指定事務的提交方式
SqlSession
構建者對象接口
執行 SQL
管理事務
接口代理
映射配置文件包含了數據和對象之間的映射關係以及要執行的 SQL 語句
這個namespace,命名空間,至關因而給這個映射節點,起一個名字
內部的全部增刪改查的配置,都須要經過這個命名空間獲取
語法:命名空間.id
<select>
:查詢功能標籤
屬性
id:惟一標識, 配合名稱空間使用。
parameterType:指定參數映射的對象類型
resultType:指定結果映射的對象類型
SQL 獲取參數: #{屬性名}
修改StudentMapper.xml,增長以下:
由於參數類型是Integer,因此屬性名能夠更名字(#{sid})
可是這裏的屬性名通常是與數據庫列名一致的
爲啥叫屬性名,其實應該是參數名,可是這個參數名通常都是與javabean中的屬性名保持一致的,因此叫屬性名
測試類StudentTest01.java,新增代碼:
/*
根據id查詢
*/
####3.3 新增功能
<insert>
:新增功能標籤
屬性
id:惟一標識, 配合名稱空間使用
parameterType:指定參數映射的對象類型
resultType:指定結果映射的對象類型
SQL 獲取參數: #{屬性名} #{列名}
修改StudentMapper.xml,增長以下:
注意:由於這裏的參數類型是Student,因此屬性名必須與Student的字段保持一致
測試類StudentTest01.java,新增代碼:
/*
新增功能
*/
<update>
:修改功能標籤
屬性
id:惟一標識, 配合名稱空間使用
parameterType:指定參數映射的對象類型
resultType:指定結果映射的對象類型
SQL 獲取參數: #{屬性名}
修改StudentMapper.xml,增長以下:
注意:由於這裏的參數類型是Student,因此屬性名必須與Student的字段保持一致
測試類StudentTest01.java,新增代碼:
/*
修改功能
*/
<delete>
:查詢功能標籤。
屬性
id:惟一標識, 配合名稱空間使用。
parameterType:指定參數映射的對象類型。
resultType:指定結果映射的對象類型。
SQL 獲取參數: #{屬性名}
修改StudentMapper.xml,增長以下:
測試類StudentTest01.java,新增代碼:
/*
刪除功能
*/
@Test
public void delete() throws Exception{
//1.加載核心配置文件
InputStream is = Resources.getResourceAsStream("MyBatisConfig.xml");
//2.獲取SqlSession工廠對象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
//3.經過工廠對象獲取SqlSession對象
SqlSession sqlSession = sqlSessionFactory.openSession();
//SqlSession sqlSession = sqlSessionFactory.openSession(true);
//4.執行映射配置文件中的sql語句,並接收結果
int result = sqlSession.delete("StudentMapper.delete",5);
//5.提交事務
sqlSession.commit();
//6.處理結果
System.out.println(result);
//7.釋放資源
sqlSession.close();
is.close();
}
總結: 你們能夠發現crud操做,除了標籤名稱以及sql語句不同以外,其餘屬性參數基本一致。
核心配置文件包含了 MyBatis 最核心的設置和屬性信息。如數據庫的鏈接、事務、鏈接池信息等。
以下圖:
properties標籤做用:
引入外部的數據庫配置文件
標籤屬性
resource:數據庫鏈接配置文件路徑
獲取數據庫鏈接參數的語法格式
${鍵名}
優勢
便於靈活的修改數據庫鏈接池配置參數.
建立:src/jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.59.143:3306/db1
username=rooot
password=itheima
修改MyBatisConfig.xml配置文件:properties標籤引入外部文件
<!--引入數據庫鏈接的配置文件-->
<properties resource="jdbc.properties"/>
<!-- property獲取數據庫鏈接的配置信息 -->
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<typeAliases>
:爲全類名起別名的父標籤。
<typeAlias>
:爲全類名起別名的子標籤。
屬性
type:指定全類名
alias:指定別名 ([ˈeɪliəs]:別名)
<package>
:爲指定包下全部類起別名的子標籤。(別名就是類名)
以下圖:
具體以下配置:修改MyBatisConfig.xml,增長代碼以下:
<!--起別名-->
<typeAliases>
<typeAlias type="com.itheima.bean.Student" alias="student"/>
<!--<package name="com.itheima.bean"/>
若是bean包下有不少Javabean都須要起別名,就可使用package,指定一個包名
這樣的話,就自動給這個包下全部的類添加別名,別名是類名的小寫名字
-->
</typeAliase>
</typeAliases>
而後使用的時候就方便了,修改StudentMapper.xml中的com.itheima.bean.Student
<select id="selectAll" resultType="student"> SELECT * FROM student </select> <select id="selectById" resultType="student" parameterType="int"> SELECT * FROM student WHERE id = #{id} </select> <insert id="insert" parameterType="student"> INSERT INTO student VALUES (#{id},#{name},#{age}) </insert> <update id="update" parameterType="student"> UPDATE student SET name = #{name},age = #{age} WHERE id = #{id} </update> <delete id="delete" parameterType="int"> DELETE FROM student WHERE id = #{id} </delete>
分層思想:控制層(controller)、業務層(service)、持久層(dao)。
調用流程
實現步驟
在controller包下: 新建StudentContoller類
在service包下: 新建StudentService接口以及StudentServiceImpl實現類
在mapper包下:新建StudentMapper接口以及StudentMapperImpl實現類
StudentContoller----->StudentService----->StudentMapper
在mybatis項目中持久層就再也不叫dao了,而是叫作mapper(其實都是同樣的,就是換個名字)
StudentMapper接口
package com.itheima.mapper; import com.itheima.bean.Student; import java.util.List; /* 持久層接口 */ public interface StudentMapper { //查詢所有 public abstract List<Student> selectAll(); //根據id查詢 public abstract Student selectById(Integer id); //新增數據 public abstract Integer insert(Student stu); //修改數據 public abstract Integer update(Student stu); //刪除數據 public abstract Integer delete(Integer id); }
StudentMapperImpl實現類
package com.itheima.mapper.impl; /* 持久層實現類 */ public class StudentMapperImpl implements StudentMapper { /* 查詢所有 */ @Override public List<Student> selectAll() { } /* 根據id查詢 */ @Override public Student selectById(Integer id) { } /* 新增功能 */ @Override public Integer insert(Student stu) { } /* 修改功能 */ @Override public Integer update(Student stu) { } /* 刪除功能 */ @Override public Integer delete(Integer id) { } }
StudentService接口
package com.itheima.service; import com.itheima.bean.Student; import java.util.List; /* 業務層接口 */ public interface StudentService { //查詢所有 public abstract List<Student> selectAll(); //根據id查詢 public abstract Student selectById(Integer id); //新增數據 public abstract Integer insert(Student stu); //修改數據 public abstract Integer update(Student stu); //刪除數據 public abstract Integer delete(Integer id); }
StudentServiceImpl實現類
package com.itheima.service.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.mapper.impl.StudentMapperImpl; import com.itheima.service.StudentService; import java.util.List; /* 業務層實現類 */ public class StudentServiceImpl implements StudentService { //建立持久層對象 private StudentMapper mapper = new StudentMapperImpl(); @Override public List<Student> selectAll() { return mapper.selectAll(); } @Override public Student selectById(Integer id) { return mapper.selectById(id); } @Override public Integer insert(Student stu) { return mapper.insert(stu); } @Override public Integer update(Student stu) { return mapper.update(stu); } @Override public Integer delete(Integer id) { return mapper.delete(id); } }
StudentController測試類:
package com.itheima.controller; import com.itheima.bean.Student; import com.itheima.service.StudentService; import com.itheima.service.impl.StudentServiceImpl; import org.junit.Test; import java.util.List; /* 控制層測試類 */ public class StudentController { //建立業務層對象 private StudentService service = new StudentServiceImpl(); //查詢所有功能測試 @Test public void selectAll() { List<Student> students = service.selectAll(); for (Student stu : students) { System.out.println(stu); } } //根據id查詢功能測試 @Test public void selectById() { Student stu = service.selectById(3); System.out.println(stu); } //新增功能測試 @Test public void insert() { Student stu = new Student(4,"趙六",26); Integer result = service.insert(stu); System.out.println(result); } //修改功能測試 @Test public void update() { Student stu = new Student(4,"趙六",16); Integer result = service.update(stu); System.out.println(result); } //刪除功能測試 @Test public void delete() { Integer result = service.delete(4); System.out.println(result); } }
工具類抽取:
package com.itheima.utils; 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 java.io.IOException; /* 工具類 */ public class MyBatisUtils { // 私有構造方法 private MyBatisUtils(){} // 聲明鏈接工廠對象 private static SqlSessionFactory sqlSessionFactory; // 靜態代碼塊,讀取核心配置文件並工廠對象賦值 static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("MyBatisConfig.xml")); } catch (IOException e) { e.printStackTrace(); } } // 提供靜態方法,返回SqlSession對象 public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(true); } }
StudentMapperImpl代碼:
package com.itheima.mapper.impl; import com.itheima.bean.Student; import com.itheima.mapper.StudentMapper; import com.itheima.utils.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import java.util.List; /* 持久層實現類 */ public class StudentMapperImpl implements StudentMapper { /* 查詢所有 */ @Override public List<Student> selectAll() { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectAll"); // 釋放資源 sqlSession.close(); // 返回結果 return list; } /* 根據id查詢 */ @Override public Student selectById(Integer id) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Student stu = sqlSession.selectOne("StudentMapper.selectById", id); // 釋放資源 sqlSession.close(); // 返回結果 return stu; } /* 新增功能 */ @Override public Integer insert(Student stu) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.insert("StudentMapper.insert", stu); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 修改功能 */ @Override public Integer update(Student stu) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.update("StudentMapper.update", stu); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 刪除功能 */ @Override public Integer delete(Integer id) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 Integer result = sqlSession.delete("StudentMapper.delete", id); // 釋放資源 sqlSession.close(); // 返回結果 return result; } /* 查詢指定的數據表 */ @Override public List<Student> selectByTableName(String tableName) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectByTableName",tableName); // 釋放資源 sqlSession.close(); // 返回結果 return list; } /* 模糊查詢 */ @Override public List<Student> selectLike(String condition) { // 獲取SqlSession對象 SqlSession sqlSession = MyBatisUtils.getSqlSession(); // 執行sql語句 List<Student> list = sqlSession.selectList("StudentMapper.selectLike",condition); // 釋放資源 sqlSession.close(); // 返回結果 return list; } }
在平常開發過程當中,排查問題時不免須要輸出 MyBatis 真正執行的 SQL 語句、參數、結果等信息,咱們就能夠藉助 LOG4J 的功能來實現執行信息的輸出。
使用步驟:
導入 jar 包:「01-MyBatis基礎\資料\jar包\log4j-1.2.17.jar」
修改核心配置文件:MyBatisConfig.xml
<!--配置LOG4J:如下name和value是固定寫法--> <settings> <setting name="logImpl" value="log4j"/> </settings>
在 src 下編寫 LOG4J 配置文件 : log4j.properties (配置文件名字也是固定寫法)
# Global logging configuration # 日誌的四個級別,從高到低:ERROR(錯誤信息) WARN(警告信息) INFO(普通訊息) DEBUG(調試信息,推薦使用) # stdout:輸出到控制檯 log4j.rootLogger=DEBUG, stdout # 輸出格式 log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
效果
錯誤:
Caused by: org.xml.sax.SAXParseException; lineNumber: 41; columnNumber: 17; 元素類型爲 "configuration" 的內容必須匹配 "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)"。
這個是由於configuration下的節點順序是有要求的,settings必須是在properties下,放在其餘位置會報錯。