Mybatis

本文介绍了MyBatis框架的配置流程,包括引入依赖、配置文件mybatis.xml详解、实体类与映射文件UserMapper.xml的编写,以及如何通过接口调用和动态代理实现数据库操作。还涵盖了别名、自定义配置和MyBatis的工作原理等内容。
摘要由CSDN通过智能技术生成

目录

What框架? Why框架

Mybatis简介

MyBatis 发展历史

MyBatis的优点

Mybatis配置

引入依赖

mybatis.xml配置文件

写跟数据库表对应的java实体类

映射文件UserMapper.xml

测试程序

使用别名

Mybatis调用接口Dao的接口方法,创建UserMapper接口

mybatis.xml配置详细说明

properties配置

typeAliases配置

typeHandlers

objectFactory配置

environments配置

databaseIdProvider配置

MyBatis 工作原理

1、SqlSession与Connection

2、SqlSession的getMapper

使用JDK的动态代理类Proxy,根据映射接口,创建动态代理对象


What框架? Why框架

1、框架即framework

        其实就是某种应用的半成品,就是一组组件,供你选用完成你自己的系统。

        简单理解就是一套资源,包含jar包、源码、帮助文档、示例等。

2、为什么要用框架开发?

使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。这样可以节省开发时间,提高代码重用性,让开发变得更简单。

Mybatis简介

MyBatis 是支持定制化 SQL以及高级映射(ORM)的优秀的持久层框架。

MyBatis 发展历史

Mybatis的前身是 Apache的一个开源项目 iBatis, 2010年迁移到了google code 改名为 MyBatis,最后又迁移到了Github。

mybatis – MyBatis 3 | 简介http://www.mybatis.org/mybatis-3/zh/index.html

MyBatis的优点

基于SQL语法,简单易学,能了解底层组装过程,SQL语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度,程序调试方便。

Mybatis配置

引入依赖

    <dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

mybatis.xml配置文件

mybatis配置顺序如下,不能颠倒,也就是如果有properties属性配置,一定放到最前面,settings放到第二个位置,以此类推

<?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>
        <!--日志配置(mybatis执行的日志,主要sql语句和参数),STDOUT_LOGGING配置日志打印控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="dev">
        <environment id="dev">
            <!--事务管理器JDBC-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源,使用连接池-->
            <dataSource type="POOLED">
                <!--数据库驱动-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--连接字符串-->
                <!--&amp;表示&,因为&在xml表示其他含义-->
                <property name="url"
                          value="jdbc:mysql://localhost:3306/db1?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                <!--数据库用户名-->
                <property name="username" value="root"/>
                <!--数据库密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!--自定义的映射文件-->
    <mappers>
        <!--resource 引入的Mapper映射文件的路径,类路径的资源路径-->
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

写跟数据库表对应的java实体类

package com.tjetc.entity;

/**
 * 注意点:
 * 1、如果要定义有参的构造方法, 原则上一定要定义一个无参的构造方法, 因为mybatis使用反射创建对象, 优先调用无参构造方法
 * 如果不定义无参构造方法, mybatis就会反射调用有参构造方法, 有可能造成参数对应错误或者类型对应不上, 会造成错误或出现异常
 * 2、实体类至少要有set方法, 这样才能把数据库查询的数据设置到实体类定义的成员变量中
 */
public class User {
    private Long id;
    private String username;
    private String password;

    public User(Long id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

映射文件UserMapper.xml

映射文件位置为:src/main/resources/mapper/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" >
<!--namespace 命名空间-->
<mapper namespace="test">
    <!--增删改查四大标签-->
    <!--select 查询标签,id唯一标识标签-->
    <!--resultType 表示返回值类型,如果返回值是集合,resultType 表示集合里元素的类型-->
    <select id="selectList" resultType="com.tjetc.entity.User">
        select * from `user`
    </select>
    <!--mybatis 的sql语句中传参数使用 #{参数名称}-->
    <!--sql中只有一个参数,参数的具体名称没有限定-->
    <!--标准写法: parameterType 参数类型, 全限定名  包名+类名
                 resultType 返回结果类型, 全限定名  包名+类名-->
    <select id="selectById" parameterType="java.lang.Long" resultType="com.tjetc.entity.User">
        select * from `user` where id=#{id}
    </select>
    <!--    <update id="">-->

    <!--    </update>-->
    <!--    <insert id="">-->

    <!--    </insert>-->
    <!--    <delete id="">-->

    <!--    </delete>-->
</mapper>

测试程序

package com.tjetc;

import com.tjetc.common.SqlSessionUtils;
import com.tjetc.entity.User;
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 org.junit.Test;

import java.io.IOException;
import java.util.List;

public class Test1 {
    //@Test注解的作用: 执行@Test标记的方法
    @Test
    public void testSelectList() throws IOException {
        //1、获取SqlSessionFactoryBuilder对象
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        //2、获取SqlSessionFactory对象
        SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsReader("mybatis.xml"));
        //3、获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //4、调用SqlSession对象的api方法并获取数据
        //Mapper映射文件中配置的namespace的值,目的调用四大标签中的sql语句
        List<User> users = sqlSession.selectList("test.selectList");
        //5、打印数据
        System.out.println(users);
        //6、关闭SqlSession
        sqlSession.close();
    }

    @Test
//封装后方法后的调用优化
    public void testSelectById() throws IOException {
//        //1、获取SqlSessionFactoryBuilder对象
//        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//        //2、获取SqlSessionFactory对象
//        SqlSessionFactory sqlSessionFactory = builder.build(Resources.getResourceAsReader("mybatis.xml"));
//        //3、获取SqlSession对象
//        SqlSession sqlSession = sqlSessionFactory.openSession();
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        //4、调用SqlSession的方法
        User user = sqlSession.selectOne("test.selectById", 4L);
        //5、打印
        System.out.println(user);
        //6、关闭资源
        SqlSessionUtils.close(sqlSession);
    }
}

 封装在common下的SqlSessionUtils类

package com.tjetc.common;

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 SqlSessionUtils {
    //1、获取SqlSessionFactoryBuilder对象
    static SqlSessionFactoryBuilder builder;
    //2、获取SqlSessionFactory对象
    static SqlSessionFactory sqlSessionFactory = null;

    static {
        builder = new SqlSessionFactoryBuilder();
        try {
            sqlSessionFactory = builder.build(Resources.getResourceAsReader("mybatis.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取SqlSession
     *
     * @return
     */
    public static SqlSession getSqlSession() {
        //3、获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        return sqlSession;
    }

    /**
     * 关闭资源
     *
     * @param sqlSession
     */
    public static void close(SqlSession sqlSession) {
        sqlSession.close();
    }
}

使用别名

在mybatis.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">
<!--跟标签-->
<configuration>
    <settings>
        <!--日志配置(mybatis执行的日志,主要sql语句和参数),STDOUT_LOGGING配置日志打印控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--配置别名-->
    <typeAliases>
        <!--配置User的别名:不区分大小写-->
        <typeAlias type="com.tjetc.entity.User" alias="User"/>
    </typeAliases>

    <environments default="dev">
        <environment id="dev">
            <!--事务管理器JDBC-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源,使用连接池-->
            <dataSource type="POOLED">
                <!--数据库驱动-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <!--连接字符串-->
                <!--&amp;表示&,因为&在xml表示其他含义-->
                <property name="url"
                          value="jdbc:mysql://localhost:3306/db1?useUnicode=true&amp;characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                <!--数据库用户名-->
                <property name="username" value="root"/>
                <!--数据库密码-->
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <!--自定义的映射文件-->
    <mappers>
        <!--resource 引入的Mapper映射文件的路径,类路径的资源路径-->
        <mapper resource="mapper/UserMapper.xml"></mapper>
        <mapper resource="mapper/UserMapper1.xml"></mapper>
    </mappers>
</configuration>

Mybatis调用接口Dao的接口方法,创建UserMapper接口

package com.tjetc.dao;
import com.tjetc.entity.User;
import java.util.List;

/**
 * 定义mapper接口
 */
public interface UserMapper {
    List<User> selectList();

    User selectById(Long id);
}

修改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" >
<!--namespace 命名空间-->
<!--如果使用接口, namespace的值为接口的全限定名: 包名+类名 -->
<mapper namespace="com.tjetc.dao.UserMapper">
    <!--mapper映射文件中,都可以使用别名-->
    <select id="selectList" resultType="user">
        select * from `user`
    </select>名+类名-->

    <!--<select id="selectById" parameterType="java.lang.Long" resultType="com.tjetc.entity.User">-->
    <!--使用别名:parameterType resultType不区分大小写-->
    <select id="selectById" parameterType="Long" resultType="User">
        select * from `user` where id=#{id}
    </select>
</mapper>

测试:

package com.tjetc;

import com.tjetc.dao.UserMapper;
import com.tjetc.common.SqlSessionUtils;
import com.tjetc.entity.User;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class Test2 {
    @Test
    public void testUserMapper() {
        //获取SqlSession对象
        SqlSession sqlSession = SqlSessionUtils.getSqlSession();
        //获取mapper接口对应的代理类对象(技术:jdk动态代理)
        //mapper是代理对象, 通过接口的全限定名 找到mapper映射文件, 在通过接口方法名称找到mapper映射文件 找到对应的四大标签,
        //使用jdbc技术, 把标签中的sql语句发送数据库执行, 接收返回值。
        // 因此, 我们只需要定义mapper接口不需要定义mapper接口对应的实现类
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //调用mapper的方法
        List<User> users = mapper.selectList();
        System.out.println(users);
        User user = mapper.selectById(3L);
        System.out.println(user);
    }
}

mybatis.xml配置详细说明

properties配置

resources目录下创建db.properties

driverName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
username=root
password=123456

修改mybatis.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">
<!--跟标签-->
<configuration>
    <!--加载properties配置文件, 类路径的资源-->
    <properties resource="db.properties"></properties>
    <settings>
        <!--日志配置(mybatis执行的日志,主要sql语句和参数),STDOUT_LOGGING配置日志打印控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--配置别名-->
    <typeAliases>
        <!--配置User的别名:不区分大小写-->
        <typeAlias type="com.tjetc.entity.User" alias="User"/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <!--事务管理器JDBC-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源,使用连接池-->
            <dataSource type="POOLED">
                <!--${key} 根据key值读取properties配置的value值-->
                <!--数据库驱动-->
                <property name="driver" value="${driverName}"/>
                <!--连接字符串-->
                <!--&amp;表示&,因为&在xml表示其他含义-->
                <property name="url" value="${url}"/>
                <!--数据库用户名-->
                <property name="username" value="${username}"/>
                <!--数据库密码-->
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--自定义的映射文件-->
    <mappers>
        <!--resource 引入的Mapper映射文件的路径,类路径的资源路径-->
        <mapper resource="mapper/UserMapper.xml"></mapper>
        <mapper resource="mapper/UserMapper1.xml"></mapper>
    </mappers>
</configuration>

typeAliases配置

类型别名是java类型的简写。它仅在XML配置文件中,用于简化合格的class名字

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean

<?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>
    <!--加载properties配置文件, 类路径的资源-->
    <properties resource="db.properties"></properties>
    <settings>
        <!--日志配置(mybatis执行的日志,主要sql语句和参数),STDOUT_LOGGING配置日志打印控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--配置别名-->
    <typeAliases>
        <!--配置User的别名:不区分大小写-->
        <!--<typeAlias type="com.tjetc.entity.User" alias="User"/>-->
        <!--package 配置指定包下的所有类, 都可以使用别名, 类名称, 例如:User、Student-->
        <package name="com.tjetc.entity"/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <!--事务管理器JDBC-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源,使用连接池-->
            <dataSource type="POOLED">
                <!--${key} 根据key值读取properties配置的value值-->
                <!--数据库驱动-->
                <property name="driver" value="${driverName}"/>
                <!--连接字符串-->
                <!--&amp;表示&,因为&在xml表示其他含义-->
                <property name="url" value="${url}"/>
                <!--数据库用户名-->
                <property name="username" value="${username}"/>
                <!--数据库密码-->
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--自定义的映射文件-->
    <mappers>
        <!--resource 引入的Mapper映射文件的路径,类路径的资源路径-->
        <mapper resource="mapper/UserMapper.xml"></mapper>
        <mapper resource="mapper/UserMapper1.xml"></mapper>
    </mappers>
</configuration>

每一个在包 com.tjetc.entity 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 com.tjetc.entit.User 的别名为 user;若有注解,则别名为其注解值 ,例如

//@Alias("user1111")  注解也可以使用配置别名, 并且优先起作用
public class User {
    ……
}

下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

typeHandlers

无论是mybatis设置一个参数给PreparedStatement,还是从PreparedStatement中返回ResultSet,都要面临一个问题:Java类型与JDBC类型之间的转换。

Java类型面向的是内存,JDBC类型面向的是各种关系型数据库,因此两者有很大的不同。

数据类型映射,是ORM框架中最关键的问题。

自定义类型映射器

你可以重写类型映射器,也可以创建自己的非标准类型映射器。

需要实现org.apache.ibatis.type.TypeHandler接口,或继承类org.apache.ibatis.type.BaseTypeHandler

<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

objectFactory配置

当mybatis每次创建一个新的结果集对象时,都需要使用objectFactory实例。

如果希望重写默认ObjectFactory的行为,可以自定义对象工厂

environments配置

1、mybatis允许你同时配置多个environments。如开发、测试、生产,可以同时配置三个环境。还可以同时对多个不同类型的数据库操作。

注意:虽然你可以同时配置多个环境,但是对于一个SqlSessionFactory实例,只能选择一个环境使用。因此,如果你想同时连接两个数据库,必须要创建两个SqlSessionFactory。

2、transactionManager配置

这里有两种事务管理类型可选,type=[JDBC | MANAGED]

JDBC:依赖于从dataSource返回的Connection对象,直接使用JDBC管理事务

MANAGED:由JavaEE容器管理整个事务

注意:如果使用Spring整合mybatis,无需配置TransactionManager,因为Spring会用自己的事务环境重写mybatis的配置

3、dataSource配置

使用标准数据源接口javax.sql.DataSource配置数据库的JDBC连接

这里有三种数据源类型可选:type="[UNPOOLED | POOLED | JNDI]")

  • UNPOOLED数据源

        这个数据源的实现会每次请求时打开和关闭连接。虽然有点慢,但对那些数据库连接可用性要求不高的简单应用程序来说,是一个很好的选择。 性能表现则依赖于使用的数据库,对某些数据库来说,使用连接池并不重要,这个配置就很适合这种情形

  • POOLED

    采用数据库连接池配置,可以优化性能,是当前web项目配置首选。

  • JNDI

    这个数据源实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的数据源引用

databaseIdProvider配置

DatabaseIdProvider元素主要是为了支持不同厂商的数据库,即同时支持多个数据库

这个配置非常有用,项目如何同时支持多种数据库?

传统做法是生成多套mapper文件,在mybatis.xml中配置使用那套映射文件。这个做法的很大缺陷是:多套映射文件中,会有很多接口的实现是相同的,如果代码修改,需要同时修改多套文件。这给开发额外增加了很大的工作量。

MyBatis 工作原理

1、SqlSession与Connection

DefaultSqlSession是SqlSession接口的实现类

BaseExcecutor中封装了对数据库Connection的管理

数据库的Connection从dataSource中获取,并用Transaction包装

2、SqlSession的getMapper

调用session.getMapper(),输入映射接口,返回接口的实现对象

UserMapper mapper = session.getMapper(UserMapper.class);

调用MapperRegistry的getMapper()方法

断点观察SqlSession-->>configuration -->>mappedStatements(映射文件中的sql读取后,都存于此处)

使用JDK的动态代理类Proxy,根据映射接口,创建动态代理对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值