Mybatis_2.核心配置

本文详细解读了Mybatis的核心配置,包括SqlSessionFactory与SqlSession对象,数据库配置、typeAliases、typeHandler、environments和mappers元素,以及映射文件中的select、insert、update、delete和resultMap。通过实例演示了如何简化配置和提高代码效率。

系列文章目录

第一章 初识Mybatis

第二章 Mybatis核心配置


文章目录

目录

一、前言

二、回顾与补充

三、Mybatis核心配置

1.Mybatis的核心对象

2.Mybatis配置文件

properties元素

settings元素 

typeAliases元素   (常用) 

typeHandler元素 (不常用)

 environments元素

mappers元素 

3.映射文件

select元素

insert元素 

 update元素和delete元素

 sql元素

 resultMap元素

四、总结


一、前言

   本系列为博主近期复习Mybatis相关知识时整合的书籍内容、相关练习例子以及个人的一些理解的分享,作为自己重温Mybatis操作的总结。希望能对在学习Mybatis或者在一些操作上遇到同样bug的同学给到一定的帮助。

   本次的代码 链接: https://pan.baidu.com/s/13ebpuITEe5xY6_yY0hAeoA?pwd=fuu0 提取码:fuu0


二、回顾与补充

    回顾:上一次与大家一起了解了Mybatis的基本使用步骤,用mybatis实现了简单学生增删改查的例子,这一次将和大家一起分享一下Mybatis的核心配置。

    补充:在上一次的例子,每一次执行方法时都要读取配置->构建sqlSessionFactory->创建sqlSession对象,这样写的第一个问题就是重复代码。第二个是会多次实例化sqlSessionFactory对象,工厂对象一旦被创建,在整个应用执行期间都会存在。如果我们多次地创建同一个数据库的SqlSessionFactory,就造成了资源的浪费

     解决方法:对此我们可以封装一个工具类同时用上单例模式,简化了方法代码的简洁同时保证每次获取的Factory对象唯一。

  • 1、创建MybatisUtils工具类
package com.mashang.util;

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;

public class MybatisUtils {
    // 在这里使用的是饿汉式
    // sessionFactory将会经常使用因此可以在项目启动时直接创建
    private static SqlSessionFactory sessionFactory = null;

    //使用静态代码块创建factory
    static {
        try {
            // 读取配置文件
            InputStream resource = Resources.
                    getResourceAsStream("mybatis-config.xml");
            // 构建SqlSessionFactory工厂
            sessionFactory = new SqlSessionFactoryBuilder()
                    .build(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 获取sqlSession的静态方法
    public static SqlSession getSession() {
        return sessionFactory.openSession();
    }
}
  • 2、修改测试类代码:
    /*
     * 根据学生ID返回学生数据
     * */
    @Test
    public void getStudentById() throws IOException {
        //1.通过工具类获取sqlSession
        SqlSession sqlSession = MybatisUtils.getSession();
        Student student = sqlSession.selectOne("com.mashang." +
                "mapper.StudentMapper.getStudentById", 1);
        System.out.println(student);
        sqlSession.close();
    }

三、Mybatis核心配置

1.Mybatis的核心对象

        Mybatis的核心对象有两个:SqlSessionFactorySqlSession。工厂类是单个数据库映射关系经过编译后的内存镜像,主要作用是创建SqlSession,而SqlSession是应用程序与持久层之间执行交互操作的一个单线程对象,其主要作用是执行持久化操作。

在上一小节也说到:

        通常每一个数据库都会只对应一个SqlSessionFactory,所以在构建SqlSessionFactory实例时,建议使用单列模式。

        而对于sqlSession而言,每一个业务都应该有一个自己的SqlSession实例,并且该实例是不能被共享的。同时在使用完成后要及时关闭sqlSession。

        sqlSession中封装了很多方法,比如我们上一次用到的selectOne、selectList、insert、update、delete等,想要具体了解所有的方法,我们可以点进sqlSession的源码中查看:


2.Mybatis配置文件

        Mybatis的配置文件也就是我们先前配置的"mybatis-config.xml"文件,在上一章的入门案例中,我们在配置文件内只使用了<environments>和<mapper>等几个元素,但在实际开发时,通常还会对其他一些元素进行配置。对于xml文件来说配置项是要按照一定的顺序进行配置,这里附上mybatisConfig的配置顺序图供大家参考:

  • properties元素

 <properties>是一个配置属性的元素,在面向配置开发时,我们通常在db.properties中配置好数据库相关的配置,再通过动态替换<enviroment>中数据库的配置。当我们修改数据库信息时,只需要修改配置文件而不用改动mybatisConfig代码,具体实现方式如下:

        (1) 在项目目录下创建db.properties文件,编辑后的代码如下所示。

# 配置jdbc驱动
jdbc.driver=com.mysql.cj.jdbc.Driver
# 配置Jdbc url
# 其中userSSL指不使用SSL连接
# serverTimezone指的是数据库时区
jdbc.url=jdbc:mysql://localhost:3306/learn-mysql\
  ?userSSL=false&serverTimezone=Asia/Shanghai
# 配置用户名
jdbc.username=root
# 配置密码
jdbc.password=root

        (2) 在MyBatis配置文件mybatis-config.xml中配置<properties... />属性,具体如下:

<!--获取配置文件-->
    <properties resource="db.properties"/>

        (3)使用"${value}" 修改配置文件中数据库连接的信息,具体如下:

            <dataSource type="POOLED">
                <!--配置驱动-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--配置路径-->
                <!--userSSL=false:不使用SSL协议链接数据库-->
                <!--serverTimeZone=Asia/Shanghai:指明时区为亚洲上海-->
                <property name="url"
                          value="${jdbc.url}"/>
                <!--配置数据库用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--配置数据库密码-->
                <property name="password" value="${jdbc.password}"/>
            </dataSource>

 以上便是properties比较常用的一种配置方式,那么其实还可以展开<properties>标签,配置其<property>子标签,单独为每一个属性配置。有兴趣的朋友可以自行查阅相关资料、博客。

  • settings元素 

<settings>元素主要是开启Mybatis中的二级缓存、延迟加载等配置,在平常中使用的频率不是很高,因此这一块的内容博主给大家附上常用配置就不展开了。

  • typeAliases元素   (常用) 

<typeAliases>元素是为映射文件中的java类型设置一个别名,在先前的mapper映射文件中我们是使用全类名来设置java类型,如:resultType="com.mashang.entity.Student"。而在我们配置了<typeAliases>之后就只需要配置短类名即可,如:resultType="student"。(博主测试过使用首字母大写类名也可以被识别)。

配置的方法如下:

  1. 使用<typeAlias> 单独配置别名:
       <!--定义别名-->
        <typeAliases>
            <!--
                type:指定需要被定义别名的类的全限定名
                alias:自定义的别名
                可以代替com.mashang.entity.Student
                使用在映射文件的任何位置,
                若省略alias则默认以类名首字母小写为别名
                -->
            <typeAlias type="com.mashang.entity.Student" alias="student"/>
        </typeAliases>
  2. 使用自动扫描包定义别名:
        <typeAliases>
            <!--
            扫描com.mashang.entity下的所有包,
            所有实体类以首字母小写的非限定类名来作为它的别名
            -->
            <package name="com.mashang.entity"/>
        </typeAliases>

 除了可以使用<typeAliases>元素自定义别名外,MyBatis框架还默认为许多常见的Java类型(如数值、字符串、日期和集合等)提供了相应的类型别名,如图:

  • typeHandler元素 (不常用)

        typeHandler的作用就是将预处理语句中传入的参数从javaType(Java类型)转换为jdbcType(JDBC类型),或者从数据库取出结果时将jdbcType转换为javaType。为了方便转换,MyBatis框架提供了一些默认的类型处理器,如图:

         当MyBatis框架所提供的这些类型处理器不能够满足需求时,还可以通过自定义的方式对类型处理器进行扩展。通过实现TypeHandler接口或者继承BaseTypeHandle类来定义。注册的方式与<typeAliases>元素类似,这里不做具体的处理器展示,若有需要的朋友可以自行查阅资料。

  •  environments元素

        <environments>元素用于对环境进行配置,实际上就是数据源的配置,我们可以通过<environments>元素配置多种数据源,即配置多种数据库。

    <!--配置环境,默认环境id为mysql,
    可以有多个environment,通过id选择-->
    <environments default="mysql">
        <!--配置id为mysql的数据库环境-->
        <environment id="mysql">
            <!--配置事务管理,它的type属性用于指定事务管理的方式-->
            <transactionManager type="JDBC"/>
            <!--数据源配置-->
            <!--type为POOLED表示以连接池形式-->
            <dataSource type="POOLED">
                <!--配置驱动-->
                <property name="driver" value="${jdbc.driver}"/>
                <!--配置路径-->
                <!--userSSL=false:不使用SSL协议链接数据库-->
                <!--serverTimeZone=Asia/Shanghai:指明时区为亚洲上海-->
                <property name="url"
                          value="${jdbc.url}"/>
                <!--配置数据库用户名-->
                <property name="username" value="${jdbc.username}"/>
                <!--配置数据库密码-->
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

         在MyBatis中,可以配置两种类型的事务管理器,分别是JDBC和MANAGED不同点在于MANAGED从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期。

        对于数据源的配置,MyBatis框架提供了UNPOOLED、POOLED和JNDI三种数据源类型,具体如下:

        UNPOOLED:配置此数据源类型后,在每次被请求时会打开和关闭连接。它对没有性能要求的简单应用程序是一个很好的选择。

        POOLED:此数据源利用“池”的概念将JDBC连接对象组织起来,这种方式使得并发Web应用可以快速地响应请求,是当前流行的处理方式

        JNDI:此数据源可以在EJB或应用服务器等容器中使用。容器可以集中或在外部配置数据源,然后放置一个JNDI上下文的引用。

  • mappers元素 

        在配置文件中,<mappers>元素用于指定MyBatis映射文件的位置,一般可以使用以下4种方法引入映射器文件,具体如下所示。

  1. 使用类路径引入 
     
        <mappers>
            <mapper resource="com/mashang/mapper/StudentMapper.xml"/>
        </mappers>
  2. 使用本地文件路径引入
     
        <!--配置Mapper映射文件位置-->
        <mappers>
            <mapper url="file:\\\C:\Mybatis_02\src\
            main\java\com\mashang\mapper\StudentMapper.xml"/>
        </mappers>
  3. 使用接口类引入

    使用接口类需要先创建一个与mapper文件相同名字的接口类,且配置对应的抽象方法:
    package com.mashang.mapper;
    
    import com.mashang.entity.Student;
    
    /*
     * StudentMapper.xml的mapper接口类
     * */
    public interface StudentMapper {
        /*
        * 对应StudentMapper.xml中的getStudentByI方法
        <select id="getStudentById" parameterType="int"
                resultType="com.mashang.entity.Student">
            select *
            from student
            where id = #{id}
       </select>
        * */
        Student getStudentById();
    }
    
        <!--配置Mapper映射文件位置-->
        <mappers>
            <mapper class="com.mashang.mapper.StudentMapper"/>
        </mappers>
  4. 使用包名引入
        <mappers>
            <!--
            注意:包扫描是扫描mapper包下的接口类
                 而不是*.xml文件
            -->
            <package name="com.mashang.mapper"/>
        </mappers>

3.映射文件

  • select元素

        <select>元素用于映射查询语句,它可以帮助我们从数据库中读取出数据,并组装数据给业务开发人员。使用<select>元素执行查询操作非常简单,其示例如下 :

   <select id="getStudentById" parameterType="int"
            resultType="com.mashang.entity.Student">
        select *
        from student
        where id = #{id}
    </select>

上述语句中的唯一标识为getStudentById,它接收一个Integer类型的参数(int为Integer的别名),并返回一个Student类型的对象。除了上述示例代码中的几个属性外,还有其他一些可以配置的属性,如图:

  • insert元素 

         <insert>元素用于映射插入语句,在执行完元素中定义的SQL语句后,会返回一个表示影响记录数的整数。<insert>元素的配置示例如下:

    <!--添加学生-->
    <!--因为我在数据库中设置了id自增,因此将id赋值设为null-->
    <insert id="addStudent"
            parameterType="com.mashang.entity.Student">
        insert into student
        values (null, #{name}, #{age}, #{sex})
    </insert>

 <insert>元素的属性与<select>元素的属性大部分相同,但还包含了3个特有属性,这3个属性的描述如表:

属性说明
keyProperty(仅对insert和update有用)此属性的作用是将插入或更新操作时的主键值返回赋值给Entity类的某个属性,通常会设置为主键对应的属性(注意是实体类中的属性)。如果需要设置联合主键,可以在多个值之间用逗号隔开。
keyColumn(仅对 insert和 update有用)此属性用于设置第几列是主键,当主键列不是表中的第一列时需要设置。在需要主键联合时,值可以用逗号隔开。
useGeneratedKeys(仅对insert和 update有用)此属性会使 MyBatis使用JDBC的getGeneratedKeys()方法来获取由数据库内部生产的主键,如MySQL和SQL Server等自动递增的字段,其默认值为false

 对于三个属性,我们可以试验一把:

        (1)首先添加一个<insert>元素

   <insert id="addStudentWithReturn" parameterType="Student"
            keyProperty="id" useGeneratedKeys="true">
        insert into student(name, age, sex)
        values (#{name}, #{age}, #{sex})
    </insert>

        (2)修改StudentMapper接口

package com.mashang.mapper;

import com.mashang.entity.Student;

/*
 * StudentMapper.xml的mapper接口类
 * */
public interface StudentMapper {
    /*
    * 对应StudentMapper.xml中的getStudentByI方法
    <select id="getStudentById" parameterType="int"
            resultType="com.mashang.entity.Student">
        select *
        from student
        where id = #{id}
   </select>
    * */
    Student getStudentById();

    int addStudentWithReturn(Student student);
}

        (3)编写测试类


    /*
     * 创建ID并返回主键id
     * */
    @Test
    public void addStudentWithReturn() {
        // 1.准备一个学生类
        Student student = new Student();
        student.setName("冯艳");
        student.setAge(29);
        student.setSex("女");
        // 2.通过工具类获取sqlSession
        SqlSession session = MybatisUtils.getSession();
        // 3.通过getMapper传入mapper接口类的class对象获得mapper类
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        // 4.通过mapper类调用接口方法
        int row = mapper.addStudentWithReturn(student);
        if (row > 0) {
            System.out.println("添加学生成功");
            session.commit();
        } else {
            System.out.println("添加学生失败");
        }
        // 5.打印返回的student主键
        System.out.println(student.getId());
    }

         (4)运行结果:

  •  update元素和delete元素

        <update>和<delete>元素的使用比较简单,它们的属性配置也基本相同。<update>和<delete>元素的属性基本与<select>元素中的属性一致。与<insert>元素一样,<update>和<delete>元素在执行完之后,也会返回一个表示影响记录条数的整数,其使用示例如下:

  <!--根据id修改学生信息-->
    <!--
    这里使用了mybatis中的set和if结合的动态sql,
    根据传入参数动态生成sql语句,
    具体的动态sql语法在后续会介绍
    -->
    <update id="updateStudent"
            parameterType="com.mashang.entity.Student">
        update student
        <set>
            <if test="name!=null and name!=''">
                name=#{name},
            </if>
            <if test="age!=null and age!=''">
                age=#{age},
            </if>
            <if test="sex!=null and sex!=''">
                sex=#{sex},
            </if>
        </set>
        where id=#{id}
    </update>
    <!--根据id删除学生-->
    <delete id="deleteStudent" parameterType="int">
        delete
        from student
        where id = #{id}
    </delete>
  •  sql元素

        <sql>元素的作用就是定义可重用的SQL代码片段,然后在其他语句中引用这一代码片段。

        例如,定义一个包含name、age和sex字段的代码片段如下:

    <sql id="studentParamsWithoutId">name,age,sex</sql>
    <select id="getStudentById" parameterType="int"
            resultType="com.mashang.entity.Student">
        select
        <include refid="studentParamsWithoutId"></include>
        from student
        where id = #{id}
    </select>

 上面示例只是一个简单的引用查询。在实际开发中,可以更加灵活地定义SQL片段,这里的目的是想展示sql中可以多层嵌套、变量以及property的使用,其示例如下:

    <!--定义要查询的表名-->
    <sql id="tableName">
        ${tableName}
    </sql>
    <!--定义要查询的表-->
    <sql id="fromTable">
        from
        <include refid="${table_target}"/>
    </sql>
    <!--定义查询的列-->
    <sql id="columns">
        id
        ,name,age,sex
    </sql>
    <!--根据Id查询学生-->
    <select id="getStudentById" parameterType="int"
            resultType="com.mashang.entity.Student">
        select
        <include refid="columns"/>
        <include refid="fromTable">
            <property name="table_target" value="tableName"/>
            <property name="tableName" value="student"/>
        </include>
        where id = #{id}
    </select>
  •  resultMap元素

        <resultMap>元素表示结果映射集,是MyBatis中最重要也是最强大的元素。它的主要作用是定义映射规则、级联的更新以及定义类型转化器等。

    <!--resultMap的元素结构-->
    <resultMap id="" type="">
        <id/> <!--用于表示哪个列是主键-->
        <result/> <!--注入到字段或实体类属性的普通结果-->
        <association property=""/> <!--用于一对一关联-->
        <collection property=""/>   <!--用于一对多关联-->
    </resultMap>

 接下来,通过一个具体的案例来演示<resultMap>元素在此种情况的使用,具体步骤如下

        (1) 在mybatis数据库中,创建一个user表,并插入几条测试数据。 

属性名类型
uidint
usernamevarchar
addressvarchar

        数据如下:

uidusernameaddress
1夏芳湖南省 常德市 临澧县
2郝明湖南省 衡阳市 衡南县
3邱洋广西壮族自治区 贺州市 富川瑶族自治县

        (2) 创建持久化类User,并在类中定义id、name和age属性,以及其getter/setter方法和toString()方法

package com.mashang.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String address;
}

        (3) 创建映射文件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="com.mashang.mapper.UserMapper">
    <select id="findAllUser" resultMap="UserMap">
        select uid as iiiiid, username, address
        from user;
    </select>
    <!--resultMap的元素结构-->
    <resultMap id="UserMap" type="user">
        <!--其中property指的是实体类中的属性名,如id-->
        <!--column指的是在sql语句中得到的结果,如上方select
            语句返回结果为uid而我将其命名为iiiiid,则此处的
            column应该写iiiiid,其意思为将sql语句得到的结果
            iiiiid(uid)设置进User类的id属性中-->
        <id property="id" column="iiiiid"/>
        <!--result与id的属性值同理-->
        <result property="username" column="username"/>
        <result property="address" column="address"/>
    </resultMap>
</mapper>

         (4) 创建接口类UserMapper,并在接口类中编写抽象方法

package com.mashang.mapper;

import com.mashang.entity.User;

import java.util.List;

public interface UserMapper {
    List<User> findAllUser();
}

          (5) 在测试类中,编写测试方法findAllUserTest(),代码如下所示

    /*
     * 查询所有用户
     * */
    @Test
    public void findAllUser() {
        SqlSession session = MybatisUtils.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> user = mapper.findAllUser();
        System.out.println(user);
    }

        (6) 测试结果为: 

         可以看出,虽然user表的列名与User对象的属性名完全不一样,但查询出的数据还是被正确地封装到了User对象中。


四、总结

        本次主要对MyBatis中的核心对象和核心文件进行了介绍。首先讲解了MyBatis中的两个重要核心对象SqlSessionFactory和SqlSession;然后介绍了配置文件中的元素及其使用;最后对映射文件中的几个主要元素进行了介绍。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Donp1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值