最後編輯時間:2020年2月8日11:04:11
一、前置知識
1、什麼是框架
框架(Framework)是整個或部分系統的可重用設計,表現爲一組抽象構件及構件實例間交互的方法;另一種定義認爲,框架是可被應用開發者定製的應用骨架。前者是從應用方面而後者是從目的方面給出的定義。
2、三層架構
表現層:用於展示數據;
業務層:用於業務處理;
持久層:用於和數據庫交互;
圖示:
3、持久層技術解決方案
JDBC技術:
Connection;
PreparedStatement;
ResultSet;
Spring的dbcTemplate:
Spring中對JDBC的簡單封裝;
Apache的DBUtils:
與Spring中對JDBC很像,也是對JDBC的簡單封裝;
備註:以上都不是框架,JDBC是規範,後面兩個只算是工具類;
二、MyBatis概述
1、簡介
白話簡介:JDBC是用Java操作數據庫,但是JDBC太麻煩,MyBatis是對JDBC的進一步封裝。
MyBatis 是一款優秀的持久層框架,它支持定製化 SQL、存儲過程以及高級映射;
MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集;
MyBatis 可以使用簡單的 XML 或註解來配置和映射原生類型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 對象)爲數據庫中的記錄;
MyBatis使用了ORM的思想實現了結果集的封裝;
作用:
1、用來訪問數據庫,進行持久化操作;
2、本質上是對JDBC進行封裝;
2、ORM思想
Object Relational Mapping 對象關係映射
白話:把數據庫表和實體類的屬性對應起來,讓我們可以通過操作實體類來實現操作數據庫表;
3、官方文檔地址
https://mybatis.org/mybatis-3/zh/index.html
三、MyBatis環境搭建
1、內容
POM.XML文件:用於指定所用到雲端框架的座標;
實體類:實體類對應要操作的表;
接口:接口是對數據庫進行操作的Java代碼(方法);
主配置文件:配置數據庫的信息用於訪問數據庫,指定映射配置文件;
映射配置文件:指定接口中的方法所執行的SQL語句;
2、MyBatis的基本構成
SqlSessionFactoryBuilder(構造器):
根據配置信息或者代碼來生成SqlSessionFactory(工廠接口);
SqlSessionFactory(工廠接口):
依靠工廠來生成SqlSession(會話);
概述:
1、每個MyBatis應用都是以SqlSessionFactory的實例爲中心的;
2、SqlSessionFactory的實例SqlSessionFactoryBuilder來獲得;
3、SqlSessionFactory是一個工廠接口而不是一個類,它的任務是創建SqlSession;
4、SqlSession是一個會話,類似JDBC的Connection對象;
5、MyBatis提供了兩種方式去創建SqlSessionFactory:XML配置的方式(推薦)和代碼的方式;
6、Configuration存在於整個MyBatis應用的生命週期中,體積小,性能高,解析一次XML文件保存到Configuration中,可重複讀取使用;
7、DefaultSqlSessionFactory是SqlSessionFactory的一個實現類;
使用XML方式構建SqlSessionFactory:
(見SqlMapConfig.xml)
代碼方式創建SqlSessionFactory:
大部分情況下不用,需要加入自己特性的時候纔用到,例如數據源配置的信息要求是加密的時候我們需要把他們轉化過來。
package com.zibo.mybatis_crud.utils;
import com.zibo.mybatis_crud.dao.IUserDao;
import com.zibo.mybatis_crud.domain.User;
import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
public class GetSqlSessionFactory {
public static SqlSessionFactory get(){
//1、構建數據庫連接池
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/zibo?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("zibo15239417242");
//2、構建數據庫事務方式
TransactionFactory transactionFactory = new JdbcTransactionFactory();
//3、創建數據庫運行環境
Environment environment = new Environment("development",transactionFactory,dataSource);
//4、構建Configuration對象
Configuration configuration = new Configuration(environment);
//5、註冊一個MyBatis上下文別名
configuration.getTypeAliasRegistry().registerAlias("user", User.class);
//6、加入一個映射器
configuration.addMapper(IUserDao.class);
//7、使用SqlSessionFactoryBuilder構建SqlSessionFactory
return new SqlSessionFactoryBuilder().build(configuration);
}
}
SqlSession(會話):
是一個可以發送SQL去執行並返回結果,也可以獲取Mapper的接口;
SqlSession(會話)的兩種用途:
1、獲取映射器,讓映射器通過命名空間和方法名稱找到對應的SQL,發送給數據庫執行後返回結果;
2、直接通過命名空間信息去執行SQL返回結果;
SQL Mapper(映射器):
是MyBatis新設計的組件,是由一個接口和XML文件(或者註解)構成的,需要給出對應的SQL和映射規則,負責發送SQL去執行並返回結果;
作用:
1、定義參數類型;
2、描述緩存;
3、描述SQL語句;
4、定義查詢結果和POJO的映射關係;
SQL Mapper(映射器)可以用XML方式和代碼方式實現,強烈建議XML方式,代碼方式不再演示,XML見(IStudentDao.xml):
3、步驟:
第一步:創建Maven工程並導入座標;
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zibo.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13-beta-3</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
第二步:創建實體類和dao的接口;
實體類:
package com.zibo.mybatis;
import java.io.Serializable;
public class Student implements Serializable {
private int id;
private String name;
private int age;
private String sex;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
接口:
package com.zibo.mybatis;
import java.util.List;
public interface IStudentDao {
List<Student> findAll();
}
第三步:創建MyBatis的主配置文件;
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">
<!--MyBatis的主配置文件-->
<configuration>
<!-- 配置環境-->
<environments default="mysql">
<!-- 配置mysql的環境-->
<environment id="mysql">
<!-- 配置事務類型-->
<transactionManager type="JDBC"></transactionManager>
<!-- 配置數據源,也叫連接池-->
<dataSource type="POOLED">
<!-- 配置連接數據庫的4個基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://rm-wz94daz94uktn3x7x4o.mysql.rds.aliyuncs.com/zibo?useUnicode=true;useJDBCCompliantTimezoneShift=true;useLegacyDatetimeCode=false;serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="zibo@709570094"/>
</dataSource>
</environment>
</environments>
<!-- 指定映射配置文件的位置,映射配置文件是指每個dao獨立的配置文件-->
<mappers>
<mapper resource="com/zibo/mybatis/IStudentDao.xml"/>
</mappers>
</configuration>
第四步:創建映射配置文件;
IStudentDao.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="com.zibo.mybatis.IStudentDao">
<!-- 配置查詢所有-->
<select id="findAll" resultType="com.zibo.mybatis.Student">
select * from student;
</select>
</mapper>
各個文件位置圖:
4、注意事項
①MyBatis把持久層的操作接口和映射文件也叫做Mapper,所以文件XXXDao和XXXMapper是一樣的;
②在idea創建目錄的時候,它和包是不一樣的:
包的創建:com.zibo.XXX是三級目錄;
目錄的創建:com.zibo.XXX是一級目錄;
③MyBatis的映射配置文件的位置必須和dao接口的包結構相同;
④映射配置文件的mapper標籤的namespace屬性的取值必須是dao接口(Mapper)的全類名;
⑤映射配置文件的操作配置(select),id的屬性取值必須是dao接口的方法名;
當遵循了③④⑤點之後,我們在開發中就無需再寫dao實現類;
四、入門
1、步驟
第一步:讀取配置文件;
第二步:創建一個SqlSessionFactory工廠;
第三步:使用工廠生產SqlSession對象;
第四步:使用SqlSession對象創建接口的代理對象;
第五步:使用代理對象執行方法;
第六步:釋放資源
2、代碼演示
配置文件:
log4j.properties:
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
測試代碼:
package com.zibo.mybatis;
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;
import java.io.InputStream;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
//第一步:讀取配置文件;
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//第二步:創建一個SqlSessionFactory工廠;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//第三步:使用工廠生產SqlSession對象;
SqlSession session = factory.openSession();
//第四步:使用SqlSession對象創建接口的代理對象;
IStudentDao iStudentDao = session.getMapper(IStudentDao.class);
//第五步:使用代理對象執行方法;
List<Student> students = iStudentDao.findAll();
for (Student student : students) {
System.out.println(student);
}
//第六步:釋放資源
session.close();
in.close();
}
}
運行結果:
五、入門案例分析
六、MyBatis基於註解的入門案例
1、原基礎修改步驟:
第一步:刪除IStudentDao.xml;
第二步:在IStudentDao的方法上使用Select註解,並指定SQL語句;
@Select("select * from student")
第三步:在SqlMapConfig.xml中的mapper配置中使用class屬性指定被註解的dao全限定類名;
<mapper class="com.zibo.mybatis.IStudentDao"/>
2、關於dao實現類
實際開發中越簡便越好,所有不管是XML配置還是註解配置都採用不寫dao實現類的方式,但是MyBatis是支持寫dao實現類的;
3、寫dao實現類的演示
修改步驟:
第一步:創建一個dao的接口實現類;
package com.zibo.mybatis;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import java.util.List;
public class IStudentDaoImpl implements IStudentDao {
private SqlSessionFactory factory;
public IStudentDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}
@Override
public List<Student> findAll() {
//1、使用工廠生產SqlSession對象
SqlSession session = factory.openSession();
//2、使用session執行查詢方法
//3、返回查詢結果
return session.selectList("com.zibo.mybatis.IStudentDao.findAll");
}
}
第二步:修改Test測試類:
package com.zibo.mybatis;
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;
import java.io.InputStream;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
//第一步:讀取配置文件;
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//第二步:創建一個SqlSessionFactory工廠;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//第三步:使用工廠生產SqlSession對象;
IStudentDaoImpl iStudentDao = new IStudentDaoImpl(factory);
// SqlSession session = factory.openSession();
// //第四步:使用SqlSession對象創建接口的代理對象;
// IStudentDao iStudentDao = session.getMapper(IStudentDao.class);
//第五步:使用代理對象執行方法;
List<Student> students = iStudentDao.findAll();
for (Student student : students) {
System.out.println(student);
}
//第六步:釋放資源
// session.close();
in.close();
}
}
七、生命週期
1、SqlSessionFactoryBuilder
是利用XML或者Java代碼的方式構建SqlSessionFactory,通過它可以構建多個SqlSessionFactory。
它的作用是一個構建器,一旦我們構建了SqlSessionFactory就不再需要它了,因此它一般在局部代碼中;
2、SqlSessionFactory
SqlSessionFactory作用是創建SqlSession,而SqlSession是一個會話,相當於JDBC的Connection對象,每次應用程序訪問數據庫,都需要通過SqlSessionFactory創建SqlSession對象,所以SqlSessionFactory應該存在於MyBatis應用的整個生命週期;
如果我們多次創建同一個數據庫的SqlSessionFactory,數據庫連接(Connection)資源很快就會被耗盡,所以SqlSessionFactory的責任是唯一的,就是創建SqlSession,我們果斷採用單例模式,所以每個數據庫應該只對應一個SqlSessionFactory;
3、SqlSession
SqlSession是一個會話,相當於JDBC中的Connection對象,它的生命週期應該是在請求數據庫請求事務的過程中。它是一個線程不安全的對象,在涉及多線程的時候我們要特別當心,操作數據庫需要注意其隔離級別,數據庫鎖等高等特性;
此外,每次創建的SqlSession都要及時關閉它,否則對系統性能的影響很大;
它存活於一個應用的請求和操作,可以執行多條SQL語句,保證事務的一致性;
4、Mapper
Mapper是一個接口,沒有任何實現類,它的作用是發送SQL,然後返回我們需要的結果,或者執行SQL從而修改數據庫的數據,因此它應該在一個SqlSession方法之內,是一個方法級別的東西,所以儘量在Sqlsession方法事務中使用它,然後廢棄掉。