MyBatis框架

框架概述

框架是一个半成品,已经对基础的代码进行了封装并提供相应的API去进行调用操作,开发者在使用框架时直接调用封装好的API可以省去很多代码的编写工作,从而提高工作效率和开发速度,框架是一种经过市场使用校验,具有一定功能的半成品软件
经过校验 : 指框架本身的功能经过测试,其框架所具有的功能均已实现
具有一定功能 : 指框架可以完成特定的功能,不同的框架功能不同
半成品软件 : 指框架自身是一个软件,但是该软件无法直接运行,需要配合其他的程序才可以完成指定的项目工作

框架的工作模式:
开发工程师在使用框架的功能基础上,完成开发剩余的部分功能逻辑,组成一个完整的产品

例如 : 我想卖包子
不使用框架 : 种小麦 ==> 磨面粉 ==> 擀面皮 ==> 养猪 ==> 杀猪剁成肉馅 ==> 包成包子蒸熟
使用框架 : 从框架拿来面皮 ==> 从框架拿来肉馅 ==> 我包起来蒸熟

MyBatis框架

MyBatis是一款优秀的持久层框架(将内存中的数据存储到数据库中),它支持定制化SQL,存储过程以及高级映射.
MyBatis避免了几乎所有的JDBC代码和手动设置SQL参数以及可以从查询到的结果集封装成我们想要的类型, MyBatis可以使用简单的XML文件或注解来配置和映射原生类型在这里插入图片描述
我们把MyBatis的功能架构分为三层:

  1. API接口层 : 提供给外部使用的接口API,开发人员通过这些本地API来操作数据库. 接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理
  2. 数据处理层 : 负责具体的SQL查找,SQL解析,SQL执行和执行结果映射处理等,它主要的目的使根据调用的请求完成一次数据库操作
  3. 基础支撑层 : 负责最基础的功能支撑,包括连接管理,事务管理,配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件,为上层的数据处理层提供最基础的支撑在这里插入图片描述

环境准备

  1. 添加项目需要的jar包
    • MySQL数据库的JDBC驱动包 mysql-connector-java-5.1.26-bin.jar
    • MyBatis框架的核心jar包 mybatis-3.4.5.jar
  2. 创建数据库里的表,在java中创建与之对应的模型
  3. mybatis主配置文件创建在Resource目录中,文件取名规范mybatis-config.xml,官网:https://mybatis.org/mybatis-3/zh/index.html,可在官网拷贝配置文件的约束
<?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="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

Mapper映射文件

例如UserMapper.xml
mybatis中访问SQL语句就是编写在xml文件中的,映射文件也需要在mybatis官网中拷贝约束
书写完xml文件之后需要在mybatis主配置文件中 mappers 标签中关联

查询语句

<?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="org.mybatis.mapper.UserMapper">
<!--namespace : 用来区分唯一映射xml文件,一般取名:包名.文件名(不带扩展名)-->
  <select id="selectUser" resultType="xxx.xxx.User">
    select * from user where id = #{id}
  </select>
</mapper>

select标签中的属性

<select
  id="selectPerson"
  parameterType="int"
  parameterMap="deprecated"
  resultType="xxx.xxx.User"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

各属性代表的含义

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是省略的,因为 MyBatis 可以通过传入的对象获取到这个类的字节码文件,自然知道传入的对象参数是什么类型了。
resultType告诉MyBatis把查询到的结果集一行数据封装成什么类型返回(类型的全限定名)。如果返回的是集合也是一样的,只需要告诉它每一行数据封装成什么类型就可以了,它会把每行数据封装成指定类型并添加到一个集合中去返回。如果类的属性与列名不一样则该属性获取不到数据, resultType 和 resultMap 之间只能同时使用一个。
resultMap对外部 resultMap 的命名引用。结果映射是 MyBatis 最强大的特性,如果你对其理解透彻,许多复杂的映射问题都能迎刃而解。 resultType 和 resultMap 之间只能同时使用一个。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
fetchSize这是一个给驱动的建议值,尝试让驱动程序每次批量返回的结果行数等于这个设置值。 默认值为未设置(unset)(依赖驱动)。
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
resultSetTypeFORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等价于 unset) 中的一个,默认值为 unset (依赖数据库驱动)。
databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。
resultOrdered这个设置仅针对嵌套结果 select 语句:如果为 true,则假设结果集以正确顺序(排序后)执行映射,当返回新的主结果行时,将不再发生对以前结果行的引用。 这样可以减少内存消耗。默认值:false。
resultSets这个设置仅适用于多结果集的情况。它将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称之间以逗号分隔

插入,更新,删除语句

<insert id="insertAuthor">
  insert into Author (id,username,password,email,bio)
  values (#{id},#{username},#{password},#{email},#{bio})
</insert>

<update id="updateAuthor">
  update Author set
    username = #{username},
    password = #{password},
    email = #{email},
    bio = #{bio}
  where id = #{id}
</update>

<delete id="deleteAuthor">
  delete from Author where id = #{id}
</delete>

insert,update,delete标签中的属性

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty="id"
  keyColumn="id"
  useGeneratedKeys="true"
  timeout="20">

<update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

<delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

各属性代表的含义

属性描述
id在命名空间中唯一的标识符,可以被用来引用这条语句。
parameterType将会传入这条语句的参数的类全限定名或别名。这个属性是省略的,因为 MyBatis 可以通过传入的对象获取到这个类的字节码文件,自然知道传入的对象参数是什么类型了。
flushCache将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:(对 insert、update 和 delete 语句)true。
timeout这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为未设置(unset)(依赖数据库驱动)。
statementType可选 STATEMENT,PREPARED 或 CALLABLE。这会让 MyBatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED。
useGeneratedKeys(仅适用于 insert 和 update)告诉MyBatis是否需要获取生成的主键,默认值:false
keyColumn仅适用于 insert 和 update)告诉MyBatis要获取的主键列。如果生成列不止一个,可以用逗号分隔多个属性名称。
keyProperty(仅适用于 insert 和 update)告诉MyBatis获取到的主键列,你帮我设置到传入SQL语句的对象参数中的哪个属性上。如果生成列不止一个,可以用逗号分隔多个属性名称。
databaseId如果配置了数据库厂商标识(databaseIdProvider),MyBatis 会加载所有不带 databaseId 或匹配当前 databaseId 的语句;如果带和不带的语句都有,则不带的会被忽略。

DAO层开发使用

DAO接口

在dao包中新建一个接口

public interface IUserDAO{
	void insert(User u);
}

DAO接口实现类

在dao.impl包下新建一个DAO实现类

public class UserDAOImpl implement IUserDAO{
	//实现方法
	public void insert(User u){
		try{
			//获取配置文件的输入流
			InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
			//使用SQL会话工厂创建对象,根据配置信息创建一个SQL会话工厂
			SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
			//使用SQL会话工厂对象(对连接池的封装)获得一个SQL会话对象
			SqlSession sqlSession = ssf.openSession();
			//SQL会话对象(对Connection的封装)调用对应方法去执行我们的SQL语句
			sqlSession.insert("org.mybatis.UserMapper.insert"); //xml命名空间 + sql语句id
			//提交事务
			sqlSession.commit();
			//释放SQL会话对象
			sqlSession.close();
		} catch (Exception e){
			e.printStackTrace(;)
		}
	}
}

MyBatis的执行流程

  1. 加载主配置文件(Mybatis-config.xml)和主配置文件中的关联映射xml文件到内存中,将配置文件中的内容配置到一些对象上,如Configuration , Environment , TransactionManger , DataSource等对象
  2. 通过操作获取到这些配置文件中访问数据需要的数据,根据这些数据创建SqlSessionFactory对象
  3. 从SqlSessionFactory对象中获取SqlSession对象,然后执行SQL
  4. 在xml中,INSERT INTO user(name,age) VALUES(#{name},#{age}) 这条SQL语句会先被翻译成 INSERT INTO user(name,age) VALUES( ? , ? ) 在加载完这个映射文件之后,会将SQL中的#{}(OGNL表达式) 翻译成占位符 ?
  5. 底层依然是使用PreparedStatement来执行这条SQL,在执行之前会使用反射去给的参数对象中获取属性,并设置到SQL语句对应?占位符

select查询结果封装resultType = 类型别名

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写
在mybatis主配置文件中添加这些标签就能实现

<typeAliases>
  <typeAlias alias="User" type="xxx.domain.User"/>
</typeAliases>
<!--或者使用整个包下的类都可以使用别名,别名为类名-->
<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

日志管理

在持久层的开发过程中,我们程序员需要随时观察SQL语句的执行情况,如果sql书写有问题我们能够及时发现就能节约很多时间,如果能够在开发工具控制台中将我们执行的SQL全部打印出来,那么就可以方便的观察SQL书写等出现的问题

  1. 首先将日志相关的jar包添加到项目中并引入
    在这里插入图片描述
  2. 在资源文件夹中新建一个日志配置文件, log4j.properties , 从mybatis官网中拷贝对于这个日志框架的一个打印模板
log4j.rootLogger=ERROR, stdout

log4j.logger.项目模块的包名=TRACE

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
  1. 配置好项目的包名后,这个项目执行的sql语句都会被打印

抽取数据库的四要素

由于主要配置文件中的内容太多,但数据库四要素可能偶尔需要改动,为了反正误改动到主配置文件中的其他内容,所以将四要素,独立写成一个properties文件

db.properties

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/javaWeb
username=root
password=admin
<!--在主配置文件添加这个标签,将这个properties文件在主配置文件中关联-->
<properties resource="db.properties"/>

在主要配置文件中使用这个properties文件中的内容时,使用"${properties文件中对应的key名称}"来获取


版权声明:本文为cylcjsg原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。