Mybatis-基础

简介

查看Mybatis官方文档:https://mybatis.org/mybatis-3/zh/index.html

  1. Mybatis是一款优秀的持久层框架,它支持自定义SQL,存储过程以及高级映射
  2. Mybatis免除了几乎所有的JDBC代码以及设置参数获取结果集的工作。
  3. Mybatis可以通过简单的XML或者注解配置和映射原始类型接口java POJO为数据库中的记录。

Mybatis SQL 映射框架使得一个面向对象构建的应用程序去访问一个关系型数据库变得更容易。
MyBatis使用XML描述符注解对象存储过程SQL语句耦合。

Mybatis整体架构

在这里插入图片描述
接口层:SqlSession就是我们与myabtis完成交互的核心接口。
核心层:SqlSession执行的方法,底层需要经过配置文件的解析,SQL解析,请求参数映射,结果集映射的支持。
支持层:核心层的功能实现,是基于底层的各个模块,共同协同完成。

Mybatis与Hibernate比对

在这里插入图片描述

简单使用-基于Mapper动态代理

注意点

  1. mapper.xml文件中的namespace属性配置一定要和Mapper(定义的Dao接口)接口的全限定名相同。
  2. mapper.xml文件中定义的元素statement,它们的id属性要和Mapper(定义的Dao接口)接口的方法名相同。
  3. Mapper(定义的Dao接口)接口方法的方法参数类型,mapper.xml中定义的元素statementparameterType 属性中声明的类型一致。
  4. Mapper(定义的Dao接口)接口方法的方法返回值类型,mapper.xml中定义的元素statementresultType 属性中声明的类型一致。

项目引入mybatis依赖

<dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.0</version>
</dependency>

定义Mybatis配置文件

<?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>
    <settings>
    <!-- 定义全局参数 -->
    </settings>
    <environments default="dataSourceInfo">
        <environment id="dataSourceInfo">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/userInfo.xml"/>
    </mappers>
</configuration>

定义Mapper接口

public interface UserInfoMapper {
UserInfo findById();
}

实体类

public class UserInfo {
    
    private String id;
    
    private String name;
    
    private String sex;
    
    // getter setter toString equals hashcode
}

mapper.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.test.mybatis.mapper.UserInfoMapper">

    <select id="findById" resultType="com.test.mybatis.entity.UserInfo">
        select * from user_info where id = #{id}
    </select>
</mapper>

测试运行

public static void main(String[] args) throws Exception {
        InputStream xml = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(xml);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        
        // 获取Mapper接口的代理
        UserInfoMapper mapper = sqlSession.getMapper(UserInfoMapper.class);
        UserInfo userData= mapper .findById("123456");
        System.out.println(userData);
    }

一对一,多对一配置

如果存在关联查询,那么在mapper.xml中,可以配置<resultMap>标签属性。将数据库中的表字段与对象中的属性字段做映射。将mapper.xml中对应方法的返回属性resultType替换为resultMap,引用配置的resultMap

一对一
使用一对一查询时,在一个实体类中添加另一实体类属性。用resultMap实现映射关系时,使用association连接,javaType为封装的类型。

 <!--
      一对一查询
       <association 解决一对一问题
       property="student" 对应Score 中 student属性
       column="studentid" 对应Score_tb 与 student_tb关联的外键 列名,可以不写
       javaType="Student"  将其他非Score 中的字段写入Student 类  
  -->
 <resultMap id="scoreMap1" type="Score">
        <id column="scoreid" property="scoreid"></id>
        <result column="couresename" property="couresename"></result>
        <result column="score" property="score"></result>
        <result column="studentid" property="studentid"></result>
      
        <association property="student" column="studentid" javaType="Student" >
            <id property="id" column="id"></id>
            <result property="name" column="name"></result>
            <result property="age" column="age"></result>
            <result property="sex" column="sex"></result>
            <result property="height" column="height"></result>
            <result property="sAddress" column="s_address"></result>
        </association>
    </resultMap>

一对多
一对多是在一个类中包含另一个类list的集合,在映射时,使用CollectionofType为封装类型。

<!--
    <collection  解决一对多问题

    property="scoreList"  将collection 组成的成绩集合放置到 student对象中
    column="id"   根据相同 的学生id组成集合
    ofType="Score"  将学生id组成集合 每一个item 生成一个 Score
    -->
 <resultMap id="studentWithScoreMap" type="Student">
        <id column="id" property="id"></id>
        <result property="name" column="name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="height" column="height"></result>
        <result property="sAddress" column="s_address"></result>

        <collection property="scoreList" column="id" ofType="Score">
            <id property="scoreid" column="scoreid"></id>
            <result property="couresename" column="couresename"></result>
            <result property="score" column="score"></result>
            <result property="studentid" column="id"></result>
        </collection>

    </resultMap>

多对多
表之间的多对多关系稍微复杂,需要一个中间表来表示。
中间表有三个字段,其中两个字段分别作为外键指向各自一方的主键,由此通过中间表来表示多对多关系,通过一个表联合另一个中间表可以表示为一对多关系。
多对多,其实可以从一方到另一方表示为一对多关系,反之亦然
在这里插入图片描述
如:查找学生并包含职位信息

<!--多对多中的一对多-->
    <resultMap id="studentWithRole" type="Student">
        <id property="id" column="id"></id>
        <result property="name" column="name"></result>
        <result property="age" column="age"></result>
        <result property="sex" column="sex"></result>
        <result property="height" column="height"></result>
        <result property="sAddress" column="s_address"></result>
        <collection property="roleList" column="roleid" ofType="Role">
        <id property="roleid" column="roleid"></id>
            <result property="rolename" column="rolename"></result>
        </collection>
    </resultMap>

Mybatis中设置的配置文件详解

properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)

properties属性

properties属性作用

  1. 定义全局配置变量
  2. 加载外部化的properties配置文件

定义全局配置变量,使用 ${} 的表达式如下

 <properties>
        <property name="jdbc.driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="jdbc.url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"/>
        <property name="jdbc.username" value="root"/>
        <property name="jdbc.password" value="123456"/>
    </properties>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

加载外部化配置文件

1.我们先把数据源连接配置到properties文件中,文件名称为jdbc.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

2.通过properties标签把上面的properties文件加载进来。

<properties resource="jdbc.properties" />

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driverClassName}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

resource/url只能声明一个文件。resourceurl 是互斥的,二者只能取其一。那么如何声明多个文件呢?
  通过xml配置的方式是无法实现的。我们可以通过定义Properties对象,加载多个配置文件。通过构造SqlSessionFactory的时候,传入Properties对象。

 InputStream xml = Resources.getResourceAsStream("mybatis-config.xml");
        // 使用Properties的API加载这些properties文件
        Properties properties = new Properties();
        properties.load(Resources.getResourceAsStream("jdbc1.properties"));
        properties.load(Resources.getResourceAsStream("jdbc2.properties"));
        
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(xml, properties);

3.配置的优先级
总共配置的方式有三种
(1)直接在 <properties> 中定义配置属性
(2)借助 <properties>resource / url 属性加载外部化配置文件
(3)编程式加载外部化配置文件

按照官方的说法,优先级为:
第一:编程式加载的外部化配置文件
第二:借助 <properties>resource / url 属性加载外部化配置文件
第三:在 <properties> 中定义的配置属性

setting配置

MyBatis 中可供调整的所有内部配置项的全局设置。
在这里插入图片描述

typeAliases-类型别名

typeAliases 类型别名的设置,是考虑到 mapper.xml 中我们每次写实体类的时候,都要写它们的全限定类名,太麻烦,于是 MyBatis 提供了类型别名的机制。

<typeAliases>
        <!-- 逐个声明 -->
        <typeAlias alias="Student" type="com.test.mybatis.entity.Student"/>
        
        <!-- 包扫描
             以此法被扫描的实体类,别名为类名的首字母小写形式(类似于Bean -> bean)
        -->
        <package name="com.test.mybatis.entity"/>
</typeAliases>

typeHandlers-类型处理器

typeHandlers 类型处理器,它的意义是针对一个特定的 Java 类型,或者 jdbc 类型,采用特定的处理器来处理这个类型的字段。
在这里插入图片描述
Java 类型和 jdbc 类型之间,用什么类型进行转换,都是这些 typeHandler 干的活。
一般情况下,我们只需要使用 MyBatis 内置的这些 typeHandler 就完全够用。

自定义类型处理器

实现 TypeHandler 接口,并声明其泛型,泛型就是要处理的目标类型。
TypeHandler 接口中定义了 4 个方法。分别对应对方法参数的处理,对返回结果集的处理。

当方法传入的参数为TypeHandler接口中指定的泛型的时候,如何对PreparedStatement 操作。
当方法返回结果封装时,对于实体类中出现的指定泛型类型的属性时,应该如何从ResultSet中取到数据,并转换为指定类型。

objectFactory-对象工厂

每次查询动作中,数据库返回 ResultSet 时,MyBatis 会根据 statemet 的定义,创建对应的结果对象(跟表对应的实体类对象)。

创建结果对象的工厂,是一个叫 ObjectFactory 的家伙负责的。

默认情况下,MyBatis 内置了一个 DefaultObjectFactory 来实现结果对象的创建,而我们定义的结果对象通常都有默认的无参构造器,或者有显式定义无参构造器,这样也是方便 DefaultObjectFactory 帮我们创建结果对象。

既然 MyBatis 的全局配置文件中提供了 objectFactory 标签,就说明 MyBatis 允许我们自定义 ObjectFactory 以代替默认的 DefaultObjectFactory

如果要自定义对象创建工厂objectFactory,我们只需要继承DefualtObjectFactory即可。然后重写创建对象的create方法。

public class ExtendsObjectFactory extends DefaultObjectFactory {
    
    @Override
    public <T> T create(Class<T> type) {
        T t = super.create(type);
        // 判断是否为User类型,如果是,则预初始化值
        if (User.class.equals(type)) {
            User user = (User) t;
            user.setAge(0);
        }
        return t;
    }
}

然后注册到mybatis-config.xml配置文件中。

<objectFactory type="com.test.mybatis.factory.ExtendsObjectFactory"/>

plugins-插件

MyBatis 的插件实际上就是拦截器,它可以拦截 MyBatis 的执行流程,并在特定的位置上提供扩展
Mybatis提供的可扩展的位置有4个:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)

我们都知道有一个分页插件PageHelper,它就是基于Mybatis的插件机制实现的。

environments-环境

环境的配置和spring中profile概念差不多。我们数据源的配置都配置在这里。

databaseIdProvider-数据库厂商标识

databaseIdProvider 数据库厂商标识,它为我们提供了数据库可移植性的支持。
我们在编写 mapper.xml 时,针对不同的 statement ,声明不同的数据库厂商标识MyBatis 即会动态的根据数据库厂商标识,使用不同的 statement ,从而达到不同的数据库发送不同 SQL 的效果

我们可以在Mybatis-config.xml中配置databaseIdProvider。
 <databaseIdProvider type="DB_VENDOR"> <!-- DB_VENDOR是固定的 -->
        <property name="MySQL" value="mysql"/>
        <property name="Oracle" value="oracle"/>
    </databaseIdProvider>
在mapper.xml中进行引用
<select id="findAllByStudentId" parameterType="string" 
            resultType="com.test.mybatis.entity.Student" databaseId="mysql">
        select name,age from gen_studentinfo where id = #{studentId}
    </select>

    <select id="findAllByStudentId" parameterType="string" 
            resultType="com.test.mybatis.entity.Student" databaseId="oracle">
        <!-- 注意这里查的表不一样 -->
        select name,age from gen_studentinfo where id= #{studentId}
    </select>

mappers-映射器

配置 mapper.xml 都在这里面写。
三种方式:
1.通过resource指定加载的mapper.xml。
2.通过class指定加载的mapper接口。
3.通过package指定扫描所有mapper接口。使用包扫描时,Mapper接口与对应的mapper.xml放在同一个目录下,且Mapper接口的名称要与mapper.xml的名称一致。(Mapper接口包扫描时会自动寻找同目录下的同名称的mapper.xml文件加载解析)

 <mappers>
        <mapper resource="mapper/studentMapper.xml"/> <!-- 直接加载mapper.xml -->
        <mapper class="com.test.mybatis.mapper.UserMapper"/> <!-- 加载Mapper接口 -->
        <package name="com.test.mybatis.mapper"/> <!-- 包扫描Mapper接口 -->
    </mappers>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值