MyBatis的基础学习

MyBatis简介

. Mybatis 开源免费框架,是数据库访问层的框架,底层是对JDBC的封装
在使用MyBatis时不需要编写实现类,只需要写写sql命令。这是MyBatis的一个优点

环境搭建

导入jar包

在这里插入图片描述

导入MyBatis的jar包和MySQL的驱动包
其中
在这里插入图片描述
其中这是核心包
asm为Cglib的依赖包
cglib为动态代理包
commons-loggiing为日志包
javaassist为字节码解析包,也是cglib依赖的包
log4j都为日志包
slf4j也为日志包

建立配置文件

1.首先在src下建立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>
    <environments default="default">
    <!--defaulty引用environment的id,表示当前所使用的环境-->
        <environment id="default">
        	<!--使用JDBC原生事务-->
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOlED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db_contracts?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>  <!--于之后的建立的mapper映射文件建立联系-->
        <mapper resource="cn/com/mapper/UserMapper.xml" />
    </mappers>
</configuration>

2.新建映射文件

<?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="cn.com.mapper.UserMapper">
    <select id="selectAll" resultType="cn.com.pojo.User">
        select * from user
    </select>
</mapper>

可以将namespace理解为全路径(包名+类名)
将id理解为方法名
resultType为返回值类型
如果方法返回值是 list,在 resultType 中写 List 的泛型, 因为 mybatis 对 jdbc 封装,一行一行读取数据

3.调用获取结果

package cn.com.test;



import cn.com.pojo.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 java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Test {
    public static void main(String[] args) throws IOException {
        //获取流数据
        InputStream is= Resources.getResourceAsStream("MyBatis.xml");
        //创建工厂
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
        //生产SqlSession
        SqlSession sqlSession=factory.openSession();
        //查询结果
        List<User> list=sqlSession.selectList("cn.com.mapper.UserMapper.selectAll");  //使用namespace的路径+mapper标签的id

        for (User u:list){
            System.out.println(u);
        }
    }
}

解析配置文件

在全局配置文件MyBatis.xml中

<transcationManager>标签中Type属性可取值为
 1:JDBC,表示事务管理使用JDBC原生事物管理方式
 2:MANAGED,表示事务管理转交给其他容器。原生JDBC事务的setAutoMapping(false)

<dataSouce>标签中Type属性
1:POOLED 使用数据库连接池
2.:UNPOOLED 不使用数据库连接池,和原生JDBC一样
3:JNDI java命名目录接口技术

MyBatise原理

获取SqlSession原理

       InputStream is= Resources.getResourceAsStream("MyBatis.xml");
        //创建工厂
        SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(is);
        //生产SqlSession
        SqlSession sqlSession=factory.openSession();

这是创建SqlSession的步骤,为什么要使用SqlSessionFactoryBuilder来创建工厂而不直接创建工厂呢?
因为直接创建太过繁琐
在这里插入图片描述
SqlSessionFactory是一个接口,所以实例化时需要创建其实现类DefaultSqlSessionFactory,但是DefaultSqlSessionFactory的构造方法需要传入Configuration对象。对于Configuration对象并不好创建
所以使用SqlSessionFactoryBuilder的build()方法来创建

进入build的源码可以看出其内部原理
在这里插入图片描述
在这里插入图片描述
在其内部是使用的XMLConfigBuilder来解析配置文件
然后调用XMLConfigBuilder的parse方法来为build方法传参在这里插入图片描述
而build的参数是Configuration对象所以 可以等效为

        InputStream is= Resources.getResourceAsStream("MyBatis.xml");
        //获取解析器
        XMLConfigBuilder parse=new XMLConfigBuilder(is,null,null);
        //获取Configuration对象
        Configuration configuration = parse.parse();
        //获取SqlSessionFactory工厂
        SqlSessionFactory factory=new DefaultSqlSessionFactory(configuration);
        //生产SqlSession
        SqlSession sqlSession=factory.openSession();

可以比较出SqlSessionFactoryBuilder创建更为简便

openSession

DefaultSqlSessionFactory的openSession中是如何创建session对象
在这里插入图片描述
这也可以验证autoCommit默认是false
在这里插入图片描述
在openSession()方法中可以看出
1.Transaction 是事务类
2.TransactionFactory 事务工厂 ,负责生产 Transaction
3.Executor MyBatis 执行器
作用:负责执行 SQL 命令 ,相当于 JDBC 中 statement 对象(或 PreparedStatement 或 CallableStatement)
默认的执行器 SimpleExcutor 批量操作 BatchExcutor

通过 openSession(ExecutorType type)控制
ExecutorType是一个枚举类型
在这里插入图片描述

4.DefaultSqlSession 是 SqlSession 接口的实现类

流程

1.MyBatis运行时,先通过Resources加载全局配置文件
2.通过SqlSessionFactoryBuilder构建器创建SqlSessionFactory
其内部实现了创建了SqlSessionFactory接口的实现类DefaultSqlSessionFactory
在创建DefaultSqlSessionFactory之前,需要先创建XmlConfigBuilder解析xml文件,并将解析结果存放在Configuration对象中,之后把Configuration传递给DefaultSqlSessionFactory对象
从而创建了SqlSessionFactory工厂
3.每次创建session对象时,都需要TransactionFactory 创建 Transaction 对象,同时还需要创建 SqlSession 的执行器 Excutor,最后实例化 DefaultSqlSession,传递给 SqlSession 接口
4.调用SqlSession的方法执行增删改查功能

查询方式

selectList()

selectList返回值为List<resultType属性>

  SqlSession sqlSession=factory.openSession();
  List<User> list=sqlSession.selectList("cn.com.mapper.UserMapper.selectAll");

        for (User u:list){
            System.out.println(u);
        }

selectOne()

selectOne返回值为Object

<select id="selectCount" resultType="int">
		select count(*) from user
</select>
int count=sqlSession.selectOne("cn.com.mapper.UserMapper.selectCount");        System.out.println(count);

selectMap()

selectMap() 返回值 Map
适用于需要在查询结果中通过某列的值取到这行数据的需求.

 <select id="selectMap" resultType="cn.com.pojo.User">
		select username,password from user
	</select>
 Map<Object,Object> map=sqlSession.selectMap("cn.com.mapper.UserMapper.selectMap","username");
 System.out.println(map.get("reverie"));

在user表中有username和password两个列
所以selectMap的第二个参数为所需要映射的列名
则map中的key为第二参数指定列中的数据,value为resultType所指定的数据

parameterType 属性

在 XXXMapper.xml 中等标签的 parameterType 可以 控制参数类型
.SqlSession 的 selectList()和 selectOne()的第二个参数和 selectMap() 的第三个参数都表示方法的参数.

<select id="selectByName" resultType="cn.com.pojo.User" parameterType="string">
        select * from user where username=#{param1}
</select>
  User user=sqlSession.selectOne("cn.com.mapper.UserMapper.selectByName","reverie");
  System.out.println(user);

parameterType 控制参数类型

1. #{}获取参数内容
使用索引,从 0 开始 #{0}表示第一个参数

也可以使用#{param1}第一个参数

如果只有一个参数(基本数据类型或 String),mybatis对#{}里面内容没有要求只要写内容即可,

<select id="selectByName" resultType="cn.com.pojo.User" parameterType="string">
        select * from user where username=#{acascasc}   
</select>

只有一个参数,所以#{}中的内容可以乱写

2.参数是对象

<select id="selectByName" resultType="cn.com.pojo.User" parameterType="cn.com.pojo.User">
        select * from user where username=#{username}
</select>
User u=new User();
u.setUsername("reverie");
u=sqlSession.selectOne("cn.com.mapper.UserMapper.selectByName",u);
System.out.println(u);

如果参数是对象#{属性名}
如果参数是 map 写成#{key}

#{} 和 ${} 的区别

#{} 获取参数的内容支持 索引获取,param1 获取指定位置参数, 并且 SQL 使用?占位符
在这里插入图片描述
在日志打印中可以看出 #{}使用的是占位符

$ {} 使用的是字符串拼接方式,而不使用?占位符,默认找${内容}内容的 get/set 方法,如果写数字,就是一个数字

<select id="selectByName" resultType="cn.com.pojo.User" parameterType="cn.com.pojo.User">
        select * from user where username='${username}'
</select>

在这里插入图片描述
可以看出未使用?占位符
使用的是字符串拼接

 <select id="selectByName" resultType="cn.com.pojo.User" parameterType="cn.com.pojo.User">
        select * from user where username=${username}
    </select>

因为username是一个字符串类型,所以在拼接的时候要在${}前后加单引号
如果不加就报错了
在这里插入图片描述

typeAliases 别名

<select id="selectByName" resultType="cn.com.pojo.User" parameterType="cn.com.pojo.User">
        select * from user where username=#{username}
</select>

在resultType属性和parameterType中时用的是全路径名称(包名+类名)
其实可以使用别名的方式简化别名

类别名

给某个类起别名

<?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>
    <!--添加别名-->
    <typeAliases>
        <typeAlias type="cn.com.pojo.User" alias="u" />
    </typeAliases>
    
    <environments default="default">
        <environment id="default">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOlED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db_contracts?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="cn/com/mapper/UserMapper.xml" />
    </mappers>
</configuration>
 <select id="selectByName" resultType="u" parameterType="u">
        select * from user where username=#{username}
 </select>

定义别名后可以在resultType和parameterType中使用别名

 User u=new User();
 u.setUsername("reverie");
 u=sqlSession.selectOne("cn.com.mapper.selectByName",u);
 System.out.println(u);

包别名

.直接给某个包下所有类起别名,别名为类名,不区分大小写

<typeAliases>
    <package name="cn.com.pojo"/>
</typeAliases>
 <select id="selectByName" resultType="user" parameterType="user">
        select * from user where username=#{username}
 </select>

MyBatis的增删改

在 mybatis 中默认是关闭了JDBC 的自动提交功能
每一个 SqlSession 默认都是不自动提交事务. 所以使用session.commit()提交事务.

构造SqlSession可以使用openSession(true)设置自动提交,相当于JDBC的setAutoCommit(true);

mybatis 中<insert> <delete> <update>标签没有 resultType 属性,返回值都是int

增加数据

<insert id="ins" parameterType="User"> 
   insert into people values(#{username},#{password}) 
</insert>
        User user=new User();
        user.setUsername("kryie");
        user.setPassword("123");
        int index=sqlSession.insert("cn.com.mapper.UserMapper.ins",user);
        sqlSession.commit();
        if(index>0)
            System.out.println("成功");
        else
            System.out.println("失败");

修改数据

 <update id="update" parameterType="User">
        update user set password=#{password} where username=#{username}
 </update>
        User user=new User();
        user.setUsername("kryie");
        user.setPassword("123456");
        int index=sqlSession.update("cn.com.mapper.UserMapper.update",user);
        sqlSession.commit();
        if(index>0)
            System.out.println("成功");
        else
            System.out.println("失败");

删除数据

<delete id="delete" parameterType="User">
        delete from user where username=#{username}
</delete>
        User user=new User();
        user.setUsername("kryie");
        user.setPassword("123456");
        int index=sqlSession.delete("cn.com.mapper.UserMapper.delete",user);
        sqlSession.commit();
        if(index>0)
            System.out.println("成功");
        else
            System.out.println("失败");

MyBatis缓存

应用程序和数据库之间的数据交互是一个好耗时的过程
类似于计算机中的缓存,在MyBatsi中是有缓存的。从而减少了对数据库的访问

在MyBatis中是默认开启缓存的

同一个SqlSession对象在调用同一个<select>时,在第一次访问时,会将查询结果存放在缓存中,下一次再访问这个<select>时会从缓存中拿

1.缓存

public static void main(String[] args) throws IOException {
        InputStream is= Resources.getResourceAsStream("MyBatis.xml");
        SqlSessionFactory factory= new SqlSessionFactoryBuilder().build(is);
        //生产SqlSession
        SqlSession sqlSession=factory.openSession();

        sqlSession.selectList("cn.com.mapper.UserMapper.selectAll");
        sqlSession.selectList("cn.com.mapper.UserMapper.selectAll");
    }

在这里插入图片描述
可以看出只查询了一次,因为第二次是直接从缓存中拿的

2.测试范围

        SqlSession sqlSession=factory.openSession();
        SqlSession sqlSession2=factory.openSession();
        sqlSession.selectList("cn.com.mapper.UserMapper.selectAll");
        sqlSession2.selectList("cn.com.mapper.UserMapper.selectAll");

现在使用两个SqlSession去调用同一个select
在这里插入图片描述
可以看出执行了两次

这是因为缓存的有效范围是同一个SqlSession对象

3.缓存对象
在MyBatis中,缓存的是statement对象,
一个select对应一个statement对象在这里插入图片描述
查看源码可以看出一个selct对应一个statement对象

每次执行select的流程
1.先在缓存区中找是否存在相应的statement对象 ,如果存在则返回结果
2.如果不存则去数据库获取数据
3.从数据库返回查询结果
4.把查询结果放到对应的缓存区中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值