欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MyBatis的基础学习

程序员文章站 2022-05-03 09:15:59
...

MyBatis简介

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

环境搭建

导入jar包

MyBatis的基础学习

导入MyBatis的jar包和MySQL的驱动包
其中
MyBatis的基础学习
其中这是核心包
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">
    <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.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来创建工厂而不直接创建工厂呢?
因为直接创建太过繁琐
MyBatis的基础学习
SqlSessionFactory是一个接口,所以实例化时需要创建其实现类DefaultSqlSessionFactory,但是DefaultSqlSessionFactory的构造方法需要传入Configuration对象。对于Configuration对象并不好创建
所以使用SqlSessionFactoryBuilder的build()方法来创建

进入build的源码可以看出其内部原理
MyBatis的基础学习
MyBatis的基础学习
在其内部是使用的XMLConfigBuilder来解析配置文件
然后调用XMLConfigBuilder的parse方法来为build方法传参MyBatis的基础学习
而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对象
MyBatis的基础学习
这也可以验证autoCommit默认是false
MyBatis的基础学习
在openSession()方法中可以看出
1.Transaction 是事务类
2.TransactionFactory 事务工厂 ,负责生产 Transaction
3.Executor MyBatis 执行器
作用:负责执行 SQL 命令 ,相当于 JDBC 中 statement 对象(或 PreparedStatement 或 CallableStatement)
默认的执行器 SimpleExcutor 批量操作 BatchExcutor

通过 openSession(ExecutorType type)控制
ExecutorType是一个枚举类型
MyBatis的基础学习

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.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.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.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.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.selectByName",u);
System.out.println(u);

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

#{} 和 ${} 的区别

#{} 获取参数的内容支持 索引获取,param1 获取指定位置参数, 并且 SQL 使用?占位符
MyBatis的基础学习
在日志打印中可以看出 #{}使用的是占位符

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

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

MyBatis的基础学习
可以看出未使用?占位符
使用的是字符串拼接

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

因为username是一个字符串类型,所以在拼接的时候要在${}前后加单引号
如果不加就报错了
MyBatis的基础学习

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.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.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.delete",user);
        sqlSession.commit();
        if(index>0)
            System.out.println("成功");
        else
            System.out.println("失败");
相关标签: JavaEE